prototype原型练习 前端校招面试

 上章节我们学习了原型链相关知识,这节讲解几个原型的练习题进一步去加深对原型的理解。

练习题1

 首先,从稍微简单的开始入手,看如下JS代码:

function Foo(){

}

Foo.prototype.a = 1  //对构造函数Foo添加原型属性

var f1 = new Foo()  //创建Foo的实例对象f1

//修改Foo的prototype地址指向
Foo.prototype = {
    a = 2,
    b = 3
}

var f2 = new Foo()  //更改Foo的prototype地址指向后创建Foo的实例对象f2

console.log(f1.a)  //1
console.log(f1.b)  //undefined

console.log(f2.a)  //2
console.log(f2.b)  //3

产生这样输出结果的原因可从如下内存图得出答案。

Foo.prototype.a = 1为构造函数Foo()添加原型属性a后创建的实例对象f1时内存图如下所示:

  

通过Foo.prototype = { a=2 , b=3 }后,只是修改了Foo的prototype的指向,原来指向的Object实例对象仍然被之前Foo所创建的实例对象f1的__proto__所引用,所以f1的隐式原型依旧指向之前的prototype属性;

在修改了Foo的显式原型指向后创建的实例对象f2的隐式原型__proto__将会指向新的显示原型所指向的位置,可由如下内存结构图看出:

 所以由上图可知,实例对象f1的__proto__指向的为Foo之前的prototype,所以f1.a=1 , f1.b=undefined;而实例对象f2的__proto__指向的为修改后的Foo指向的prototype,即f2.a=2 , f2.b=3。

练习题2 

这道题稍微有些复杂,涉及到上章节补充的原型链相关知识,这里我们先看如下JS代码:

function Foo(){

}

Object.prototype.a = function(){
    console.log("a()")
}

Function.prototype.b = function(){
    console.log("b()")
}

var f1 = new Foo() //Foo的实例化对象

f1.a()  // a()
f1.b()  // Uncaught TypeError: f1.b is not a function

F.a()  // a()
F.b()  // b()

 由于涉及到上章节讲到的内容,我们将上章节的原型链的图继续展示如下:

由上图可知: 

  •  Foo的实例对象 f1 在查找 a() 方法时,沿着隐式原型链的__proto__查找,在Object的原型对象上最终查找到 a() 方法。
  •  Foo的实例对象 f1 在查找 a() 方法时,沿着隐式原型链的__proto__查找,一直查找到Object的原型对象的__proto__,__proto__为null,返回Uncaught TypeError: f1.b is not a function。
  • 函数对象F()作为Function()的实例对象拥有__proto__属性,且其隐式原型的__proto__值与Function()的显式原型的prototype值指向的地址相同,所以此时F作为实例对象查找 a() 方法时沿着其__proto__的值逐个查找,在Object的原型对象上最终查找到 a() 方法。
  • 函数对象F()在查找 b() 方法时,继续沿着其__proto__的值逐个查找,最终在Function()的prototype指向的地方找到 b() 方法。

笔者建议:

在初期理解或者做原型相关的题目时,最好在纸上将内存结构图画出,这样易于分析,在后期熟练后便可在脑海中构建关系图。 

猜你喜欢

转载自blog.csdn.net/weixin_44384728/article/details/126051232