饥人谷技术博客

原型与原型链

2019-03-16  本文已影响6人  JaniceZD

1. 公用属性(就是原型对象)

所有对象都有 toStringvalueOf 属性,那么是否有必要给每个对象一个 toStringvalueOf 呢?

明显不需要(内存不允许)。

JavaScript 的做法是把 toStringvalueOf 放在一个对象里(暂且叫做公用属性组成的对象),然后让每一个对象的__proto__存储这个「公用属性组成的对象」的地址,当需要使用的时候,引用这个对象即可。

而这个公用属性和方法组成的对象,就是传说中的原型

JavaScript 规定,所有对象都有自己的原型对象(prototype)。
原型对象的作用,就是定义所有实例对象共享的属性和方法。

2. 原型链

Number对象、String对象、Boolean对象,他们还有各自独有的公用属性库,他们的 __proto__ 指向的就是各自的独有属性,这些独有属性的 __proto__ 最终指向的 Object 的公有属性,就是Object.prototype(原型),这一条链就叫原型链。引用情况如下图:

原型链.png
由此可知,
o1.toString === o2.toString    //true

“原型链”(prototype chain):对象到原型,再到原型的原型。所有对象的原型最终都可以上溯到 Object.prototype,即 Object 构造函数的 prototype 属性。也就是说,所有对象都继承了Object.prototype的属性。

Object.prototype 对象有没有它的原型呢?回答是Object.prototype 的原型是 null

完整的原型链.png
图中红色的线,就组成了一条原型链

3. 一些公式:

注:当声明一个对象时,JS引擎除了在栈里弄出一个哈希,还把proto指向了其该有的公用属性(原型)。

(1)number:

var n1 = new Number();
n1.__proto__ === Number.prototype    
//true,是把Number.prototype的地址赋给 n1的__proto__属性了
n1.__proto__.__proto__ === Object.prototype   //true

(2)string:

var s1 = new String()
s1.__proto__ === String.prototype   //true
s1.__proto__.__proto__ === Object.prototype  //true

(3)object:

var o1 = new Object()
o1.__proto__ === Object.prototype   //true
o1.__proto__.__proto__ === null     //true

(4)function:

var f1 = new Function()
f1.__proto__ === Function.prototype    //true
f1.__proto__.__proto__ === Object.prototype   //true

(5)重要公式与推论

公式:
var 对象 = new 函数()   //函数可以是Number/String/Boolean/Object
对象.__proto__ === 对象的构造函数.prototype

__proto__是对象的属性,prototype是函数的属性。

推论:
// 另外,所有函数都是由 Function 构造出来的,所以
Number.__proto__ = Function.prototype   // 因为 Number 是函数,是 Function 的实例
Object.__proto__ = Function.prototype   // 因为 Object 是函数,是 Function 的实例
Function.__proto__ == Function.prototye  // 因为 Function 是函数,是 Function 的实例!

Function.__proto__.__proto__ === Object.prototype   //true

FunctionNumberStringObjectFunction的构造函数。
注意:Function.__proto__.__proto__ === Object.prototype //true

无代码内存图.png

4. 三句话解释原型与原型链

第一句话:prototype 是函数的原型对象,即 prototype 是一个对象,它会被对应的 __proto__ 引用。
第二句话:要知道自己的 __proto__ 引用了哪个 prototype,只需要看看是哪个构造函数构造了你,那你的 __proto__ 就是那个构造函数的 prototype
第三句话:所有对象的原型最终都可以上溯到 Object.prototype,即 Object 构造函数的 prototype 属性。
注意: Object.prototype.__proto__ === null //true

5. 其他

面试题: '1'.__proto__ 是什么?
答:'1' 会临时转化为 String 对象,

'1'.__proto__ === String.prototype      //true

所有对象都有 __proto__ 属性。

Object.prototype.__proto__  ===  null

1.toString()     //语法错误,不加引号JS引擎会把.当作小数点,比如1.234
1..toString()    //'1'
// 第一个.当作小数点,第二个为点操作符
上一篇 下一篇

猜你喜欢

热点阅读