面试之原型与原型链

124 阅读2分钟

思考题

  • 用自己的话来解释什么是原型、原型链?
  • 原型链的终点是什么?如何打印出来?
  • 如何获取对象非原型链上的属性?
  • 怎么读取实例中的属性?怎么读取变量?
  • 重写了原型对象,容易发生什么事情?
  • 多个实例共享的一个原型对象,如果其中一个实例对象修改原型对象,会发生什么?

image.png

用自己的话来解释什么是原型、原型链?

脑海中务必记住上面那个图

我举个列子来说明,有一个构造函数Person,现在我new出来了一个实例对象p,其中实例p的__proto__ 指向的那个对象,即Person.prototype就是实例p的原型

当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,找到Object.prototype就可以停止了,这种原型与原型相互层层链接的过程就是原型链。

原型链的终点是什么?如何打印出来?

原型链的终点是null , Object.prototype.__proto__

怎么读取实例中的属性?怎么读取变量?

  • 读取实例中的属性 沿着原型链
  • 读取函数中变量 沿着作用域链

如何获取对象非原型链上的属性?

核心思想就是使用 hasOwnproperty()

function iterate(obj){
   var res=[];
   for(var key in obj){
        if(obj.hasOwnProperty(key))
           res.push(key+': '+obj[key]);
   }
   return res;
}

重写了原型对象,容易发生什么事情?

重写原型对象之后,如果没有指定constructor属性时,constructor会默认指向原型链上最近prototype的constructor

多个实例共享的一个原型对象,如果其中一个实例对象修改原型对象,会发生什么?

JavaScript 对象是通过引用来传递的,多个实例对象指向的是同一个原型,当修改原型时,与之相关的对象也会继承这一改变

小知识点

  • __proto__ 、[[prototype]] 、prototype 是同一个东西吗?

    不是,结合最上面的图,很好理解。 比如有一个构造函数Person(),现在new出来一个实例p,js的每个对象都会有一个隐藏属性[[prototype]]指向创建它的构造函数Person()的原型对象 protype,只有函数有prototype属性。有个疑问箭头函数不是没有自己的prototype嘛?

    而访问[[prototype]],最早之前使用的是__proto__,现在换成了getPrototypeOf()/setPrototypeOf()

  • 添加和删除属性是在实例上操作的,而不是在原型上,查找是沿着原型链

  • p.constructor === Person.prototype.constructor