原型模式(构造函数)
利用原型模式,将方法定义在构造函数的原型对象上,解决对象需要多个方法,就需要在全局定义更多的函数,不便于自定义类型的统一管理的问题。
- 每个函数都有一个prototype属性,指向一个对象。
- 该对象包含应该由特定引用类型的实例共享的属性和方法。
- 该对象就是通过调用构造函数创建的对象的原型。
原型继承
- 利用构造函数构建对象结构(模板,近似于类),从语义上较为清晰的表达对象结构。
- 利用构造函数原型扩展,能方便的为该构造函数所创建的对象进行基于原型的扩展。
- 利用构造函数还可以进行基于原型对象的继承。
注:
当在构造函数原型上创建属性(或方法)时,会被改构造函数的额所有对象所共享。
对象自身对继承自原型的属性赋值,则创建了一个属于自己的同名属性,并“屏蔽”了继承自原型的属性。
构造函数、原型和实例的关系:
- 每个构造函数都有一个原型对象。
- 原型有一个属性指回构造函数
- 实例有一个内部指针[[Prototype]]指向原型。
原型链
- 当对象原型是另一个构造函数的实例,如此迭代,形成了一连串的继承关系,即为原型链。
- 原型链表达了对象与对象之间的继承关系。
function Animal() {
this.colors = ["white", "black"];
}
function Mouse(name, age) {
this.name = name;
this.age = age;
}
Mouse.prototype = new Animal();
let m1 = new Mouse("Mickey", 10);
console.log(m1.name, m1.colors);//当原型中包含引用值时,在各实例间共享的是该引用值的引用。当某个实例修改该属性时,会影响全部实例。
m1.colors.push("red");//子类型在实例化时不能个父类型传递参数。
let m2 = new Mouse("Miney", 9);
console.log(m2.colors);
盗用构造函数
- 在子类构造函数中调用父类构造函数,并将子类当前实例只定为构造函数的上下文。
原型链与盗用构造函数的组合
function Animal(type) {
this.colors = ["white", "black"];
this.type = type;
}
Animal.prototype.show = function () {
console.log(this.colors, this.type);
};
function Mouse(name, age, type = "Mouse") {
Animal.call(this, type);//父类构造函数“盗用”,解决传参问题
this.name = name;
this.age = age;
}
Mouse.prototype = new Animal();//强制指定原型对象,表达继承关系
Mouse.prototype.constructor = Mouse;//强制指定构造函数为原构造函数
let m2 = new Mouse("Miney", 9);
console.log(m2.name, m2.colors);
m2.show();
console.log(m2 instanceof Mouse, Mouse.prototype.isPrototypeOf(m2));
console.log(m2 instanceof Animal, Animal.prototype.isPrototypeOf(m2));
console.log(m2 instanceof Object, Object.prototype.isPrototypeOf(m2));
既可以传参,又可以原型继承
console.log(tagpow2:${x},${y}
);
tag: 标签模板