• 中美研究人员发现新型狗流感病毒 2019-05-29
  • 豫园商城升级改造:这些楼顶可见最好的风景--旅游频道 2019-05-14
  • 头条 —频道 春城壹网 七彩云南 一网天下 2019-05-14
  • 人为某种意识而奋斗是幸福的,获得成绩或成就更幸福。 2019-05-10
  • 【专题】省违反中央八项规定精神和“四风”问题线索举报平台 2019-05-09
  • 确定这是热身赛?吴前拼到大腿抽筋 拆绷带继续干 2019-05-09
  • 应对排放新规 大众德国工厂计划短暂停产 2019-04-26
  • 一师一团土地确权登记颁证工作全面展开 2019-04-26
  • 一语惊坛(5月31日):“我们不一样”,中国向世界许下一个承诺。 2019-04-22
  • 俄罗斯世界杯F组:球迷风采 2019-04-10
  • 5月份国民经济数据发布:中国经济持续稳中向好 2019-04-10
  • 贵州宣讲十九大:干部争当宣讲员 群众心窝暖洋洋 2019-03-25
  • 别空谈,说说看,这个“简单的逻辑关系”是什么关系? 2019-03-25
  • 快过闪电,MIUI 10与MIUI 9速度对比 2019-03-21
  • 泽州去年“免费教育”资金达5211万元 2019-03-19
  • JavaScript 新语法详解:Class 的私有属性与私有方法

    快乐彩开奖号码 www.752o.com 译者按: 为什么偏要用 # 符号?

    本文采用意译,版权归原作者所有

    proposal-class-fieldsproposal-private-methods定义了 Class 的私有属性以及私有方法,这 2 个提案已经处于 Stage 3,这就意味着它们已经基本确定下来了,等待被加入到新的 ECMAScript 版本中。事实上,最新的 Chrome 已经支持了 Class 私有属性。

    那么,对于 Class 的私有属性与私有方法,它们究竟是什么呢?它们是怎样工作的?为什么要使用#符号来定义呢?

    Class 的私有属性语法如下:

    class Point {
        #x;
        #y;
    
        constructor(x, y) {
            this.#x = x;
            this.#y = y;
        }
    
        equals(point) {
            return this.#x === point.#x && this.#y === point.#y;
        }
    }

    我们可以将其语法理解为 2 个部分:

    • 定义 Class 私有属性
    • 引用 Class 私有属性

    定义 Class 私有属性

    私有属性与公共属性的定义方式几乎是一样的,只是需要在属性名称前面添加#符号:

    class Foo {
        publicFieldName = 1;
        #privateFieldName = 2;
    }

    定义私有属性的时候也可以不用赋值:

    class Foo {
        #privateFieldName;
    }

    引用 Class 私有属性

    引用私有属性也只需要使用#就好了。

    class Foo {
        publicFieldName = 1;
        #privateFieldName = 2;
        add() {
            return this.publicFieldName + this.#privateFieldName;
        }
    }

    其中,this.#可以简化,去掉 this 也没问题,下面两种写法是等价的:

    method() {
      #privateFieldName;
    }
    method() {
      this.#privateFieldName;
    }

    在 Class 定义中引用 Class 实例的私有属性

    对于私有属性,我们是不可以直接通过 Class 实例来引用的,这也是私有属性的本来含义。但是有一种情况除外,在 Class 定义中,我们可以引用 Class 实例的私有属性:

    class Foo {
        #privateValue = 42;
        static getPrivateValue(foo) {
            return foo.#privateValue;
        }
    }
    
    Foo.getPrivateValue(new Foo()); // >> 42

    其中,fooFoo的实例,在 Class 定义中,我们可以通过 foo 来引用私有属性#privateValue。

    Class 的私有方法

    Class 的私有属性是提案proposal-class-fields的一部分,这个提案只关注 Class 的属性,它并没有对 Class 的方法进行任何修改。而 Class 的私有方法是提案proposal-class-fields的一部分。

    Class 的私有方法语法如下:

    class Foo {
        constructor() {
            this.#method();
        }
        #method() {
            // ...
        }
    }

    我们也可以将函数赋值给私有属性:

    class Foo {
        constructor() {
            this.#method();
        }
    
        #method = () => {
            // ...
        };
    }

    封装(隐藏)私有属性

    我们不能直接通过 Class 实例引用私有属性,我们只能在 Class 定义中引用它们:

    class Foo {
      #bar;
      method() {
        this.#bar; // Works
      }
    }
    let foo = new Foo();
    foo.#bar; // Invalid!

    另外,要做到真正的私有的话,我们应该无法检测这个私有属性是否存在,因此,我们需要允许定义同名的公共属性:

    class Foo {
        bar = 1; // public bar
        #bar = 2; // private bar
    }

    如果我们不允许公共属性与私有属性同名,我们则可以通过给同名的公共属性复制监测该私有属性是否存在:

    foo.bar = 1; // Error: `bar` is private! (报错,说明私有属性存在)

    不报错也行:

    foo.bar = 1;
    foo.bar; // `undefined` (赋值失败,说明私有属性存在)

    对于 subclass 应该同样如此,它也允许公共属性与私有属性同名:

    class Foo {
        #fieldName = 1;
    }
    
    class Bar extends Foo {
        fieldName = 2; // Works!
    }

    关于 Class 私有属性的封装,可以参考Why is encapsulation a goal of this proposal?。

    为什么使用#符号?

    很多人都有一个疑问,为什么 JS 不能学习其他语言,使用private来定义私有属性和私有方法?为什么要使用奇怪的#符号?

    使用 private 的话,代码要舒服很多:

    class Foo {
      private value;
    
      equals(foo) {
        return this.value === foo.value;
      }
    }

    为什么不使用 private 来定义私有属性?

    很多语言使用 private 来定义私用属性,如下:

    class EnterpriseFoo {
      public bar;
      private baz;
      method() {
        this.bar;
        this.baz;
      }
    }

    对于这些语言属性,私用属性和公共属性的引用方式是相同的,因此他们可以使用 private 来定义私有属性。

    但是,对于 JavaScript 来说,我们不能使用 this.field 来引用私有属性(我接下来会解释原因),我们需要在语法层面上区分私有属性和公共属性。在定义和引用私有属性的时候,使用#符号,私有属性与公共属性可以很好地区分开来。

    为什么引用私有属性的时候需要#符号?

    引用私有属性的时候,我们需要this.#field,而不是this.field,原因如下:

    • 因为我们需要封装私有属性,我们需要允许公共属性与私有属性同名,因此私有属性与公共属性的引用方式必须不一样。这一点我们在前文已经详述。
    • 公共属性可以通过this.field以及this['field']来引用,但是私有属性不能支持this['field']这种方式,否则会破坏私有属性的隐私性,示例如下:
    class Dict extends null {
        #data = something_secret;
        add(key, value) {
            this[key] = value;
        }
        get(key) {
            return this[key];
        }
    }
    
    new Dict().get("#data"); // 返回私有属性

    因此,私有属性与公共属性的引用方式必须不一样,否则会破坏this['field']语法。

    • 私有属性与公共属性的引用方式一样的话,会导致我们每次都需要去检查属性是公共的还是私有的,这会造成严重的性能问题。

    这篇文章遵循Creative Commons Attribution 4.0 International License。

    参考

    关于Fundebug

    Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了10亿+错误事件,付费客户有Google、360、金山软件、百姓网等众多品牌企业?;队蠹?a >免费试用!

    版权声明

    转载时请注明作者Fundebug以及本文地址:
    [https://blog.fundebug.com/2019/04/23/javascript-class-private-field-and-private-method/

    posted @ 2019-04-23 09:57 Fundebug 阅读(...) 评论(...) 编辑 收藏
  • 中美研究人员发现新型狗流感病毒 2019-05-29
  • 豫园商城升级改造:这些楼顶可见最好的风景--旅游频道 2019-05-14
  • 头条 —频道 春城壹网 七彩云南 一网天下 2019-05-14
  • 人为某种意识而奋斗是幸福的,获得成绩或成就更幸福。 2019-05-10
  • 【专题】省违反中央八项规定精神和“四风”问题线索举报平台 2019-05-09
  • 确定这是热身赛?吴前拼到大腿抽筋 拆绷带继续干 2019-05-09
  • 应对排放新规 大众德国工厂计划短暂停产 2019-04-26
  • 一师一团土地确权登记颁证工作全面展开 2019-04-26
  • 一语惊坛(5月31日):“我们不一样”,中国向世界许下一个承诺。 2019-04-22
  • 俄罗斯世界杯F组:球迷风采 2019-04-10
  • 5月份国民经济数据发布:中国经济持续稳中向好 2019-04-10
  • 贵州宣讲十九大:干部争当宣讲员 群众心窝暖洋洋 2019-03-25
  • 别空谈,说说看,这个“简单的逻辑关系”是什么关系? 2019-03-25
  • 快过闪电,MIUI 10与MIUI 9速度对比 2019-03-21
  • 泽州去年“免费教育”资金达5211万元 2019-03-19
  • 欢乐斗地主怎么得经验 香港六合彩惠泽设群 剑网3指尖江湖茶叶刷新 英魂之刃腾讯版下载 七星彩查询 进击的猿人试玩 大乐透官方网址 广西快3升级版下载说明 河南十一选五最新开奖结果 fifa手游 如何卖球员 欢乐球吃球攻略在哪里 澳洲幸运8开奖时间 金鱼花怎样种植 30选5开奖结果查询结果 体彩天津11选5开奖结果查询结果 网易七乐彩走势图表