本文转载自: http://www.phpfuns.com/scripts/javascript/five-method-define-javascript-object.shtml
JavaScript中定义对象的5种方式(JavaScript中没有类的概念,只有对象)
i)基于已有对象扩充其属性和方法
var object = new Object(); object.name = "zhangsan"; // 添加name属性 object.sayName = function(name){//添加sayName方法 this.name = name; alert(this.name); }; object.sayName("kyle");//调用sayName方法,name属性被修改为kyle,浏览器将打印kyle
最简单的一种方式,使用起来并不方便,适合于临时需要一个对象。
ii)工厂方式创建对象
不带参数的工厂方法:
//工厂方法 function createObject(){ var object = new Object(); //创建一个对象 object.name = "zhangsan"; //为该对象添加一个name属性 object.password = "123"; //为该对象添加一个password属性 object.get = function(){ //为该对象添加一个get方法 alert(this.name+","+this.password); }; return object; //返回该对象 } var object1 = createObject(); //调用createObject工厂方法创建对象object1 var object2 = createObject(); //调用createObject工厂方法创建对象object2 object1.get(); //调用对象get方法 object2.get(); //调用对象get方法
带参数的工厂方法:
function createObject(name, password) { var object = new Object(); object.name = name; object.password = password; object.get = function() { alert(this.name + "," + this.password); }; return object; } var object1 = createObject("zhangsan", "123"); var object2 = createObject("lisi", "456"); object1.get(); object2.get();
上面两种不带参数和带参数的工厂方法缺点:
每创建一个对象,内存中就创建一个get方法,比较浪费内存,且影响性能。而我们的期望是,创建两个不同的对象,它们的属性是不一样的,但方法是共用的。所以接下来我们需要改进createObject工厂方法。
改进的工厂方法:
// 把get()放在外面实现共用 function get() { alert(this.name + "," + this.password); }
function createObject(name, password) { var object = new Object(); object.name = name; object.password = password; object.get = get; return object; } var object1 = createObject("zhangsan", "123"); var object2 = createObject("lisi", "456"); object1.get(); object2.get();
将get方法定义在createObject函数外面,这样每创建一个对象,get方法都是共用的。让一个函数对象被多个对象所共享,而不是每一个对象都拥有一个函数对象。
iii)构造函数方式创建对象
不带参数的构造函数
function Person(){ //在执行第一行代码前,js引擎会为我们生成一个对象 this.name = "zhangsan"; this.password = "123"; this.getInfo = function(){ alert(this.name+","+this.password); }; //此处有一个隐含的return语句,用于将之前生成的对象返回(也是跟工厂方式不一样的地方) } var p1 = new Person(); p1.getInfo();
带参数的构造函数
function Person(name, password) { this.name = name; this.password = password; this.getInfo = function() { alert(this.name + "," + this.password); }; } var p1 = new Person("zhangsan", "123"); var p2 = new Person("lisi", "456"); p1.getInfo(); p2.getInfo();
iv)原型(prototype)方式创建对象
prototype是Object对象里面的一个属性,
function Person() { } Person.prototype.name = "zhangsan"; Person.prototype.password = "123"; Person.prototype.getInfo = function() { alert(this.name + "," + this.password); }; var p1 = new Person(); var p2 = new Person(); p1.name = "kyle";// 对象生成之后再去改变属性 p1.getInfo(); p2.getInfo();
单纯地使用原型方式有两个问题:第一,你无法在构造函数中为属性赋初值,只能在对象生成之后再去改变属性值。
function Person() { } Person.prototype.name = new Array(); Person.prototype.password = "123"; Person.prototype.getInfo = function() { alert(this.name + "," + this.password); }; var p1 = new Person(); var p2 = new Person(); p1.name.push("zhangsan"); p1.name.push("lisi"); p1.password = "456"; p1.getInfo(); p2.getInfo();
浏览器将会打印:zhangsan,lisi,456和zhangsan,lisi,123.
如果使用原型方式创建对象,那么生成的所有对象会共享原型中的属性,这样一个对象改变了该属性也会反应到其他对象当中。所以单纯地使用原型方式是不行的,还需要结合其他方式。接下来我们会继续介绍。
使用原型+构造函数方式来定义对象
function Person() { this.name = new Array(); this.password = "123"; } Person.prototype.getInfo = function() { alert(this.name + "," + this.password); }; var p1 = new Person(); var p2 = new Person(); p1.name.push("zhangsan"); p2.name.push("lisi"); p1.getInfo(); p2.getInfo();
使用原型+构造函数方式来定义对象,对象之间的属性互不干扰,各个对象间共享同一个方法,这是一种比较好的方式。
v)动态原型方式
function Person() { this.name = "zhangsan"; this.password = "123"; if (typeof Person.flag == "undefined") { alert("invoked"); Person.prototype.getInfo = function() { alert(this.name + "," + this.password); }; Person.flag = true; } } var p1 = new Person(); var p2 = new Person(); p1.getInfo(); p2.getInfo();
在动态原型方式中,在构造函数中通过标志量让所有对象共享一个方法,而每个对象拥有自己的属性。上面代码在第一次创建对象时,首先通过一个判断语 句,看flag属性是否已经定义,若没有定义,则通过原型方式添加getInfo方法,然后将flag设置为true,那么当第二次创建对象时,if语句 判断为假,跳过执行。这样就达到了我们所期望的结果,创建的对象属性是互不干扰的,而对象的方法是共享的。