原型本质:所有的构造函数都有一个prototype属性,该属性是指向函数的原型对象
所有的实例都有一个_proto_属性,该属性指向产生实例对象的构造函数的原型
_proto_不是标准属性,在Chrome,Safari,Firefox浏览器叫_proto_,在别的浏览器这个属性对脚本是不可见的, 实际上该属性是浏览器内部使用的,编程的时候不允许使用
_proto_属性和构造函数中的prototype指向同一块区域.因此下面代码结果为true
console.log(Person.prototype===p1.__proto__) //true
原型的好处就是可以实现实例对象之间共享属性和方法
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.showName =function(){console.log(this.name);}
Person.prototype.showAge =function(){console.log(this.age);}
Person.prototype.arr = ['red','yellow'];
var p1 = new Person('zhangsan',12);
var p2 = new Person('lisi',13);
p1.showName();
p2.showName();
console.log(p1.showName === p2.showName);//true
我们在调用p1.showName()与p2.showName()时,解析器会问:实例p1中有showName属性吗?答案是:没有? 然后继续问:p1原型中有showName属性吗?答案是:有,因此就可以读取到在原型中的showName函数
上边代码 给原型中的arr数组push新的值,如p1.arr.push('black');p1与p2访问到的值也是相同的
注意
如果写成p1.arr = ['pink'];相当于创建了一个新的属性,加到p1的实例对象,并没有加到原型中;
因此获取p1.arr的值就是pink,在执行p1.arr的时候
解析器会问:实例对象p1中有arr属性吗? 答案是:有 ,如果在实例对象中找到了具有给定名字的属性,那么就直接返回属性的值,如果没有找到才会到原型对象中找
总结
通过obj.arr =值;相当于创建了一个新的属性,加到obj中实例对象
但是obj.arr.push(123);这种结构不会再obj中添加一个属性,而是在arr中添加了一个值