JavaScript继承——原型链和借用构造函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010011236/article/details/87970630

一、继承之借用构造函数

借用构造函数:通过在子类型构造函数使用 call() 或 apply() 方法继承超类构造函数的属性和方法。

function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'gree'];
}

function SubType(name, age) {
  
  SuperType.call(this, name);   // 借用构造函数
  
  this.age = age;
}

var instance1 = new SubType('Nicholas', 29); /* ① */
instance1.colors.push('black');  /* ② */
console.log(instance1.colors);   /* ③ */

执行 var instance1 = new SubType('Nicholas', 29); 时,实际会执行如下步骤:

1)创建一个新对象

2)把构造函数(SubType)的作用域赋值给新创建的对象

3)执行构造函数(SubType)中的代码,其内部执行过程为:

    i)当执行完 SuperType.call(this, name) 时,SubType 构造函数拥有了 SuperType 构造函数中的属性,

        即新创建的对象拥有 name = 'Nicholas'、colors = ['red', 'blue', 'gree'] 属性

   ii)age = 29

4)返回新创建的对象(并赋值给 instance1)

所以 instance1 对象中拥有的实例属性为:name、colors、age,其值分别为 'Nicholas'、 ['red', 'blue', 'gree'] 、29。

二、继承之原型链

原型链:子构造函数的原型对象为超类型构造函数的实例,即 SubType.prototype = new SuperType()。

function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'gree'];
}

SuperType.prototype.sayName = function() {
  console.log(this.name);
}

function SubType(name, age) {
  this.name = name;
  this.age = age;
}

// 原型链继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
  console.log(this.age);
}

var instance1 = new SubType('Nicholas', 29);
console.log(instance1.name);
instance1.sayName();
instance1.colors.push('black');
console.log(instance1.colors);  //['red', 'blue', 'gree', 'black']

var instance2 = new SubType('Greg', 30);
console.log(instance2.colors);  // ['red', 'blue', 'gree', 'black']

上述代码的原型链图如下所示

由上图可知:

1)当调用 instance1.name,其执行的是 instance1 对象实例中的属性,即为 'Nicholas'。该属性屏蔽了原型链中的 name 属性。

2)当调用 instance1.sayName(),实际上是继承了 SuperType.prototype 对象的方法,由于 this 指向的是当前对象 instance1,即语句执行的结果为显示 'Nicholas'

而由于通过原型继承的方法和属性是共享的,如果原型链中包含引用类型的属性时,当有一个对象改变该属性时,创建的其他对象都会共享该属性改变后的值。

3)当执行 instance1.colors.push('black') 后,原型链中 colors 属性的值为 ['red', 'blue', 'gree', 'black']

     此后再创建一个新对象 instance2,instance2.colors 的值为即为 ['red', 'blue', 'gree', 'black']

三、继承之组合继承(借用构造函数和原型链)

组合继承就是结合借用构造函数和原型链的优点来实现继承,具体代码如下所示:

function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'gree'];
}

SuperType.prototype.sayName = function() {
  console.log(this.name);
}

function SubType(name, age) {
  
  SuperType.call(this, name);   // 借用构造函数
  
  this.age = age;
}

// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
  console.log(this.age);
}

var instance1 = new SubType('Nicholas', 29);
console.log(instance1.name);
instance1.colors.push('black');
console.log(instance1.colors); // ['red', 'blue', 'gree', 'black']

var instance2 = new SubType('Greg', 30);
console.log(instance2.colors); // ['red', 'blue', 'gree']

当执行 var instance1 = new SubType('Nicholas', 29) 时,其原型链图如下图所示:

由上图可知,instance1 对象中拥有 colors 属性,该属性屏蔽了原型链中的属性,属于实例属性。

即修改 instance1 的 colors 属性不会被其他实例所共享。

参考文献

[1] 《JavaScript高级程序设计(第3版)》

猜你喜欢

转载自blog.csdn.net/u010011236/article/details/87970630