实例与原型

60 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情

还记得大一刚接触原型、原型链的概念时整个人像个呆子。后来听了大风老师的画图讲解后我才深刻明白的。授人与鱼,授人与渔。

构造函数、实例、原型三者的关系

任何函数都有一个prototype属性,该属性是一个对象。如下:

function F(){}
console.log(F.prototype)//=>object
F.prototype.sayHi = function(){
    console.log("hi!")
}

构造函数的prototype对象默认都有一个constructor属性,指向prototype对象所在的函数。

console.log(F.constructor===F)//=>true

通过构造函数得到实例对象內部都会包含一个只想构造函数的prototype对象的指针__proto__。

var instance  = new F();
console.log(instance.__proto__===F.prototype)//=>true;

__proto__是非标准属性

###### 实例对象可以直接访问原型对象成员。

instance sayHi() //=>hi!

我也要向老师当时给我讲的时候一样!画图哈哈!!画图真的很清晰!!不要晕不要晕。看图说话。

image.png

以上图示请结合上面几行代码使用。

总结:

  1. 任何函数都具有一个prototype属性,该属性是一个对象
  2. 构造函数的prototype对象默认都有一个constructor属性,指向prototype对象所在函数。
  3. 通过构造函数得到的实例对象內部会包含一个指向构造函数的prototype对象的指针__proto__.
  4. 所有实例都直接或间接继承了原型对象的成员。

了解了 构造函数-实例-原型对象 三者之间的关系后,接下来我们来解释一下为什么实例对象可以访问原型对象中的成员。

  • 每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。
  • 搜索首先从对象实例本身开始。
  • 如哦在实例中找到了具有给定名字的属性,则返回该属性的值。
  • 如果没找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。
  • 如果在原型对象中找到了这个属性,则返回该属性的值。

也就是说,在我们调用instance.sayHi()时,会先后执行两次搜索:

  • 解析器问:“实例instance有sayHi()吗” 答:“没有呜呜呜”
  • 然后他继续搜索,再问:“instance的原型里有sayHi()吗” 答:“有!”
  • 于是,它就读取那个保存在原型对象中的函数。

如果再次创造实例:

var instanceNew = new F()
console.log(instanceNew.sayHi())//输出什么?

答案还是hi!

无论是instance还是instanceNew去调用本不在自身的方法sayHi(),结果都是一样的,都会进行相同的两次搜索,实现多个对象实例共享原型所保存的属性和方法基本原理。

即:如果在自身找不到,则沿着原型链向上查找,找到就返回;如果一直到原型链的末端还找不到,那就返回“undefined”

👆,👆,👆,所以宝贝你会了没。

刚刚去关了一下空调,坐在这里长了好冷,我要去恰饭了,goodbye。

锅锅!!11!!!