小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
最简单的类
class Person {
constructor(name) {
this.name = name
}
}
编译后
// 使用babel编译后的代码会自动开启严格模式
"use strict";
// 对Person函数的调用进行检测,阻止Perosn被像一个普通函数那样被调用
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Person = function Person(name) {
_classCallCheck(this, Person);
this.name = name;
};
添加属性
class Person {
// 实例属性
foo = 'foo';
// 静态属性
static bar = 'bar';
constructor(name) {
this.name = name;
}
}
编译后
"use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var Person = function Person(name) {
_classCallCheck(this, Person);
// 挂载实例属性
_defineProperty(this, "foo", "foo");
this.name = name;
};
// 挂载静态顺序
_defineProperty(Person, "bar", "bar");
使用访问器方法
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
return 'hello, I am ' + this.name;
}
static onlySayHello() {
return 'hello'
}
get name() {
return 'Klaus';
}
set name(newName) {
console.log('new name 为:' + newName)
}
}
编译后
"use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
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(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
var Person = /*#__PURE__*/ (function () {
function Person(name) {
_classCallCheck(this, Person);
this.name = name;
}
// 往构造函数上添加方法,并将挂载完方法的构造函数返回
// 参数1: 构造函数
// 参数2: 实例方法组成的数组
// 参数3; 静态方法组成的数组
_createClass(
Person,
[
{
key: "sayHello",
value: function sayHello() {
return "hello, I am " + this.name;
}
},
{
key: "name",
get: function get() {
return "Klaus";
},
set: function set(newName) {
console.log("new name 为:" + newName);
}
}
],
[
{
key: "onlySayHello",
value: function onlySayHello() {
return "hello";
}
}
]
);
return Person;
})();
实现继承
class Parent {
constructor(name) {
this.name = name
}
static staticMethod() {
console.log('staticMethod')
}
}
class Child extends Parent {
constructor(name, age) {
super(name)
this.age = age
}
}
const child = new Child('Klaus', '18')
Child.staticMethod()
类Parent是构造函数Parent形式的语法糖,所以函数Parent同时有 prototype 属性和 __proto__ 属性
所以Babel在实现继承的时候,存在两条继承链
Child.prototype === Parent---> 静态方法的继承Child.prototype.prototype === Parent.prototype---> 实例方法的继承
也就是说,ES6中实现的继承 = 寄生组合式继承 + Object.setPrototypeOf(Child, Parent)
上述代码经过编译后的代码中,babel使用了_inherits和 _possibleConstructorReturn这两个辅助函数来实现继承,
具体转换可以使用babel的try it out来进行测试
_inherits
function _inherits(subClass, superClass) {
// 类只能继承自函数或null
// 如果继承自函数,则该函数可以使用构造函数,也可以是普通函数
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function")
}
// 子类继承父类的实例方法
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: { value: subClass, writable: true, configurable: true }
})
if (superClass) _setPrototypeOf(subClass, superClass)
}
// Object.setPrototypeOf(Child, Parent)
// 子类继承父类静态方法
function _setPrototypeOf(o, p) {
_setPrototypeOf =
Object.setPrototypeOf ||
function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
_possibleConstructorReturn
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
// 返回的是一个函数
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
// self ==> 子类实例 call ==> 子类调用父类构造方法后的返回值
// 该方法的作用是
// + 如果父类的构造函数有返回值, 则返回构造函数中的返回值
// + 如果父类的构造函数返回undefined, 那么就返回self
function _possibleConstructorReturn(self, call) {
if (call && (_typeof(call) === "object" || typeof call === "function")) {
return call;
} else if (call !== void 0) {
// void 0 === undefined ---> true
throw new TypeError(
"Derived constructors may only return object or undefined"
);
}
return _assertThisInitialized(self);
}
function _assertThisInitialized(self) {
// 子组件实际返回的实例对象是通过父组件来进行创建的
// 所以如果没有在使用this之前调用super方法
// 子组件内部的self的值是undefined
if (self === void 0) {
throw new ReferenceError(
"this hasn't been initialised - super() hasn't been called"
);
}
return self;
}
// 实际调用
var _super = _createSuper(Child);
var _this;
// 执行super方法,返回的_this才是实际的子类实例
// 没有执行super方法的时候,_this的值是undefined
// 所以在子类中,在使用this之前,需要先手动调用super
_this = _super.call(this, name);
_this.age = age;
return _this;
_possibleConstructorReturn实际的功能如下:
- 在子类中,使用
this之前,必须调用super方法 - 如果父类的构造函数返回了对象或函数,就之前使用父类的返回值
class Parent {
constructor(name) {
this.name = name
}
}
class Child extends Parent {
constructor(name, age) {
super(name)
this.age = age
}
}
const child = new Child('Klaus', 23)
console.log(child) // => {name: 'Klaus', age: 23}
class Parent {
constructor(name) {
this.name = name
return {}
}
}
class Child extends Parent {
constructor(name, age) {
super(name)
this.age = age
}
}
const child = new Child('Klaus', 23)
console.log(child) // => { age: 23 }