原型只是一个被称为“原型”的空对象属性。全部的函数都是由Function()构造函数建立的。当建立函数实例时,它老是拥有一个prototype属性,这是一个空对象。函数
prototype属性来自Function()构造函数。spa
prototype属性是JavaScript为每一个Function()实例建立的一个对象,它经过new关键字建立的对象实例连接回建立它们的构造函数。prototype
prototype属性的值能够设置为JavaScript中任何可用的复杂值(对象),JavaScript将忽略任何设置为原始值的prototype属性。code
将构造函数建立的实例连接于构造函数的prototype属性,意味着 任什么时候候使用new关键字建立对象时,它都会在建立的对象实例和建立对象的构造函数的prototype属性之间添加一个隐藏的连接。该连接在实例中被称为 __proto__对象
var my = new Array();
my.constructor === Array
my.constructor.prototype === Array.prototype
my.__proto__ === Array.prototype
Array.prototype.constructor == Array
因为prototype属性是一个对象,所以原型链或查找中的最后一站是Object.prototype。blog
var my = []; console.log(my.foo); //先在my对象中查找foo //若是没有找到,再到Array.prototype中查找 //若是没有找到,再到Object.prototype中查找 //若是也没有找到,则返回undefined
与做用域链同样,原型链在链查找时将使用它找到的第一个值。ip
Object.prototype.foo = 1;
Array.prototype.foo = 2; var my = []; console.log(my.foo)//输出2,在Array.prototype.foo上查找到 my.foo = 3; console.log(my.foo)//输出3,在my.foo上查找到
使用新对象替换prototype属性会删除默认构造函数(constructor)属性,除非手动指定一个。原型链
var Foo = function(){} Foo.prototype = {} var myFoo = new Foo(); //myFoo.constructor !== Foo //myFoo.constructor 为Object(),而非Foo() var Bar = function(){} var myBar = new Bar() //myBar.constructor === Bar //myBar.constructor 为Bar() var Hea = function(){} Hea.prototype = { constructor:Hea } var myHea = new Hea() //myHea.constructor === Hea //myHea.constructor 为Hea()
prototype属性是动态的。实例老是能从原型得到最新的值,无论什么时候被实例化、更改、附加。作用域
var Foo = function(){} Foo.prototype.x = 1 var my = new Foo() //my.x 输出1 Foo.prototype.x = 2 //my.x 输出2
建立一个实例时,该实例将在实例化时被绑定到“刚完成的”原型。提供一个新对象做为prototype属性,不会更新已建立的实例和新原型之间的链接。一旦开始建立实例,就不该该用一个新对象来替换对象的原型。原型
var Foo = function(){} Foo.prototype.x = 1;
var my = new Foo(); //my.x 输出1 //使用新对象覆盖Foo的原型 Foo.prototype = { x:2 } //my.x 仍是输出1,my依然引用的是初始化时的原型对象 var bar = new Foo(); //bar.x 输出2 新对象实例bar引用的是新原型对象