JavaScript中除了基本类型外的数据类型,都是对象。但是由于其没有 类(class)和"实例"(instance)的概念,如何将所有对象联系起来就成了一个问题,于是就有了原型和原型链的概念。
公用属性(原型(prototype))
每个对象都有toString()、valueof()等方法,但他们并其实没有单独的方法(为了节省空间),而是JS在每个对象里都存了一个隐藏属性:_proto_\,这个属性指向了存放公用属性的地址(Object.prototype),当用toString()时,就是调用的公用属性
var a1=new Number(1)
var a2 = new Number(10)
a1.toString() === a2.toString() // true
原型链
除函数Object以外的其他函数的原型对象在最后均会通过proto指向函数的原型对象,即Object.prototype,而函数Object的原型对象最后会通过proto指向null。
也就是 a1.__proto__.__proto__.__proto__ === null
这条链所对应的值
总之,所有的对象都有proto属性,而只有函数有prototype属性。
事实上 JavaScript 所有数据都可以以对象的形式表现:由于函数是对象,我们可以用构造函数的方法使得 Number、Boolean、String变成对象。
var 对象 = new 函数(); //函数可以是Number/String/Boolean/Object
对象.__proto__ === 构造函数.prototype //true
__proto__是对象的属性,prototype是函数的属性
而这些构造函数都是由 Function构造出来的, 所以
Function.__proto__ === Function.prototype
Array.__proto__ === Function.prototype
Object.__proto__ === Function.prototype
Number.__proto__ === Function.prototype
Boolean.__proto__ === Function.prototype
String.__proto__ === Function.prototype
Function.__proto_ === Function.prototype
这里最需要注意的是Function的构造函数就是Function,只有它的proto是指向自己的
举个例子:
这里的 a 是 Number 的实例,可以看到 n 里面有一个 __proto__ 指向 Number() 这个函数,Number() 就是 n 的原型对象(prototype) ;
而 Number() 函数有一个 __proto__ 指向 Object() 函数 ,Object() 是 Number() 的原型对象,Number 是 Object 的实例;
Object() 函数里存在 hasOwnProrerty 证明已经到达最后的属性层,再往后就是对象 null。
也就是
a.__proto__ === Number.prototype // true
Number.__proto__ === Function.prototype //true
Number.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__ === null //true
面试题:
'1'.__proto__是什么?
答:’1’会临时转化为String对象
'1'.__proto__ === String.prototype //true
所有对象都有__proto__属性
Object.prototype.__proto__ === null;
1.toString() //语法错误,不加引号JS会把.当作小数点
1..toString() //'1',第一个.当作小数点,第二个为点操作符
参考: