标签:
殊不知,JavaScript的世界中的对象,追根溯源来自于一个 null
「一切皆为对象」,这句着实是一手好营销,易记,易上口,印象深刻。
万物初生时,一个null对象,凭空而生,接着Object、Function学着null的模样塑造了自己,并且它们彼此之间喜结连理,提供了prototype和constructor,一个给子孙提供了基因,一个则制造万千子子孙孙。
在JavaScript中,null也是作为一个对象存在,基于它继承的子子孙孙,当属对象。乍一看,null像是上帝,而Object和Function犹如JavaScript世界中的亚当与夏娃。
__proto__在JavaScript中,每个对象都拥有一个原型对象,而指向该原型对象的内部指针则是__proto__,通过它可以从中继承原型对象的属性,原型是JavaScript中的基因链接,有了这个,才能知道这个对象的祖祖辈辈。从对象中的__proto__可以访问到他所继承的原型对象。
var a = new Array();
a.__proto__ === Array.prototype // true
上面代码中,创建了一个Array的实例a,该实例的原型指向了Array.prototype。Array.prototype本身也是一个对象,也有继承的原型:
a.__proto__.__proto__ === Object.prototype // true
// 等同于 Array.prototype.__proto__ === Object.prototype
这就说了明了,Array本身也是继承自Object的,那么Object的原型指向的是谁呢?
a.__proto__.__proto__.__proto__ === null // true
// 等同于 Object.prototype.__proto__ === null
所以说,JavaScript中的对象,追根溯源都是来自一个null对象。佛曰:万物皆空,善哉善哉。
除了使用.__proto__方式访问对象的原型,还可以通过Object.getPrototypeOf方法来获取对象的原型,以及通过Object.setPrototypeOf方法来重写对象的原型。
值得注意的是,按照语言标准,__proto__属性只有浏览器才需要部署,其他环境可以没有这个属性,而且前后的两根下划线,表示它本质是一个内部属性,不应该对使用者暴露。因此,应该尽量少用这个属性,而是用 Object.getPrototypeof和Object.setPrototypeOf,进行原型对象的读写操作。这里用__proto__属性来描述对象中的原型,是因为这样来得更加形象,且容易理解。
prototype函数作为JavaScript中的一等公民,它既是函数又是对象,函数的原型指向的是Function.prototype
var Foo = function() {}
Foo.__proto__ === Function.prototype // true
函数实例除了拥有__proto__属性之外,还拥有prototype属性。通过该函数构造的新的实例对象,其原型指针__proto__会指向该函数的prototype属性。
var a = new Foo();
a.__proto__ === Foo.prototype; // true
而函数的prototype属性,本身是一个由Object构造的实例对象。
Foo.prototype.__proto__ === Object.prototype; // true
prototype属性很特殊,它还有一个隐式的constructor,指向了构造函数本身。
Foo.prototype.constructor === Foo; // true
a.constructor === Foo; // true
a.constructor === Foo.prototype.constructor; // true
标签:
原文地址:http://www.cnblogs.com/hyea/p/5636077.html