可以讲的太多了,就挑重点说了。本文主要依据这篇文章写的,加上了自己的一些想法,以后自己学习中迷惑了再回头看看。
先贴出代码:
//创建一个函数b var b = function(){ var one; } //使用b创建一个对象实例c var c = new b(); //查看b 和c的构造函数 b.constructor; // function Function() { [native code]} b.constructor==Function.constructor; //true c.constructor; //实例c的构造函数 即 b function(){ var one; } c.constructor==b //true //b是一个函数,查看b的原型如下 b.constructor.prototype // function (){} b.__proto__ //function (){} //b是一个函数,由于javascript没有在构造函数constructor和函数function之间做区分,所以函数像constructor一样, //有一个原型属性,这和函数的原型(b.__proto__ 或者b.construtor.prototype)是不一样的 b.prototype //[object Object] 函数b的原型属性 b.prototype==b.constructor.prototype //fasle b.prototype==b.__proto__ //false b.__proto__==b.constructor.prototype //true //c是一个由b创建的对象实例,查看c的原型如下 c.constructor.prototype //[object Object] 这是对象的原型 c.__proto__ //[object Object] 这是对象的原型 c.constructor.prototype==b.constructor.prototype; //false c的原型和b的原型比较 c.constructor.prototype==b.prototype; //true c的原型和b的原型属性比较 //为函数b的原型属性添加一个属性max b.prototype.max = 3 //实例c也有了一个属性max c.max //3
原型,说起来复杂,实际上就是一个对象。js中万物皆为对象,所有对象又可以成为一个原型。
某函数的原型属性是一个对象,这个函数被用作构造函数来创建实例时,该函数的原型属性将被作为原型赋值给所有的对象实例。
也就是说你定义的实例引用的并不是函数的原型,而是原型属性。(在原型属性上可以定义很多方法给自己使用)
所以代码中存在这样一段代码:
c.constructor.prototype==b.prototype; //true
实例的原型属性对应它引用的原型属性
下面解释一下__proto__,prototype和constructor。
__proto__:实例的方法,实例可以通过它指向自己的原型,类似一个指针,具有指向作用.
prototype:原型属性。代码中b是有原型属性的,因为它本身就是一个原型。但c没有原型属性,它只能通过__proto__方法(constructor.prototype方法后文讲)来获取原型。
constructor:构造函数.b.constructor当然就是函数体本身.c.constructor是它引用的原型属性对应的原型的构造函数,也就是b.
所以可以说实例c的原型就是对b的原型属性的引用。
所以通过c.constructor先取得c的构造函数(也就是c本身),在通过prototype指向原型属性,也就取得了c的原型,即b的原型属性。
修改原型属性,构造函数的实例将获得构造函数的最新版本:
var a=function(x){ this.x=x; } var s=new a(9); s.x;//9 a.prototype.y=12;//通过prototype改变原型a的原型属性 s.y;//12
修改原型,不会反应到创建的实例中
var a=function(x){ this.x=x; } var s=new a(9); s.x;//9 a.__proto__.y=12; s.y;//undefined;
替换实例属性为一个新的对象,实例对象的原型依然引用原来被创建的原型属性
var a=function(x){ this.x=x; }; var s=new a(9); s.x; a.prototype={y:12}; s.y;//null