之前写过一篇简单的通过prototype构建对象prototype构建对象,前几天从新看了一下书,记录一下prototype的细节
我们可以通过字面量形式创建对象,也可以通过构造函数来创建(就是new 关键字+ 函数名称)。 一个普通的函数可以通过new 变的特殊。
我们每创建一个函数,这个函数都有一个prototype属性,这个属性是一个对象,这个对象包含的key->value键值对,是由这个函数通过new 构造方法创建的所有实例共享的。(也是由所有原型对象为 由该函数创建的实例 的对象共享)
function Person() { }
Person.prototype //所有Person的实例都共享这个对象
通过构造函数创建一个实例之后,这个实例内部有一个指针[[prototype]]指向的函数的原型对象。
var p = new Person()
Object.getPrototypeOf(p) === Person.prototype //true
所有的实例都是共享这个原型对象,请注意共享的是同一个对象,不是原型对象的拷贝。
所有函数创建的时候(没有手动更改原型对象的前提下),函数的原型对象是JS 根对象 Object的实例。
function Animal() {}
// 实例内部指针 应该与函数的prototype指向的对象是同一个
// 下面的结果是true
Object.getPrototypeOf(Animal.prototype)=== Object.prototype
// 下面的结果也是true,因为Animal是Function的一个实例
// Object.getPrototypeOf(Animal) === Function.prototype //true
Object.getPrototypeOf(Function.prototype) === Object.prototype
Object.getPrototypeOf(Object) === Function.prototype //true
上面表述有错误,博主也晕了,看这个文章:
JavaScript instanceof 运算符深入剖析 :
https://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/index.html
tips: 原型对象必须是对象,我们给其设置为非对象属性,将会无效。
function Foo() {}
Foo.prototype = "string"
var foo = new Foo()
//函数的prototype属性指向的原型对象生效的话
//下面的判断应该是true,但是是false
Object.getPrototypeOf(foo) === "string"
String 是继承自Object
// 下面的结果为true
Object.getPrototypeOf(String.prototype) === Object.prototype
原型链继承, 原理很简单,假入Person 继承 Animal , 代码这样写:
//snippet one
function Animal() {}
function Person() {}
Person.prototype = new Animal()
//但是上面的代码将Person之前的原型对象(Object的实例)全部覆盖了,之前的原型对象里面的constructor属性(值为Person)也就没有了,现在我们执行下面的代码:
var p = new Person()
p.constructor // 是函数Animal 而不是 Person
p.constructor === Animal //true
所以我们将 代码 snippet one 改变一下:
//snippet one
function Animal() {}
function Person() {}
Person.prototype = new Animal()
Object.defineProperty(Person.prototype,
'constructor',
{ enumarable: false, value: Person }
)
这样Person的实例constructor指向的就是Person 而不是Animal。
参考:《javascript高级程序》第六章