首先,上一篇文章详细分析了原型属性和自身属性的区别,但为了让你们更明白一点,因此这里讲一下为何须要原型。但要讲原型就必须讲构造函数,讲构造函数就必须讲对象。首先来看看对象。程序员
var newObj = new Object; newObj.name = "keti"; newObj.color = "red"; newObj.changeColor = function(color){ newObj.color = color; }
这种方法看上去很蠢,因此咱们找到另外一种方法:使用literal直接建立,看上去要优雅得多:架构
var newObj = { name: "keti"; color: "red"; changeColor: function(color){ newObj.color = color; } }
使用literal来常见对象彷佛很不错,比较直观,两个卷括号括起来就是个对象嘛,多清晰明了。可是若是你要建立一系列结构相似的对象,难道要这样一个个写吗?做为程序员咱们的遵循的理念就是尽量减小重复,也就是著名的DRY(Don't Repeat Youself)。因此咱们是没法容忍这么愚蠢的事情发生的,所以就有了构造函数,跟类有点类似,但咱们这里不讨论类。构造函数就是创建一个模板,不绑定数据,只提供架构,你只需把相关数据填充到模板里就能够生成一个新的对象了:函数
function NewObj(name,color){ this.name = name; this.color = color; this.changeColor = function(c){ this.color = c; } } var newObj1 = new NewObj("keti","red");
上面代码中,new是一个构造器,NewObj是咱们建立好的模板,填入数据,赋给变量newObj1,ok,新的对象就这样生成了。this
到此建立对象的方法彷佛已经很不错了,但仔细观察咱们还发现了新的问题:对于changeColor()这个方法事实上对全部instance来讲是相同的,也就是说能够共享,不像name和color那样须要绑定给每一个instance。而构造函数这种形式每次都会把自身的属性所有copy一份给每一个instance,这就形成了没必要要的浪费;而且,当咱们想修改这个方法时,就必须从新生成全部的instance才能得到更新,好比说:prototype
function NewObj(name,num){ this.name = name; this.num = num; this.changNum = function(c){ this.num = c; } } var newObj1 = new NewObj("kemi",10); newObj1.changNum(100); newObj1.num; //很明显是100
我如今想修改changNum()这个函数:指针
function NewObj(name,num){ this.name = name; this.num = num; this.changNum = function(c){ this.num = c*2; } } newObj1.changNum(100); newObj1.num; //依然是100,也就是说这个对象并不受咱们修改的模板影响到
怎么解决这个问题呢?有一个原型对象。原型对象里的属性和方法并非像构造函数自身属性同样copy给每一个instance,而是“引用”,也能够理解为给每一个instance提供一个指向该原型对象的指针,这样每一个instance就能找到原型对象里的属性,而很明显,这是一种共享,也就是说,当你修改了这个原型里的属性,那么全部共享该属性的instance都能得到这个修改。所以,原型刚好解决了上面提到的两个问题。code
function NewObj(name,num){ this.name = name; this.num = num; } NewObj.prototype.changNum = function(c){ this.num = c; } var newObj1 = new NewObj("kemi",10); newObj1.changNum(100); newObj1.num; //很明显是100 NewObj.prototype.changNum = function(c){ this.num = c*2; }//咱们从新修改一下这个方法 newObj1.changNum(100); newObj1.num; //变成200了。
为何通常状况下会把属性直接写在构造函数内,而方法经过prototype添加呢?这两种方式的区别上面其实已经有所展示了:大部分的instance的属性都是不一样的,好比说name,所以在构造函数内经过this直接绑定给instance无疑是个好方案,而方法一般是通用的,使用prototype可让每一个instance共享同一个方法,而不用每一个都copy一次,又能实现实时更新。对象