ITEEDU

javascript创建对象详解

传统的方法

创建对象最简单的方法,就是创建一个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

与工厂模式的不同之处:

  1. 没有显示地创建构造函数
  2. 直接将属性和方法赋给了this对象
  3. 没有return语句

优点:动态的传递参数

缺点:每创建一个对象就会创建相同的方法函数对象,占用大量内存。(可以用原型模式来解决)

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();

优点:将原型函数写在对象定义里面

缺点:不支持继承