1. 公用属性(就是原型对象)
所有对象都有 toString
和 valueOf
属性,那么是否有必要给每个对象一个 toString
和 valueOf
呢?
明显不需要(内存不允许)。
JavaScript 的做法是把 toString
和 valueOf
放在一个对象里(暂且叫做公用属性组成的对象),然后让每一个对象的__proto__
存储这个「公用属性组成的对象」的地址,当需要使用的时候,引用这个对象即可。
而这个公用属性和方法组成的对象,就是传说中的原型。
JavaScript 规定,所有对象都有自己的原型对象(prototype)。
原型对象的作用,就是定义所有实例对象共享的属性和方法。
2. 原型链
Number
对象、String
对象、Boolean
对象,他们还有各自独有的公用属性库,他们的 __proto__
指向的就是各自的独有属性,这些独有属性的 __proto__
最终指向的 Object
的公有属性,就是Object.prototype
(原型),这一条链就叫原型链。引用情况如下图:

由此可知,
o1.toString === o2.toString //true
“原型链”(prototype chain):对象到原型,再到原型的原型。所有对象的原型最终都可以上溯到 Object.prototype
,即 Object
构造函数的 prototype
属性。也就是说,所有对象都继承了Object.prototype
的属性。
Object.prototype
对象有没有它的原型呢?回答是Object.prototype
的原型是 null
。

图中红色的线,就组成了一条原型链。
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
即 Function
是Number
、String
、Object
、Function
的构造函数。
注意:Function.__proto__.__proto__ === Object.prototype //true

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'
// 第一个.当作小数点,第二个为点操作符
网友评论