关于__proto__(左右都是2个_)和prototype的一些认识
I._proto_:
1.这个属性是实例对象(子)的属性,每个实例对象都有一个__proto__属性,这个属性指向实例化该实例的构造函数(包含能从父里继承到的属性和方法)的原型对象(prototype)。
2.因为实例中有__proto__属性所以每个实例就能直接调用构造函数中prototype里的属性乃至方法(因为这些属性和方法都被复制进实例的__proto__中),但是对于同名属性或者方法,实例是覆盖构造函数的[或者说优先级实例>构造函数]。原理见下3.
3.当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父的prototype)里找,如果父对象也不存在这个属性,则继续往父对象的__proto__属性所指向的那个对象(爷爷的prototype)里找,如果还没找到,则继续往上找…直到原型链顶端null,此时若还没找到,则返回undefined。
图例:
II.prototype:
1.每个构造函数都有一个prototype对象,这个对象指向该构造函数的原型(父)。
例子1:
function human(){
this.age = 12;//构造方法里面的age属性
this.chat = function(){//构造方法里面的showMsg方法
console.log("卢本伟牛逼");
}
}
human.prototype.say = function () {//实例方法上定义的say方法
console.log('test');
}
human.prototype.age = 23;//原型上定义的age属性
var b = new human();//实例化一个human,
//此时b对象包含了human构造函数中的属性和方法,不包含human原型上的属性和方法。
console.log(b);
b.chat();
b.say();
console.log(b.age)
结果:
1.console.log(b):age、chat从构造方法里继承;_proto_:age、say(后续在prototype中添加)。
2.b.chat();实例可调用构造方法里的chat()。
3.b.say():如上述(__proto__3.)所述,b实例中无say()方法,则通过__proto__从父对象的prototype中找到say()方法。
4.console.log(b.age):原理同上3.,b实例中有age属性,所以不通过__proto__找age属性。
例子2:
function human(){
this.age = 12;//构造方法里面的age属性
this.chat = function(){//构造方法里面的showMsg方法
console.log("卢本伟牛逼");
}
}
human.prototype.say = function () {//实例方法上定义的say方法
console.log('test');
}
human.prototype.age = 23;//原型上定义的age属性
var b = new human();//实例化一个human,
//此时b对象包含了human构造函数中的属性和方法,不包含human原型上的属性和方法。
function man(){};//初始化一个新构造方法man
man.prototype=b;//把man的原型指向实例化的b,即man的原型中就具备了b对象所有的属性和方法
var a = new man();//实例化一个man,
console.log(a)
结果: