对象存值:obj.a = 1,obj对象的原型.链上无论有无a成员,都会在obj对象中操作a成员(已经有a成员则改它的值,如果没有则先添加a属性再赋值)
对象取值:var re = obj.x,取出obj对象中x属性的值,如果对象中无x属性,到原型链上取值,都没有返回undefined。
实例:
<script>
function fn () {
this.a = 1
}
fn.prototype.x=20
//fn创建的对象的对象模型添加x属性,赋值为20
var f1=new fn()
//f1={__proto__:{x:20},a:1}
f1.x=10//为f1对象存值,虽然f1原型对象中有x属性,但是只会加在对象自己身上。
console.log(f1.x,f1.a,f1.b)//10 1 undefined
</script>
原型对象的操作
构造函数的prototype属性可以修改
内置构造函数的prototype不能修改,但是可以操作(可以给原型属性添加成员)
对象的__proto__也可以操作和修改,内置的对象不能修改
如果内置函数的__proto__被修改了,其带的功能就没有了,修改时系统会自动跳过编译(官方说法为“静默”)
<script>
var arr=new Array(10,20,40)
arr.__proto__.fn=90//未修改原型对象,只是操作它,为它添加一个属性
arr.__proto__=[1,2,3]//自动跳过不会执行
var arr2=[10]
console.log(arr2.fn) //打印90 arr2数组中没有fn属性,到数组的原型链上查找
</script>
综合案例分析:
<script>
//校招面试题
function Parent() {
this.a = 1;
this.b = [1, 2, this.a];
this.c = {
demo: 5
};
this.show = function() {
console.log(this.a, this.b, this.c.demo);
}
}
function Child() {
this.a = 2;
this.change = function() {
this.b.push(this.a);
this.a = this.b.length;
this.c.demo = this.a++;
}
}
Child.prototype = new Parent();
//执行后Child创建的对象拥有new Parent()对象的功能
var parent = new Parent();
//parent={__proto__:{},a:1,b:[1,2,1],c:{demo:5},show:function(){...}}
var child1 = new Child();
//child1={__proto__:{a:1,b:[1,2,1],c:{demo:5},show:function(){...}},
//a:2,change:function(){...}}
var child2 = new Child();
//child2={__proto__:{a:1,b:[1,2,1],c:{demo:5},show:function(){...}},
//a:2,change:function(){...}}
child1.a = 11;
//执行后 child1={__proto__:{a:1,b[1,2,1],c{demo:5},show:function()
//{...}},a:11,change:function(){...}}
child2.a = 12;
//执行后 child2={__proto__:{a:1,b:[1,2,1],c:{demo:5},show:function()
//{...}},a:12,change:function(){...}}
parent.show();
//调用parent中的show函数,show函数中的this代表parent
//打印结果1 [1,2,1] 5
child1.show();
//child1调用show方法,child1中无show方法,到原型对象中查找,找到后调用,此时show方法中
//的this代表child1,child1对象中无b、c.demo到原型对象中查找
//打印结果 11 [1,2,1] 5
child2.show();
//child2调用show方法,child2中无show方法,到原型对象中查找,找到后调用,此时show方法
//中的this代表child2,child2对象中无b、c.demo到原型对象中查找
//打印结果为 12 [1,2,1] 5
child1.change();
//child1调用change方法,child1中无b属性,到原型中查找,并操作b属性添加一个元素
//此时 child1的__proto__变为{a:1,b:[1,2,1,11],c:{demo:5}
//然后从新赋值a为4
//然后操作原型对象中的c的demo属性,变为4 ,这条语句执行完毕后a+1
//新的child1对象 {__proto__:{a:1,b:[1,2,1,11],c:{demo:4},show:function(){...}},
//a:5,change:function(){...}}
child2.change();
//child2调用change方法,child1中无b属性,到原型中查找,并操作b属性添加一个元素
//此时 child2的__proto__变为{a:1,b:[1,2,1,11,12],c:{demo:4}
//然后从新赋值a为5
//然后操作原型对象中的c的demo属性,变为5,这条语句执行完毕后a+1
//新的child2对象 {__proto__:{a:1,b:[1,2,1,11,12],c:{demo:5},show:function()
//{...}},a:6,change:function(){...}}
parent.show();
//parent再一次调用show方法
//打印结果为 1 [1,2,1] 5
child1.show();
//child1再一次调用show方法,child1无b、c.demo 到原型对象中查找 ,此时原型对象已经发生
//了改变 为__proto__:{a:1,b:[1,2,1,11,12],c:{demo:5},show:function(){...}
//打印结果5 [1,2,1,11,12] 5
child2.show();
//child2再一次调用show方法,child2无b、c.demo 到原型对象中查找 ,此时原型对象已经发生
//了改变 为__proto__:{a:1,b:[1,2,1,11,12],c:{demo:5},show:function(){...}
//打印结果6 [1,2,1,11,12] 5
</script>
补充:引用数据与原型对象综合
<script>
function fn() {
}
//隐式操作fn.prototype={}
var f1 = new fn( ) //__proto__=fn.prototype
fn.prototype = { //让fn.prototype从新引用一个对象
age: 20
}
console. log(f1.age)//undefined
var f2 = new fn( )
console. log(f2.age)//20
</script>