深入细致阐释:
他们晓得 JS 有第一类,比如说
他们能对 obj 展开许多操作方式,主要就包括
「读」特性
「追加」特性
「预览」特性
「删掉」特性
上面他们主要就上看呵呵「读」和「追加」特性。
为甚么有 valueOf / toString 特性呢?
在他们没对 obj 展开任何人其它操作方式以后,辨认出 obj 早已有两个特性(方式)了:
所以难题来了:valueOf / toString / constructor 是是不是来?他们并没给 obj.valueOf 表达式呀。
要弄清楚 valueOf / toString / constructor 是是不是来的,要是加进 console.dir 了。
上面这个图有点难懂,我手画一个示意图:
他们辨认出 console.dir(obj) 打出来的结果是:
1. obj 本身有一个特性 name(这是他们给它加的)
2. obj 还有一个特性叫做 __proto__(它是一个第一类)
3. obj.__proto__ 有很多特性,主要就包括 valueOf、toString、constructor 等
4. obj.__proto__ 其实也有一个叫做 __proto__ 的特性(console.log 没显示),值为 null
现在回到他们的难题:obj 为甚么会拥有 valueOf / toString / constructor 这两个特性?
答案:
这跟 __proto__ 有关。
当他们「读取」 obj.toString 时,JS 引擎会做下面的事情:
1. 看看 obj 第一类本身有没 toString 特性。没就走到下一步。
2. 看看 obj.__proto__ 第一类有没 toString 特性,辨认出 obj.__proto__ 有 toString 特性,于是找到了
所以 obj.toString 实际上就是第 2 步中找到的 obj.__proto__.toString。
能想象,
3. 如果 obj.__proto__ 没,所以浏览器会继续查看 obj.__proto__.__proto__
4. 如果 obj.__proto__.__proto__ 也没,所以浏览器会继续查看 obj.__proto__.__proto__.proto__
5. 直到找到 toString 或者 __proto__ 为 null。
上面的过程,就是「读」特性的「搜索过程」。
而这个「搜索过程」,是连着由 __proto__ 组成的链子一直走的。
这个链子,就叫做「蓝本链」。
共享蓝本链
现在他们有另一个第一类
如图:
所以 obj.toString 和 obj2.toString 其实是同一个东西,也就是 obj2.__proto__.toString。
这有甚么象征意义呢?
如果他们改写 obj2.__proto__.toString,所以 obj.toString 其实也会变!
这样 obj 和 obj2 就是具有某些相同行为的第一类,这就是象征意义所在。
差异化
如果他们想让 obj.toString 和 obj2.toString 的行为不同是不是做呢?
直接表达式就好了:
总结:
「读」特性时会沿着蓝本链搜索。
「追加」特性时不会去看蓝本链(但是如果你给这个特性加了许多配置,则不一样,以后讲)。