为什么ES6类中不支持本地函数?

3
“在ES6中为什么要省略像这样的内容?”
class Foo {
   myMethod(){
      // do something with 'bar'
   }
   constructor(){
       this.myMethod();
   }
   otherMethod(){
       this.myMethod();
   }
}

我知道在构造函数中定义函数,或者在类外部定义函数然后使用 myMethod() 是可行的。然而,作为其他语言的用户,我惊讶地发现有类,但没有本地(或私有)方法。我在互联网上找不到这个被省略的原因。


3
如果你来自其他编程语言,你可能会惊讶地发现EcmaScript并没有类。如果是这样的话,你应该了解一下原型(prototypes)的概念。ES6中的类大部分只是一些语法糖。 - speg
3
JavaScript没有私有属性和方法,而类语法只是原型继承的简化语法糖。 - gcampbell
你可以使用TypeScript,它有私有和受保护的属性(只是编译时检查)。 - gcampbell
1
这是由于JS的基于引用的安全模型:没有函数所有权,因为一切都是动态的(并且可以调用/应用/绑定)。因此,保密的唯一方法是隐藏引用,如果这些引用在类中,则任何人都可以访问它们。添加传统私有变量需要添加大量的调用时间检查;这很慢,而且不需要,因为受保护的方法/获取器/设置器可以提供隐私。 - dandavis
在ES6中省略这样的东西” - 比如什么?你给出的例子可以运行。你的意思是什么?“bar”是什么意思? - Bergi
显示剩余3条评论
1个回答

1

编辑: 我刚意识到你的帖子是关于函数而不是变量。由于函数是一种变量类型,因此即使我没有明确地将示例制作为函数,所有这些解决方案都适用于函数。


我已经找到了几种解决方案,每种方法都有其优缺点:

方法0:工厂模式

var Foo = (function() {
  let priv = {
    "eh": 0
  };
  return class Foo {
    constructor(num) {
      priv.eh = num;
    }
    test() {
      return priv.eh;
    }
  };
})();

var a = new Foo(383);

console.log(a.test());

利用JS作用域将变量“priv”隐藏在函数后面
优点: - 完全安全。除非返回指针,否则基本上无法访问priv - 利用了广泛使用的JavaScript范例。工厂一直被程序员使用多年 - 私有变量不会与父类冲突
缺点: - 不是很清晰或易读
方法一:从构造函数中定义所有内容
class Foo2 {
  constructor(num) {
    Object.assign(this, {
      test() {
        return num;
      }
    });
  }
}

var b = new Foo2(262);

console.log(b.test());

正如盒子上所说的那样。

优点:

  • 绝对安全。无法从作用域外访问局部变量
  • 比方法1更易读懂一些。很容易理解每个部分的作用
  • 私有变量不会与父类冲突

缺点:

  • 构造函数变得混乱
  • 仍然不够易读

方法二:命名约定
class Foo3 {
  constructor(num) {
    this._eh = num;
  }
  test() {
    return this._eh;
  }
}

var c = new Foo3(101);

console.log(c.test());

不需要隐藏在奇怪的安全程序背后。只需在名称中指定哪些属性是“私有”的即可。
优点: - 非常易读,可以利用类结构
缺点: - 完全没有保护作用,只是一种建议。 - 私有变量与父类的私有变量冲突。
方法三:符号。
const eh = Symbol("eh");

class Foo4 {
  constructor(num) {
    this[eh] = num;
  }
  test() {
    return this[eh];
  }
}

var d = new Foo4(100);

console.log(d.test());

我只是想包含这个,因为我觉得很酷

优点:

  • 作为命名约定易读。私有变量不使用字符串,而是使用符号。非常容易阅读。

缺点:

  • 无意义。在任何父级作用域受保护的情况下,您可以将私有变量存储在那里。
    • 不安全。即使您解决了上述问题,人们仍然可以使用Reflect.ownKeys()访问所有键(包括符号)。

希望这对您有所帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接