Prototype属性的作用
JavaScript规定所有对象都有自己的原型对象prototype。一方面任何一个对象都可以充当其他对象的原型。另一方面它也有自己的原型。所有对象最终都会上溯到Object.prototype。所有属性都继承自Object.prototype,因此,所有对象都有valueOf和toString方法。Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此原型链的最后一层是null。
···
function Animal(name){
this.name = name;
}
Animal.prototype.color = 'black';
var cat = new Animal('cat');
var dog = new Animal('dog');
cat.color;//black
dog.color;//black
Animal.prototype.color = 'red';
cat.color;//red
cat.color = 'white';
cat.color;//white
···
原型对象的属性不是实例对象的自身属性,只要修改原型对象,马上就能作用到实例对象上。由于实例对象没有color属性,都是读取原型对象的color属性。当实例对象没有某个属性或方法时,就会去原型对象上找。如果实例对象自身拥有这个属性,则使用自身属性,不用去原型对象寻找。
原型链
JavaScript规定所有对象都有自己的原型对象prototype。一方面任何一个对象都可以充当其他对象的原型。另一方面它也有自己的原型。所有对象最终都会上溯到Object.prototype。所有属性都继承自Object.prototype,因此,所有对象都有valueOf和toString方法。Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此原型链的最后一层是null。
var obj = new 构造函数();
obj.__proto__ === 构造函数.prototype
var number = new Number()
number.__proto__ = Number.prototype
Number.__proto__ = Function.prototype // 因为 Number 是 Function 的实例
var object = new Object()
object.__proto__ = Object.prototype
Object.__proto__ = Function.prototype // 因为 Object 是 Function 的实例
var function = new Function()
function.__proto__ = Function.prototype
Function.__proto__ == Function.prototye // 因为 Function 是 Function 的实例!
我们首先创建一个object
let obj = {name:'obj1'}
我们可以看到obj被创建后它的prototype就是Object,我们没有对obj操作,它就有了valueOf,toString等方法。
它们的关系大概如下图所示:
我们发现:
obj原本有个名字叫name,由我们命名。
obj有个proto属性
obj.proto有toString,constructor, valueOf等方法或属性。
这一切都和proto有关。
当我们访问obj.toString, js引擎会去检查对象本身有没有这个属性,如果没有,就去查看obj.proto有没有这个属性。

此时已经找到toString属性。如果还是没有就会去查找obj.proto.proto 直到找到或者结果为null为止。
共享原型链
我们继续创建一个对象obj2

此时 obj和obj2 的toString是同一个东西。如果我们改变obj.proto.toString(),此时obj2.proto的toString()也会改变。
obj.__proto__.toString = ()=> { console.log('__proto__.toString')}

此时 obj2.proto.toString也发生了改变。这样obj和obj2就是拥有了相似行为的对象。
差异化
如果我们想让obj和obj2的toString不同,我们直接给obj2.toString赋值即可
obj2.toString = () => { console.log('obj2') }

此时 obj2.toString发生了改变。
网友评论