概念
继承的目的使得子类具有父类的各种属性和方法, 实现继承的差异仅仅在于实现方法
ES6继承
### 语法
class Point { /* ... */ }
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 调用父类的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 调用父类的toString()
}
}
转译成es5
关注几个标注出的函数
"use strict";
//...
var Point = function Point() {
_classCallCheck(this, Point);
};
var ColorPoint = /*#__PURE__*/function (_Point) {
_inherits(ColorPoint, _Point);
var _super = _createSuper(ColorPoint);
function ColorPoint(x, y, color) {
var _this;
_classCallCheck(this, ColorPoint);
_this = _super.call(this, x, y); // 调用父类的constructor(x, y)
_this.color = color;
return _this;
}
_createClass(ColorPoint, [{
key: "toString",
value: function toString() {
return this.color + ' ' + _get(_getPrototypeOf(ColorPoint.prototype), "toString", this).call(this); // 调用父类的toString()
}
}]);
return ColorPoint;
}(Point);
下面5-8行就是原型式继承. 其中第七行修正了constructor
指向, 等价于subClass.prototype.constructor=subClass
.
function _inherits(subClass, superClass) {
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);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; };
return _setPrototypeOf(o, p);
}
Object.create
兼容方案
if(!Object.create) {
Object.create = function(obj) {
function fn() {}
fn.prototype = obj
return new fn()
}
}
super关键字
- In the constructor body of a derived class, the
super
appear as a function call, which must be called before thethis
kewword is used and before constructor returns. Thesuper()
call the parent class's constructor and binds the parent class's public fields. - call
super
on static methods
class A {
constructor() {
this.x = 1;
}
checkThis() {
console.log('no static', this)
}
static checkThis() {
console.log("static", this) //这里断点, 图见下方
console.log('static', this === A)
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
checkThis() {
super.checkThis()
}
}
let a = new A();
let b = new B();
a.checkThis(); //no static A { x: 1 }
b.checkThis(); //no static B { x: 2 }
A.checkThis(); //static [class A] static true
原型链继承
function parent() {
this.parent = '父类';
}
parent.prototype.parent_p = '父类原型对象的属性或者方法';
// 子类
function child() {
this.child = '子类';
}
// 核心步骤:重写子类的原型对象
child.prototype = new parent();
child.prototype.child_p = '子类原型对象的属性或者方法' // 子类的属性/方法声明在后面,避免被覆盖
// 实例化子类
const ins = new child();
console.log('子类的实例:', ins);
new做了什么
- 创建一个全新的对象。
- 这个新对象的原型
__proto__
指向函数的prototype对象。 - 执行函数, 函数的this会绑定在新创建的对象上。
- 如果函数没有返回其他对象(包括数组、函数、日期对象等),那么会自动返回这个新对象。
- 返回的那个对象为构造函数的实例。
- 对于第4点解释
//当构造函数返回的是引用值时,如:函数、对象、数组,就返回引用值。若返回的是原始值,没有任何作用
function Car(){
this.color = 'red';
this.brand = 'Benz';
return {};
}
var car = new Car();
console.log(car.color);//undefined