前端JavaScript基础训练系列八十三:class陷阱

然而,class 语法并没有解决所有的问题,在 JavaScript 中使用“类”设计模式仍然存在许
多深层问题。
首先,你可能会认为 ES6 的 class 语法是向 JavaScript 中引入了一种新的“类”机制,其
实不是这样。class 基本上只是现有 [Prototype]机制的一种语法糖。
也就是说,class 并不会像传统面向类的语言一样在声明时静态复制所有行为。如果你 (有意或无意)修改或者替换了父“类”中的一个方法,那子“类”和所有实例都会受到
影响,因为它们在定义时并没有进行复制,只是使用基于 [[Prototype]] 的实时委托:

class C { constructor() {
this.num = Math.random(); }
          rand() {
              console.log( "Random: " + this.num );
} }
var c1 = new C();
c1.rand(); // "Random: 0.4324299..."
C.prototype.rand = function() {
console.log( "Random: " + Math.round( this.num * 1000 ));
};
var c2 = new C(); c2.rand(); // "Random: 867"
c1.rand(); // "Random: 432" ——噢! 如果你已经明白委托的原理所以并不会期望得到“类”的副本的话,那这种行为才看起来

比较合理。所以你需要问自己:为什么要使用本质上不是类的 class 语法呢?
ES6 中的 class 语法不是会让传统类和委托对象之间的区别更加难以发现和理解吗?
class 语法无法定义类成员属性(只能定义方法),如果为了跟踪实例之间共享状态必须要 这么做,那你只能使用丑陋的 .prototype 语法,像这样:

class C { constructor() {
// 确保修改的是共享状态而不是在实例上创建一个屏蔽属性! C.prototype.count++;
// this.count 可以通过委托实现我们想要的功能
console.log( "Hello: " + this.count ); }
  ES6中的Class | 191
}
// 直接向 prototype 对象上添加一个共享状态 C.prototype.count = 0;
var c1 = new C(); // Hello: 1
var c2 = new C(); // Hello: 2
      c1.count === 2; // true
      c1.count === c2.count; // true

这种方法最大的问题是,它违背了 class 语法的本意,在实现中暴露(泄露!) 了 .prototype。
如果使用 this.count++ 的话,我们会很惊讶地发现在对象 c1 和 c2 上都创建了 .count 属 性,而不是更新共享状态。class 没有办法解决这个问题,并且干脆就不提供相应的语法 支持,所以你根本就不应该这样做。
此外,class 语法仍然面临意外屏蔽的问题:

class C { constructor(id) {
// 噢,郁闷,我们的 id 属性屏蔽了 id() 方法
this.id = id; }
          id() {
              console.log( "Id: " + id );
} }
var c1 = new C( "c1" );
c1.id(); // TypeError -- c1.id 现在是字符串 "c1"

除此之外,super 也存在一些非常细微的问题。你可能认为 super 的绑定方法和 this 类似 (参见第 2 章),也就是说,无论目前的方法在原型链中处于什么位置,super 总会绑定到
链中的上一层。
然而,出于性能考虑(this 绑定已经是很大的开销了),super 并不是动态绑定的,它会在 声明时“静态”绑定。没什么大不了的,是吧?
呃…可能,可能不是这样。如果你和大多数 JavaScript 开发者一样,会用许多不同的方 法把函数应用在不同的(使用 class 定义的)对象上,那你可能不知道,每次执行这些操 作时都必须重新绑定 super。
此外,根据应用方式的不同,super 可能不会绑定到合适的对象(至少和你想的不一样),

所以你可能(写作本书时,TC39 正在讨论这个话题)需要用 toMethod(…) 来手动绑定 super(类似用 bind(…) 来绑定 this)。
你已经习惯了把方法应用到不同的对象上,从而可以自动利用 this 的隐式绑定规则)。但是这对于 super 来说是行不通的。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值