构造函数及原型的快速记忆

127 阅读2分钟

构造函数

构造函数的问题:其定义的方法会在每个实例上都创建一遍,这样的话的,就不具有复用行,明明业务逻辑都是一样的;

原型

原型链的问题(仅仅通过new的方式)

  • 主要问题出现在原型中包含引用值的时候。在一个实例上操作原型上的引用值,会导致所有实例都变化。
  • 第二个问题在于:子类型实例化时,不能给父类型的构造函数传参

盗用构造函数(通过使用 call()(或 apply())方法)

function SuperType() {
this.colors = ["red", "blue", "green"];
}
 function SubType() {
    SuperType.call(this);
}
let instance1 = new SubType(); 
instance1.colors.push("black"); 
console.log(instance1.colors); // "red,blue,green,black"
let instance2 = new SubType(); 
console.log(instance2.colors); // "red,blue,green"

相比于原型链的优点有二:

  1. 在SuperType.call(this)的时候,运行了SuperType()中所有的初始化代码,结果就是每个实例都有自己的colors属性;
  2. 因为使用了call或apply,因此可以通过子类构造函数向父类构造函数中传值(如下):
function SuperType(name){ this.name = name;
}
function SubType() {
// 继承 SuperType 并传参 SuperType.call(this, "Nicholas");
// 实例属性
     this.age = 29;
} 
let instance = new SubType(); 
console.log(instance.name); // "Nicholas"; 
console.log(instance.age); // 29

盗用构造函数的问题

  • 仅仅能使用父类原型上的数据,无法使用原型上的方法,因此如果要想自己有方法用,必须自己给自己定义,其他的都用不了,因此不能单独使用

组合式继承(综合了原型链和盗用构造函数)

基本的思路就是使用原型链继承原型上的方法,而通过盗用构造函数继承实例属性。这样即把方法定义在原型上以实现复用,又让每个实例都有自己的属性。
this.name = name;
this.colors = ["red", "blue", "green"];
}
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.sayAge = function() { console.log(this.age);
};
let instance1 = new SubType("Nicholas", 29); 
instance1.colors.push("black"); 
console.log(instance1.colors); // "red,blue,green,black" 
instance1.sayName(); // "Nicholas"; 
instance1.sayAge(); // 29
let instance2 = new SubType("Greg", 27); 
console.log(instance2.colors); // "red,blue,green" 
instance2.sayName(); // "Greg"; 
instance2.sayAge(); // 27