class A {
constructor(){
this.name = 1;
}
}
// 对应
var A = function A() {
this.name = 1;
};
constructor 的作用就是给实例对象添加属性。
声明方法
class A {
sayName(){
console.log(this.name)
}
}
// 对应
var A = /*#__PURE__*/function () {
function A() {}
var _proto = A.prototype;
_proto.sayName = function sayName() {
console.log(this.name);
};
return A;
}();
可以看到,当我们在 class 上声明一个方法,其实是将方法挂载到原型上。如果我们通过箭头函数的方式声明呢?
class A {
sayName = () => {}
}
// 对应
var A = function A() {
this.sayName = function () {};
};
其实是放到了实例上,初始化时进行赋值。
getter、setter
class A {
get age(){
return 27
}
}
// 对应
var A = /*#__PURE__*/ (function () {
function A() {}
const props = [
{
key: "age",
get: function get() {
return 27;
},
},
];
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(A.prototype, descriptor.key, descriptor);
}
return A;
})();
class A {
static sayName(){}
}
// 对应
var A = /*#__PURE__*/function () {
function A() {}
A.sayName = function sayName() {};
return A;
}();
继承
class B {}
class A extends B {}
// 对应
var A = /*#__PURE__*/ (function (_B) {
A.prototype = Object.create(_B.prototype);
A.prototype.constructor = A;
Object.setPrototypeOf(A, _B);
function A() {
var _this;
_this = _B.call(this) || this;
_this.name = 1;
return _this;
}
return A;
})(B);
只使用 extends,什么都不做的情况下,会:
将子类的 prototype 指向父类的 prototype。
子类的 prototype.constructor 指向自己。
子类的 proto 指向父类。
调用父类初始化子类 this。
super
class B {}
class A extends B{
constructor(){
super();
}
sayName(){
super.sayName()
}
static sayAge(){
super.sayAge();
}
}
// 对应
// 省略继承部分
function A() {
return _B.call(this) || this;
}
var _proto = A.prototype;
_proto.sayName = function sayName() {
_B.prototype.sayName.call(this);
};
A.sayAge = function sayAge() {
_B.sayAge.call(this);
};
前言
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。
今天就来看下隐藏在 Class 背后的技术点。本次解析基于 Babel LOOSE 模式。
constructor
constructor 的作用就是给实例对象添加属性。
声明方法
可以看到,当我们在 class 上声明一个方法,其实是将方法挂载到原型上。如果我们通过箭头函数的方式声明呢?
其实是放到了实例上,初始化时进行赋值。
getter、setter
可以看到,首先把 getter 函数转成一个 descriptor 对象,然后通过 Object.defineProperty 挂载到类的原型上,不能枚举。
静态方法
继承
只使用 extends,什么都不做的情况下,会:
super
可以看到不同阶段的 super 不一样:
总结
可以看出,其实 ES6 的实现和 ES5 中的寄生组合式继承差不多。