创建对象最简单的方法,就是创建一个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();
优点:将原型函数写在对象定义里面
缺点:不支持继承