1.大厂校招题:
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();
var parent = new Parent();
var child1 = new Child();
var child2 = new Child();
child1.a = 11;
child2.a = 12;
parent.show();
child1.show();
child2.show();
child1.change();
child2.change();
parent.show();
child1.show();
child2.show();
分析:
//解题说明:通过在对象前加代号O1 O2...O5 来标识对象 方便理解 无意义
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()的对象
//Child.prototype =O1{a:1,b:[1,2,1,11,12],c:{demo:5},show:上面的函数,__proto__:O3{}}
var parent = new Parent();
//parent=O2{a:1,b:[1,2,1],c:{demo:5},show:上面的函数,__proto__:O3{}}
var child1 = new Child();
//child1={a:5,change:上面的函数,__proto__:O1}
var child2 = new Child();
//child2={a:6,change:上面的函数,__proto__:O1}
child1.a = 11; //无论child1的原型链上是否有a成员 都会把a添加/更新到child1自己上
child2.a = 12; //无论child2的原型链上是否有a成员 都会把a添加/更新到child1自己上
parent.show();
/*console.log(this.a, this.b, this.c.demo);
==>parent就是this也就是O2对象 O2.a=>1 O2.b==>[1,2,1] O2.c.demo==>5
打印 1 [1,2,1] 5
*/
child1.show();
/*show函数是原型对象的方法 child1自己没有 就访问了原型的 但是调用者(函数内部的this)是child1
===>console.log(this.a, this.b, this.c.demo);
this.a==>11 this.b==>自己没有去访问原型的=>[1,2,1] this.c.demo==>自己没有去访问原型的=>5
打印 11 [1,2,1] 5
*/
child2.show();
/*show函数是原型对象的方法 child2自己没有 就访问了原型的 但是调用者(函数内部的this)是child2
==>console.log(this.a, this.b, this.c.demo);
this.a==>12 this.b==>自己没有去访问原型的=>[1,2,1] this.c.demo==>自己没有去访问原型的=>5
打印12 [1,2,1] 5
*/
child1.change();
/* this是child1
this.b.push(this.a);
==> b是原型对象的属性 但这个代码没有修改b 只是操作了b内部的数据是可以让原型对象内部的数据改变
this.a取值会优先取原型链的最顶层的属性11 ==> 原型对象的数组末尾添加了11
this.a = this.b.length;
给child1自己添加/更新 a属性 值为4 child1的原型对象的属性b的长度
this.c.demo = this.a++;
this.c.demo=先取值4 再把a的值加1
this.c属性是原型对象的属性 但是没有修改这个属性的情况下 是可以操作其内部的数据的
因此原型对象的的c属性中的demo属性改为4
*/
child2.change();
/* this是child2 this.b.push(this.a);
==>同上 b是原型对象的属性 但这个代码没有修改b 只是操作了b内部的数据是可以让原型对象内部的数据改变
this.a取值会优先取原型链的最顶层的属性12,原型对象的数组末尾添加了12
this.a = this.b.length;
this.a = 原型对象的b属性的length==>5;
this.c.demo = this.a++;
this.c.demo=取值5(修改了原型对象) a再加
*/
parent.show();
/*show函数内部的this是parent
console.log(this.a, this.b, this.c.demo);
1 [1,2,1] 5
*/
child1.show();
/*show函数内部的this是child1
console.log(this.a, this.b, this.c.demo);
5 [1,2,1,11,12] 5 (this.b,this.c都是原型上的)
*/
child2.show();
/* show函数内部的this是child2
console.log(this.a, this.b, this.c.demo);
6 [1,2,1,11,12] 5 (this.b,this.c都是原型上的)
*/
练习1:
function fn() {
this.x1 = {
x2: 40
}
this.x2 = [103, 4, 5]
}
function fm() {
}
fm.prototype = new fn()
function fg() {
}
fg.prototype = new fm()
var obj = new fg()
//如果x1是原型链上成员: 可以取出使用
console.log(obj.x1)
// 都不能修改这个x1属性(因为会把x1属性添加 / 更新到obj自己上)
obj.x1 = [10, 20, 40] //obj自己添加了x1
//x1是原型链上的属性 虽然不能修改 但是可以操作
obj.x1.x2 = 30
obj.x2.push(123)
var obj2 = new fg()
console.log(obj2.x1.x2)
练习2:
function fn(){}
var f1=new fn() //f1的原型的对象是官方内置的new Object对象
fn.prototype={age:20} // 修改了原型对象 函数重新引用了新的对象
console.log(f1.age) //undefined
var f2=new fn() //f2的原型的对象是修改后的原型对象
//虽然是用同一个函数创建出来的 但中途修改了fn.prototype 所以取值不一样
console.log(f1.age) //20