JavaScript 继承

一、内部属性 [[prototype]]

JavaScript 没有类的概念,它的“继承”基于对象的内部属性 [[prototype]],它是一个内部引用,它的值是引用类型值。

ES6 中 class 语法是一种误导,它只是封装在 [[prototype]] 上的一个语法糖,它的行为像类,但又不同。

JavaScript 中的原型链就是靠内部属性 [[prototype]] 关联起来的。关联的逻辑如下:

  1. 当访问一个对象的属性时,如果当前对象中不存在,就会在当前对象的内部属性 [[prototype]] 所指向的对象上进行查找,假设是 obj.__proto__
  2. 查找到,但立即返回该属性值。
  3. 没有查找到,就在当前对象的内部属性 [[prototype]] 所指向的对象上进行查找,就是 obj.__proto__.__proto__,以此类推。查找的终点对象就是 Object.prototype

我们把这个查找过程,叫“在原型链上逐级向上查找”。

取得对象的内部属性 [[prototype]],可以使用对象的非标准属性 __proto__,ES5 提供了一个标准方法 Object.getPrototypeOf(),可以达到同样目的。

二、以构造的形式调用函数

JavaScript 中没有构造函数的概念,只有“以构造的形式调用的函数”。调用函数时,前面加 new 就说这个函数,是以构造的形式调用的函数。

function Foo() {  }

new Foo(); // 以构造的形式调用的函数

当一个函数以构造的形式调用的时候,与普通的函数调用方式有以下的区别:

  1. 创建、返回一个新对象。
  2. 函数中的 this 引用指向这个新对象。
  3. 新对象的内部 [[prototype]] 链指向函数的原型对象((new Foo()).__proto__ === Foo.prototype 值为 true)。
function Foo(info) {
    this.info = info;
}

var f1 = new Foo('info1');
var f2 = new Foo('info2');

f1 === f2 // false;

f1.info // info1
f2.info // info2

f1.__proto__ === f2.__proto__ // true
f1.__proto__ === Foo.prototype // true

f1.__proto__.constructor === Foo // true

{注意} 函数的原型对象有一个属性 constructor,指向函数本身,就是说 (new Foo()).__proto__.constructor === Foo 值为 true

三、寄生组合式继承

这是最常选择的继承方式。

function inheritPrototype(subType, superType) {
    subType.prototype = Object.create(superType.prototype);
    subType.prototype.constructor = subType;
}

// Shape - superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

// superclass method
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// subclass extends superclass
inheritPrototype(Rectangle, Shape);

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?', rect instanceof Shape); // true
rect.move(1, 1); // 打印 'Shape moved.'

rect 对象有两个实例属性 xyrect.__proto__ 指向 Rectangle.prototyperect.__proto__.constructor 指向 Rectangle(手动赋予的);Rectangle.prototype.__proto__ 指向 Shape.prototypeShape.prototype.constructor 指向 Shape

四、参考链接

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

(完)

原文地址:https://www.cnblogs.com/zhangbao/p/6587773.html