Javascript中的原型与原型链

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

参考:

MDN 继承与原型链

Javascript继承机制的设计思想 by 阮一峰的网络日志

对象的继承 by 阮一峰

你可能感兴趣的:(Javascript中的原型与原型链)