「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」
在讲解之前,我们需要对原型有一定的理解
//创建一个构造函数Cat
function Cat(){}
//为构造函数的原型添加属性
Cat.prototype.type="cat";
Cat.prototype.eat = function () {
alert('我爱吃鱼')
};
//创建实例对象
var cat1 = new Cat();
cat1.eat(); //弹出'我爱吃鱼'
在每个实例对象里面都有一个[[prototype]]属性指向该实例的构造函数的原型,每个构造函数中也有一个prototype属性指向该构造函数的原型,而原型上有一个constructor指针指向它的构造函数。
在上述代码中,构造函数为Cat(),Cat()的原型Cat.prototype指向构造函数Cat(),原型上有两个属性,cat1为构造函数Cat的实例对象,所以会继承这两个属性。
原型模式有两种写法,一种是修改,一种是重写
原型的修改
//创建一个构造函数Cat
function Cat() {
}
//为构造函数的原型添加属性
Cat.prototype.type = "cat";
Cat.prototype.eat = function () {
alert('我爱吃鱼')
};
//创建实例对象
var cat1 = new Cat();
cat1.eat(); //弹出'我爱吃鱼'
Cat.prototype.name = 'fit cat';
Cat.prototype.eat = function () {
alert("我变了,我不爱吃鱼了!");
};
cat1.eat(); //先弹出'我爱吃鱼',再弹出"我变了,我不爱吃鱼了!"
console.log(cat1.name); //fit cat
当我们创建好对象实例之后,再给原型添加一些新的属性
我们发现cat1仍然能继承到原型新添加的属性,原因是我们只是给原型添加了新的属性,但是原型还是那个原型,对象实例cat1的[[prototype]] 指针指向的还是原来的原型对象,所以可以向上访问到原型的新添加属性。
原型的重写
//创建一个构造函数Cat
function Cat() {
}
//为构造函数的原型添加属性
Cat.prototype.type = "cat";
Cat.prototype.eat = function () {
alert('我爱吃鱼')
};
//创建实例对象
var cat1 = new Cat();
cat1.eat(); //弹出'我爱吃鱼'
Cat.prototype = {
name: 'fit cat',
//指明新原型的构造函数的原型指向Cat,如果没有声明,则指向Object
constructor: Cat
};
console.log(cat1.name); //undefined
cat1.eat(); //'我爱吃鱼'
//以新原型创建一个新的原型对象
var cat2 = new Cat()
console.log(cat2.name); //fit cat
cat2.eat(); // cat2.eat is not a function
这里我们重写了Cat.prototype的指针,也就是说将构造函数Cat的prototype指针从原来的原型对象指向了新的原型对象,因为原来的原型对象上面没有name属性,所以cat1访问不到。