前置知识
先了解一下JS的原型及原型链.
借用构造函数继承
借用构造函数,也叫伪造对象或经典继承
function A() {
this.colors = ["red", "blue", "green"];
}
function B() {
//继承A
A.call(this);
console.log("this",this)
}
var instance1 = new B();
console.log("instance1",instance1)
instance1.colors.push("black");
console.log(instance1.colors); // "red,blue,green,black"
var instance2 = new B();
console.log(instance2.colors); // "red,blue,green"
var instance3 = new A();
console.log("instance3",instance3)
console.log(instance3.colors) // "red,blue,green"
将A函数在B构造函数中调用,在每个实例中执行,这样每个实例中都会有一份A中的属性方法的副本,也就实现了继承A。
☆组合继承
也叫伪经典继承,将原型链和借用构造函数的技术组合到一块。使用原型链实现对原型属性和方法的继承,而通过构造函数来实现对实例属性的继承。
function A(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
A.prototype.sayName = function() {
console.log(this.name);
}
function B(name, age) {
// 继承属性
A.call(this, name);
this.age = age;
}
// 继承方法
B.prototype = new A();
B.prototype.sayAge = function() {
console.log(this.age);
};
var instance1 = new B("Nicholas", 29);
console.log("instance1",instance1)
instance1.colors.push("black")
console.log(instance1.colors) // "red,blue,green,black"
instance1.sayName() // "Nicholas";
instance1.sayAge() // 29
var instance2 = new B("Greg", 27);
console.log(instance2.colors) // "red,blue,green"
instance2.sayName() // "Greg";
instance2.sayAge() // 27
如果上例中,没有写B.prototype = new A();
,则B是无法使用sayName()这个函数的。因为B没有定义sayName这个函数,A也没有定义。sayName()是A的原型定义的。
原型式继承
不自定义类型的情况下,临时创建一个构造函数,借助已有的对象作为临时构造函数的原型,然后在此基础实例化对象,并返回。
function ABC(o){
function F(){}
F.prototype = o;
return new F();
}
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var person2 = ABC(person);
console.log(person2)
person2.name = "Greg" // 这里是直接定义person2中的name="Greg",而不是修改person中的name
console.log(person2.friends)
person2.friends.push("Rob") // 这里因为是操作数组,而person2中没有friends这个数组,它只能往原型找。所以这里是修改原型的friends
console.log(person2)
console.log(person2.friends)
var person3 = ABC(person);
person3.name = "Linda";
person3.friends.push("Barbie");
console.log(person3)
console.log(person)
console.log(person.friends)