前言
设置原型的目的是进行对象间的委托,可以让一个对象获得另一个对象的一些属性或者方法。关于设置一个对象的原型,JS提供了俩种方式。一种是通过setPrototypeOf,另一种是Object.create,通过了解二者的区别可以让我们能够根据情况去选择适合的方式。
用法
若存在A和B俩个函数,让A的原型指向B
1.setPrototypeOf
Object.setPrototypeOf(A.prototype,B.prototype)
2.Create
A.prototype = Object.create(B.prototype)
俩者都可以达到设置对象原型的功能,但是具体表现上有一些区别。
比较
假设有Animal和Plants俩个函数用于生成对象,并在原型上具备一些方法。 然后我们让Animal的原型指向Plants
初始代码如下
function Animal (name,sound) {
this.name = name
this.sound = sound
}
Animal.prototype.shout = function () {
console.log(this.name + this.sound)
}
let dog = new Animal('pipi','wang!wang!')
// 定义Plants
function Plants (name) {
this.name = name
this.sound = null
}
// 函数接收参数用于区分
Plants.prototype.shout = function (xssss) {
console.log(this.name + this.sound +'plants tag')
}
Plants.prototype.genO2 = function () {
console.log(this.name + '生成氧气。')
}
使用create
Animal.prototype = Object.create(Plants.prototype)
console.log(Animal.prototype)
/*
Plants {}
__proto__:
shout: ƒ (xssss)
genO2: ƒ ()
constructor: ƒ Plants()
__proto__: Object
*/
let cat = new Animal('mimi','miao~miao~')
dog.shout() // pipi wang!wang!
cat.shout() // mimi miao~miao~ plants tag
cat.genO2() // mimi 生成氧气。
使用setPrototypeOf
Object.setPrototypeOf(Animal.prototype,Plants.prototype)
console.log(Animal.prototype)
/*
Plants {shout: ƒ, constructor: ƒ}
shout: ƒ (xssss)
constructor: ƒ Animal(name,sound)
__proto__:
shout: ƒ ()
genO2: ƒ ()
constructor: ƒ Plants()
__proto__: Object
*/
let cat = new Animal('mimi','miao~miao~')
dog.shout() // pipi wang!wang!
cat.shout() // mimi miao~miao~
cat.genO2() // mimi 生成氧气。
总结
使用Object.create,Animal.prototype将会指向一个空对象,空对象的原型属性指向Plants的prototytpe。所以我们不能再访问Animal的原有prototypoe中的属性。Object.create的使用方式也凸显了直接重新赋值。
使用Object.setPrototypeOf则会将Animal.prototype将会指向Animal原有的prototype,然后这个prototype的prototype再指向Plants的prototytpe。所以我们优先访问的Animal,然后再是plants。
在进行俩个原型之间的委托时使用setPrototypeOf更好,Object.create更适和直接对一个无原生原型的对象快速进行委托。
执行的时候分开执行才能看到差异,你把它们俩全放到一段执行,已经create过了,那肯定结果是一样的啊。。。。。 这篇文章写了快3年了吧,我现在已经记不清当时怎么写的了,不过得出一个结论肯定经过反复的验证才敢发出来,你觉得不对,也要做多次的验证去证明才行啊,不是简单的把代码执行了就行了的事情。