浅谈_proto_和prototype
为什么要有原型
用构造函数生成实例对象时,缺点是无法共享属性和方法。
每一个实例对象,都有自己的属性和方法的副本。即每生成一个实例对象时,js都会为实例分配一个内存,用来存储那些公共的属性和方法。这不仅无法做到数据共享,也是极大的资源浪费
prototype属性就是用来解决这个问题的
prototype属性包含一个对象,所有实例对象需要共享的属性和方法,都放在这个对象里面;那些不需要共享的属性和方法,就放在构造函数里面
实例对象一旦创建,将自动引用prototype对象的属性和方法。即实例对象的属性和方法,分为两种,一种是本地的,另一种是引用的
原型(prototype)
每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
原型链
每一个对象都会有一个指向它的原型(prototype)对象的内部链接(__proto__)。每个原型对象又有自己的原型,直到某个对象的原型为null为止,组成这条链的最后一环。
Object
js中所有的对象都是Object的实例,并继承Object.prototype的属性和方法。
__proto__
定义普通对象的时候,就会生成一个_proto_,指向自己构造函数的prototype对象。(每一个对象都会有的一个属性)
function Person(){}; var p = new Person();
Person.prototype.antion = function(){
console.log(123);
} consol.log(p._proto_ === Person.prototype); //true console.log(p.__proto__); //{anition:f, constructor:ƒ, __proto__:Object}
注意:proto左右是英文状态下的两个下划线!!!
prototype
拥有内部方法的对象才有的属性(这个属性指向一个对象,也可以称其为对象),例如函数,对象的方法,Object(内置方法为toString、valueOf)。指向一个原型对象,可以访问
指向的这个原型对象其实就是自身的原型,可以为这个原型添加属性和对象(方法),甚至可以指向一个现有的对象
函数在被定义的时候就拥有了一个prototype对象
function Person(){}; var p = new Person();
console.log(Person.prototype); //{func:f, constructor:f, __proto__:Object}
2、Object.prototype 是原型链上最后一个有属性的原型,也就是说,Object.prototype 的原型是 null。所有对象都继承了 Object.prototype 的属性,我们也可以向 Object.prototype 中添加属性
function Person(){};
var p = new Person(); Object.prototype.F = function(){ console.log(“我是最后一个原型了~”); }
p.F(); //“我是最后一个原型了~”
Person.F(); //“我是最后一个原型了~”
//p为什么有 F 方法呢?以为它会沿着 __proto__ 一层一层向上寻找,直到找到 Object.prototype
//p.__proto__指向Person.prototype,p.__proto__.__proto__ === Person.prototype.__proto__ === Object.__proto__
3、prototype 对象的另一个属性是constructor,这个属性指向了函数本身,也就是它自己的构造函数。
图示
参考:
https://segmentfault.com/a/1190000011801127