首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

ES6 Class Methods 定义方式的差异

引言

在 JavaScript 中有两条不成文的说法:

一切皆对象

函数是一等公民

因而函数不仅是一等公民,也是具有属性的特殊对象。这一点,也可以从原型链上得到佐证:

函数是继承自 的,因而函数也具备 、 等方法。因为函数是对象,所以在 ES6 之前,JavaScript 中的 OOP 编程则纯粹是基于函数的,直到 ES6 提供了 、 以及 等关键字,不仅精简了语法,也使得 OOP 的编程形式逐渐趋近于 Java/C++ 等语言。

class 的背后

ES6 虽然提供了 等关键字,但只是语法糖,JavaScript 的 OOP 编程仍然是基于函数的,继承则是基于原型的。

看一个示例:

上述代码经过 babel 转换之后:

可以看到,转换后的 class A 就是一个函数,所以理论上就可以把 A 当作函数调用,但 的作用就是禁止将类作为函数调用:

然后看下 都做了什么:

通过上述代码可知, 的功能主要是通过 定义了类的普通属性和静态属性。需要注意的是普通属性是定义在了类的原型对象上,静态属性是定义在了类本身上

所以,类 A 的定义就等同于如下代码:

两种定义 Methods 的方式

ES6 中有两种常见的定义 Methods 的方式:

咋一看,二者没什么区别。方式一是常规方式,方式二是通过箭头函数来定义方法,如果你写过 React 应用,应该接触过这种方式。

区别1:this 的绑定

在箭头函数出现之前,每个新定义的函数都有它自己的 值,但箭头函数不会创建自己的 ,它从会从自己的作用域链的上一层继承 。举个粟子:

当点击 元素时,会触发 ,该方法会输出当前的 ,而(严格模式下)此时输出的 值是 ,显然这不是我们要的结果。怎么修改呢?这里至少有三种修改方式,其中之一就是通过箭头函数来定义方式。

区别2:继承

先看方式一的继承:

对于上述结果的输出应该没有什么疑问,这是符合我们预期的。然后看下另一段代码:

上述的输出会是什么呢?按照常规思路,应该是先输出 ,再输出 ,但其实不是的。

上文有提到,类的继承依然是基于原型的。上文也分析过 babel 转换过的代码,常规的写法中,类的非静态属性都是定义在类的原型对象上,而不是类的实例上的。但箭头函数不一样,通过箭头函数定义的方法时绑定在 上,而 是指向当前创建的类实例对象,而不是类的原型对象。可以查看类 B 转换后的代码:

可以看到, 方法是定义在 上的,而不是定义在 上。

类 继承 ,不仅会继承类 原型上的属性和方法,也会继承其实例上的属性和方法。那么,此时类 等效的伪代码如下:

综上,当 执行时,只会输出 ,而不会输出 。

因为当访问一个对象实例的属性时,会先在实例上进行查找,如果没有,则顺着原型链往上查找,直到原型链的顶端。若在实例上查找到对应属性,则会返回,停止查找。即使原型上定义了同一个属性,该属性也不会被访问到,这种情况称为"属性遮蔽 (property shadowing)"。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180530G00P1R00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券