首先来看三个的各自含义函数
不管何时,只要建立函数,就会根据规则为该函数建立一个 prototype属性,这个属性指向函数的原型对象。在默认状况下,全部的原型对象,都会自动得到一个constructor属性。这个属性包含一个指向 prototype 属性所在函数的指针。
在建立了自定义构造函数以后,其原型对象默认只会取得 constructor 属性和从Object继承一些方法。
当调用构造函数建立一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象
例如:prototype
// 定义函数. 会默认为该函数建立prototype属性 function Person(){} // 建立实例对象, 实例对象会有默认的proto 属性 指向原型对象 var p = new Person()
图示:
指针
function foo(){} f1 = new foo;
图示:
code
注意:
原型对象Function.prototype的constructor属性指向构造函数Function();实例对象Object和Foo自己没有constructor属性,须要继承原型对象Function.prototype的constructor属性。对象
function Foo(){}; var f1 = new Foo; console.log(Function.prototype.constructor === Function);//true console.log(Foo.constructor === Function);//true console.log(Foo.hasOwnProperty('constructor'));//false console.log(Object.constructor === Function);//true console.log(Object.hasOwnProperty('constructor'));//false
其实,在对象去查找一个属性的时候,会如今对象自己上查找,若是不存在,则在其原型对象上查找,一直查找到null为止。这种经过原型层层链接起来的就称为成了原型链
注意: 原型对象能够被修改,能够被重写。注意修改和重写的区别:blog
function Foo(){} foo.prototype.name = 'fun' var f1 = new Foo; alert(f1.name); // fun 能够访问到原型对象上的属性
function Foo(){} Foo.prototype = { name:"foo" } var f1 = new Foo; alert(f1.name); // fun 能够访问到原型对象上的属性
注意当以这种字面量来建立,虽然结果是正确的可是 constructor 并不在指向 Foo 函数了。 而如今咱们彻底重写了prototype 对象了。(就是改变了Foo.prototype的指向一个新建立的对象)所以,constructor属性指向新对象的constructor属性(新对象由Objecct建立出来的,所以指向了Object构造函数)继承
console.log(f1 instanceof Objecct) // true console.log(f1 instanceof Foo) // true console.log(f1.constructor == Foo) // false console.log(f1.constructor == Object) // true
因此一般会在改变prototype时指定constructor属相原型链
unction Foo(){} Foo.prototype = { constructor: Foo, name:"foo" } var f1 = new Foo; alert(f1.name); // fun 能够访问到原型对象上的属性
其实原型对象和实例对象之间链接就一个指针,而非副本,这样松散的链接关系, 就可以让咱们在原型对象作的任何操做,在实例上当即反应出来。原型
function Foo(){} f1 = new Foo; // 这里改变对象自己, 此时 实例对象和构造函数的原型对象是同一地址 Foo.prototype.sayHello = function(){ console.log("hello") } f1.sayHello() // 'hello'
请记住,实例中的prototype指向原型对象,在建立时就构造函数已经决定了。 不会随着构造函数的原型对象指针的改变而发生改变。io
function Foo(){} f1 = new Foo; // 这里改变了指向。 此时 实例对象和构造函数的原型对象不在指向同一地址了 Foo.prototype = { constructor: Foo, sayHello : function(){ console.log("hello") } } f1.sayHello() // erro
重写原型对象切断了现有原型与任何以前已经存在的对象实例之间的联系,以前任何实例对象它们的引用仍然是最初的原型。而现有构造函数,以及以后建立的实例对象会指向重写以后的原型对象。