关于javascript:再解-JavaScript-原型与原型链

37次阅读

共计 1912 个字符,预计需要花费 5 分钟才能阅读完成。

前言

JavaScript 原型与原型链尽管是一个陈词滥调的话题,但仍然困惑着很多人,明天我再来从另一个角度谈谈这个问题。

两个疑难

先看这样一段代码:

let obj = {}
obj.__proto__.haha = 'gogo'
console.log(obj.haha) // "gogo"

运行一下下面的代码,输入后果为 gogo

针对这个后果,有以下疑难:

  • obj 哪来的 __proto__ 属性?
  • 为什么增加到 __proto__ 上的属性,能够间接通过 obj 拿到?

第一个问题

js 中每个对象都有一个“原型”,原型个别能够通过 __proto__ 拜访到:

let obj = {}
console.log(obj.__proto__)
// {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}

能够这么了解: 原型,也是一个对象

就像:

  • 每个“人”都有一个“爸爸”;
  • 但“爸爸”也是一个“人”;
  • “爸爸”除了是某个人的爸爸外,与其他人并没有实质的区别;
  • 爸爸,也是普通人。

相似的:

  • “原型”是一个一般的对象;
  • 爸爸也有他的爸爸,原型也有它的原型。

第二个问题

对象与人不同的是:

  • 人不能够轻易拿爸爸的货色
  • 而对象能够轻易拿原型里的货色

比方,当你向一个对象,索要一个属性时:

  • 如果这个对象没有你要的属性,它就会让它的原型(爸爸)给你
  • 如果它爸也没有,那它爸就会找它爸的爸

比方上面这个例子:

let obj = {
  __proto__: {
    __proto__: {haha: 'gogo'}
  }
}
console.log(obj.haha) // "gogo"

因为 obj 自身没有 haha 这个属性,所以它会去本人的 __proto__ 中查找,如果还没有找到,那就会向它的 __proto__.__proto__ 中去找,直到找到 haha 属性或者 __proto__ 链返回 null 为止。

再换一种写法:

let 爷爷 = {haha: 'gogo'}
let 爸爸 = {__proto__: 爷爷}
let obj = {__proto__: 爸爸}
console.log(obj.haha) // "gogo"

查找 haha 属性的过程是:obj -> 爸爸 -> 爷爷 ,像不像是一条链子呢?这就是原型链。

对于 prototype

有这样一句话:

类是对象的模板

你与我,都是人,“人”是类,是模板。

你与我,都属于“人”类,有很多共性:

  • 有一张嘴
  • 有两条腿
  • 会吃饭
  • 会睡觉
    ……

这些共性是人类共有的。

当然,你与我做为独立的对象,必定也存在差别,比方:我的名字叫 X,你的名字叫 Y。这些不同点,是对象“公有”的。

看一段 js 创建对象的代码(留神正文局部):

function Person(name) {this.name = name}
Person.prototype. 吃饭 = function() {console.log('吃吃吃')
}
Person.prototype. 睡觉 = function() {console.log('睡睡睡')
}

let 我 = new Person('我')
我. 吃饭 () // "吃吃吃"
console.log(Person.prototype === 我.__proto__) // true
// 能够看出,在实例化的过程中,类的 prototype 成为对象的原型  

let 你 = new Person('你')
你. 睡觉 () // "睡睡睡"
console.log(我.__proto__ === 你.__proto__) // true
// 同一类的多个实例(对象),共享一个原型?我.__proto__. 吃饭 = function() {console.log('再吃一点')
}
console.log(我. 吃饭 == 你. 吃饭) // true
你. 吃饭 () // "再吃一点"
// 没错,同一类的多个实例,共享一个原型 

类比于人类社会,就是:

  • 你的兄弟姐妹和你“共享”一个爸爸
  • 当你的爸爸烫了个头时,你弟弟的爸爸也烫头。这个过程中,不是两个爸爸同时烫头,而是原本就一个爸爸。

重要论断:

  • 实例化的过程中(也就是“当 new 一个对象的时候”), 类的 prototype 成为对象的原型
  • 同一个类的多个实例(也就是“对象”),共享一个原型

结束语

原型是 js 底层的货色,不懂原型,简直不影响工作。

相似“原型有什么用”的问题,就像“砖块(或水泥)对盖楼有什么用”。其实在写代码的过程中,简直不会用到原型的常识。然而如果遇到了问题、呈现了 bug、性能优化时,底层的常识是必定有大用处的。

~

~ 本文完,感激浏览!

~

学习乏味的常识,结识乏味的敌人,塑造乏味的灵魂!

大家好,我是〖编程三昧〗的作者 隐逸王 ,我的公众号是『编程三昧』,欢送关注,心愿大家多多指教!

正文完
 0