在javascript中,创建对象的方式有很多种。假设我们要创建一个描述人的对象,这个对象有一个name属性和一个speak方法。针对这种情况,我们下面会一一列举不同的实现方式。
1.直接创建对象
var obj = new Object();
obj.name = 'david';
obj.speak = function(){
alert(this.name);
}
2.对象字面量的方式
var obj = {
name:'david',
speak:function(){
alert(this.name);
}
}
以上两种是最常见的创建对象方式,能够解决大部分的变量创建场景。然而,当你需要创建多个相似的对象,以上方法就显得比较乏力了,你需要不断的写重复代码。这时候,你需要引入一些设计模式来解决这个问题。
3.工厂模式
function createPeople(name){
var obj = new Object();
obj.name = name;
obj.speak = function(){
alert(this.name);
}
return obj;
}
createPeople('people1');
createPeople('people2');
createPeople('people3');
...
工厂模式这种动态创建对象的方式能够解决大部分的创建多个对象场景。然而上面的工厂模式仍有所不足。
1.创建的对象之间毫无关系。
2.每次创建对象都动态创建了匿名函数,占据了而外的内存空间。而实际上这些方法都可以公用。
因而,我们引入了构造函数。
4.构造函数
什么叫构造函数呢?它实际上就是一个普通函数,只是它跟普通函数有些区别,比如:
1.我们建议用首字母大写的函数名在区别普通函数。
2.没有return语句。
3.内部有this变量。
4.使用new关键字调用。
然后,我们用一个new关键字去创建对象。
function People(name){
this.name = name;
this.speak = function(){
alert(this.name);
}
}
var david = new People('david');
david.speak();//david
var jimmy = new People('jimmy');
jimmy.speak();//jimmy
上述例子中,我们成功创建了一个david对象。然而它是怎么实现创建对象的呢?实际上在new一个构造函数时,它做了如下4个动作:
function people(name){
var obj = new Object();//1.动态创建对象
People.apply(obj,arguments);//2.把this对象指向新创建的对象
obj.__proto__ = People.prototype;//3.把对象的__proto__属性指向对象的prototype
return obj;//4.返回对象
}
var david = people('david');
var jimmy = people('jimmy');
david.speak();//david
jimmy.speak();//jimmy
通过构造函数创建的对象,彼此是有联系的。每一个通过构造函数创建的对象,都会有一个内置的constructor属性,该属性指向构造方法。
david.constructor === People//true
jimmy.constructor === People//true
并且,我们可以通过instanceof 来识别对象。
david instanceof People//true
jimmy instanceof People//true
这样就解决了对象的识别问题。然而用构造函数创建变量,还是没有解决重复创建实例方法的问题,每次创建对象,仍然会创建匿名函数并指向speak。有没有一种方式能够让实例对象共享方法或者属性呢?
jimmy.speak===david.speak//false
为了解决实例的属性、方法共享问题。javascript引入了原型的概念。
具体查看我的其中一篇文章。
5.原型
function People(name){
this.name = name;
}
People.prototype.speak = function(){
alert(this.name);
}
var david = new People('david');
var jimmy = new People('jimmy');
david.speak===jimmy.speak;//true
这种方式把需要共享的方法放到原型中,当访问实例对象中的属性或者函数时,如果在实例对象中找不到,则会在其原型对象中查找。这就避免了重复创建函数的弊端了~
(这其实不是纯粹的原型模式,而是构造函数和原型组成的新模式。在javascript权威指南中,原型模式把所有属性、方法都放在原型对象上。个人觉得这里生硬的拆开构造函数和原型有些不妥,会让新手困惑。原型、构造函数、实例对象的关系可以查看我的另一篇博文http://www.jianshu.com/p/753322534214
网友评论