创建对象最简单的方法,就是创建一个Object对象,然后为它添加属性和方法。
如果一个对象成员引用了一个函数,该成员就被称为一个"方法",如果一个对象成员引用了一个非函数,该成员就被称为"属性"。
看下面这个例子:
var person = new Object();
person.name = "Tony";
//创建了书一个方法(因为引用了函数)
person.sayName = function(){
//this前面讲过,指的是当前函数的对象,在这里指的就是person对象
alert(this.name);
};
person.sayName(); //输出结果显而易见 Tony
缺点:使用同一个接口创建很多相似对象,会产生大量的重复代码。(为了解决这个问题---工厂模式出现了)
用函数来封装用特定接口创建对象的细节
比如下面这个例子:
function createPerson(name,age,job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var person1 = createPerson("Tony",23,"worker");
var person2 = createPerson("Tom",18,"student");
person1.sayName(); //Tony
person2.sayName(); //Tom
函数createPerson()能够根据接受的三个参数来创建一个包含
所有信息的Person对象。
优点:解决了传统方法里创建多个相似对象的问题。
缺点:没有解决对象识别的问题。(可以靠构造函数模式来解决)
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var person1 =new Person("Tony",23,"worker");
var person2 =new Person("Tom",18,"student");
person1.sayName(); //Tony
person2.sayName(); //Tom
与工厂模式的不同之处:
优点:动态的传递参数
缺点:每创建一个对象就会创建相同的方法函数对象,占用大量内存。(可以用原型模式来解决)
alert(person1.sayName == person2.sayName) //false
由上代码可以看出来,这两个Function实例并不相等,然而创建两个完成同样任务的Function实例没有必要。
将对象属性及方法定义都写在对象的prototype里面
function Person(){
}
Person.prototype.name = "Tony";
Person.prototype.age = 22;
Person.prototype.job = "worker";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName();//Tony
var person2 = new Person();
//这里就是原型模式的缺点:无法动态传递构造参数
person2.sayName();//Tony
//正好与上文中的构造函数相反,这里是相同的Function对象
alert(person1.sayName == person2.sayName); //true
优点:每次创建对象时都是使用相同prototype中的方法,不会占用重复的内存 缺点:无法动态传递构造参数(构造函数模式可以解决)
function Person(name,age,job){ //构造函数模式
this.name = name;
this.age = age;
this.job =job;
this.friends = ["S","C"];
}
Person.prototype = { //原型模式
constructor : Person,
sayName:function(){
alert(this.name);
}
}
var person1 = new Person("Tony",22,"worker");
var person2 = new Person("Tom",18,"student");
//person1里面添加了V,并不影响person2,因为他们引用的是不同数组
person1.friends.push("V");
alert(person1.friends); //s,c,v
alert(person2.friends); //s,c
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true
优点:综合了constructor及prototype方式的优点,可以动态传递构造参数,并且方法函数对象也只创建一个。 缺点:函数写在对象外面,不太符合面向对象的思想(可以用动态原型的方式来解决)
加一个判断属性,来判断该对象是否已经被创建过,如果被创建过,则方法就不在构建
function Person(name,age,job){
//属性
this.name = name;
this.age = age;
this.job = job;
//方法
//只有在sayName方法不存时,才会添加到原型中
if(typeof this.sayName !="function"){
Person.prototype.sayName = function(){
alert(this.name);
};
}
}
var person = new Person("Tony",22,"worker");
person.sayName();
优点:将原型函数写在对象定义里面
缺点:不支持继承