在之前的文章[笔记][JavaScript]物件间基本的原型链(1)中有解释过物件的继承功能,他可以优先建立一个拥有function的物件,再提供给其他物件去继承,并使用他的function,简单的例子如下:
//建立一个有个function的物件var printData = { writeName:function(){ return 'Name is ' + this.name; },}//再建立其他拥有特性name的物件并继承自printDatavar objA = Object.create(printData,{ name:{value:'A'}});var objB = Object.create(printData,{ name:{value:'B'}});//由这些物件去使用printData中的函式objA.writeName(); //输出 'Name is A'objB.writeName(); //输出 'Name is B'
上述的例子,objA和objB的原型物件都是printData,也共享了他的特性。
当然如果不使用这种方式,我们也可以利用[笔记][JavaScript]使用call()、apply()、bind()设定函式中的「this」这篇所讲的,改变this来呼叫共用的函式,例如:
//建立一个有个function的物件var printData = { writeName:function(){ return 'Name is ' + this.name; },};//个别建立两个拥有特性name的物件var objA = { name:'A',};var objB = { name:'B',};//使用call来呼叫printData.writeName()并将this指定为objA及bjBprintData.writeName.call(objA); //输出 'Name is A'printData.writeName.call(objB); //输出 'Name is B'
上面两个方式都可以做到相同的事情,接着我们试把printData转为建构器,让他可以建立像objA和objB那样的物件,像这样子经由建构器所创造出来的物件就被称做为建构器的实体,这样子的实体和objA与objB在概念上是一样的,他们的资料(特性name)都是属于实体的自有特性中,而他们的事件共享于同一个建构器的原型(printData)。
以下做个简单的例子:
//因为建构器是由new调用的函式,所以先建立一个具名函式Write,第一个字大写是因为之前看书说建构器的开头通常是大写,用来和一般函式做分别。//这个函式拥有一个参数,他会在透过new去调用时把name这个参数传入创造出来的实体中做为他的自有特性function Write(name){ this.name = name;};//接着为该Write的原型添加事件,这些原型事件会被创造出来的实体继承Write.prototype.writeName = function(){ return 'Name is ' + this.name;};//最后我们使用new来调用Write让他建立一个继承了Write.prototype的实体物件,这时候A会被传入objA里执行this.name = 'A',也就是objA.name = 'A'var objA = new Write('A');//现在呼叫建构器的原型(Write.prototype)方法(writeName)objA.writeName(); //输出 'Name is A'//第二个物件也可以使用建构器去创造var objB = new Write('B');objB.writeName(); //输出 'Name is B'//每个透过建构器产生出来的实体的特性constructor都会指向建构器本身objA.constructor == Write; //回传true//但是constructor特性的值是可以修改的,所以也可以使用instanceof检查物件是否为建构器的实体objA instanceof Write //回传true
以上就是用建构器创造实体物件的做法,如果我有观念错误或解释不清楚的地方,还麻烦各位大大指点了,谢谢大家!