Javascript創建對象
Javascript作爲一門動態性的面向對象的編程語言,其核心思想就是一切皆對象。爲了深入理解Javascript面向對象的編程思想,本文總結了幾種常見的創建JS對象的方法,比較了各自的優缺點以及使用場景。掌握這些創建對象的模式也是進一步閱讀jQuery等框架源碼,以及以後開發自己的插件等所必需的。
參考書籍:《Javascript高級程序設計》(第3版)、《Javascript權威指南》
對象字面量
這是創建對象最簡單的方式,對象是由若干“名/值”對組成的映射表:
var obj = {"name": "obj"; "age": 24};
工廠模式
工廠模式是軟件工程領域一種廣爲人知的設計模式,用函數來封裝並以特定接口創建對象的細節,實現方式如下:
// 在函數內創建對象,給新創建的對象添加屬性和方法,並顯示的返回。
function createObj(name){
var obj = new Object();
obj.name = name;
obj.getName = function(){
return this.name;
};
return obj;
}
var person = createObj("Test");
person.getName(); //Test
函數createObj()能夠根據接受的參數來創建一個person對象;可見,工廠模式可以創建多個相似對象,但是我們不能確定通過工廠模式創建的對象的類型。
構造函數模式
構造函數可以創建特定類型(Array、Object)的對象,也可以創建自定義的對象,併爲對象定義自定義的屬性和方法:
//使用原生的構造函數
var arr = new Array(); //創建一個數組對象
var myDate = new Date(); //創建一個date對象
function Person(name, age){
this.name = name;
this.age = age;
this.sayName = function(){
return this.name;
};
}
var person1 = new Person("Xiao", 24); //用自定義的構造函數創建一個對象
需要注意的是,自定義的構造函數名一般以大寫字母開頭。
使用構造函數創建對象必須使用new操作符,這裏new操作符主要做了這幾件事:
1. 創建一個新對象;
2. 把構造函數的this指向新對象;
3. 爲新對象添加屬性和方法;
4. 返回這個新對象。
構造函數模式可以創建特定類型的對象實例,但是它的主要缺點是構造函數中的方法要在每個實例上重新創建一遍,但是方法都是Function的實例,所以構造函數的不同實例的同名函數其實是不相等的。
原型模式
我們創建每一個函數都有一個prototype屬性,它指向一個對象,該對象包含有特定類型的所有實例共享的屬性和方法。也就是說prototype就是通過構造函數創建的對象實例的原型對象。因此,我們可以在原型對象上定義屬性和方法,而不必在構造函數中定義:
function Person(){};
Person.prototype.name = "Hanks";
Person.prototype = 24;
Person.prototype.sayName = function(){
return this.name;
};
var person1 = new Person();
person1.sayName(); // Hanks
var person2 = new Person();
person2.sayName(); //Hanks
person2.name = "Gray";
person2.sayName(); //Gray
更簡單的原型語法: 將原型對象中的所有屬性和方法寫在一個對象字面量中(相當於重寫原型對象)。原型模式的主要問題是:所有實例都會取得相同的默認值,而且更致命的是一個實例修改原型對象的某個屬性會在所有實例中體現出來。
構造函數與原型的組合模式
這種方式是創建自定義類型最常見的模式,用構造函數模式定義實例屬性,而用原型模式定義共享的屬性和方法。這種模式集兩者之長,不僅支持傳遞參數,還最大限度的節省了內存。
function Person(name, age){
this.name = name;
this.age = age;
};
Person.prototype.sayName = function(){
return this.name;
};
動態原型模式
這種模式將原型的初始化放在構造函數中進行,通過判斷某個方法是否已定義來決定是否需要初始化原型:
function Person(name, age){
this.name = name;
this.age = age;
//僅在sayName函數未定義的時候(初次調用)才初始化原型對象
if(typeof sayName != "function"){
Person.prototype.sayName = function(){
return this.name;
};
}
};
寄生構造函數模式
基本思想是創建一個函數,用於封裝創建對象的代碼,然後再返回新創建的對象,注意與工廠模式的區別。
// 在函數內創建對象,給新創建的對象添加屬性和方法,並顯示的返回。
function Person(name){
var obj = new Object();
obj.name = name;
obj.getName = function(){
return this.name;
};
return obj;
}
//與工廠模式的區別:這裏用new操作符創建實例
var person = new Person("Test");
person.getName(); //Test
該模式可用來爲某些構造函數添加一些額外的方法,但是又不想直接修改原來的構造函數(如不想修改原生的Array構造函數)
穩妥構造函數模式
穩妥對象沒有公共屬性和方法,構造函數中紅不使用this對象,注意與寄生構造函數模式的區別
// 在函數內創建對象,給新創建的對象添加屬性和方法,並顯示的返回。
function Person(name){
var obj = new Object();
var name = name;
obj.getName = function(){
//不引用this
return name;
};
return obj;
}
//與工廠模式的區別:這裏用new操作符創建實例
var person = Person("Test");
person.getName(); //Test
除了使用sayName()方法外,沒有其他方式可以訪問其中的數據成員。
以上8種創建JS對象的方法中,原型與構造函數組合模式和動態原型模式是一定要掌握的,具體使用哪一種模式需要根據具體的項目及要求來選擇。