Javascript高級程序設(shè)計(第2版) 6.1創(chuàng)建對象 閱讀整理
-
最簡單方式,創(chuàng)建一個object的實例堕虹,然后添加屬性方法
var person = new Object(); person.name = "rk-coder"; person.age = 26; person.sayName = function (){ console.log(this.name); }; person.sayName();
缺點:創(chuàng)建大量對象掉伏,產(chǎn)生大量的重復(fù)代碼君丁。
-
工廠模式
function createPerson(name, age){ var o = new Object(); o.name = name; o.age = age; o.sayName = function (){ console.log(this.name); }; return o; } var person1 = createPerson("rk-coder", 26); var person2 = createPerson("rk-coder2", 27); person1.sayName();//rk-coder person2.sayName();//rk-coder2
缺點:無法識別對象及對象類型
-
構(gòu)造函數(shù)模式
ECMAScript中的構(gòu)造函數(shù)可以用來創(chuàng)建特定類型的對象筷凤。構(gòu)造函數(shù)不同于其他函數(shù)痴怨,為了區(qū)別按照慣例,構(gòu)造函數(shù)的函數(shù)名首字母大寫上祈,另外通過構(gòu)造函數(shù)創(chuàng)建實例喊崖,必須使用new
操作符。function Person(name, age){ this.name = name; this.age = age; this.sayName = function (){ console.log(this.name); }; } var person1 = new Person("rk-coder", 26); var person2 = new Person("rk-coder2", 27); person1.sayName(); person2.sayName();
這里
person1
和person2
兩對象都有一個constructor
(構(gòu)造函數(shù))屬性雇逞,該屬性指向Person
。constructor
屬性最初是用來標識對象類型的茁裙,但要檢測對象類型塘砸,最好還是使用instanceof
操作符。console.log(person1.constructor == Person);//true console.log(person2.constructor == Person);//true console.log(person1 instanceof Object);//true console.log(person2 instanceof Object);//true console.log(person1 instanceof Person);//true console.log(person2 instanceof Person);//true
構(gòu)造函數(shù)和其他函數(shù)區(qū)別在于調(diào)用的方式不同晤锥。構(gòu)造函數(shù)本身也是函數(shù)掉蔬,不通過
new
調(diào)用廊宪,跟普通函數(shù)沒有區(qū)別, 而普通函數(shù)也可以通過new
調(diào)用作為構(gòu)造函數(shù)。
缺點: 每個方法都要在實例上重新創(chuàng)建一遍女轿。 -
原型模式
function Person(){}; Person.prototype.name = 'rk-coder'; Person.prototype.age = 26; Person.prototype.sayName = function (){ console.log(this.name); }; var person = new Person("rk-coder", 26); person.sayName();
每個創(chuàng)建的函數(shù)都有一個
prototype
(原型)屬性箭启。這個屬性指向一個對象,包含可以由特定類型的所有實例共享的屬性和方法蛉迹。就是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個對象實例的原型對象傅寡。使用原型對象可以讓所有對象的實例共享它所包含的屬性和方法。
默認情況下北救,所有原型對象都會自動獲得一個constructor
屬性荐操,包含一個指向prototype屬性所在函數(shù)的指針。當(dāng)調(diào)用構(gòu)造函數(shù)創(chuàng)建一個新實例后珍策,該實例內(nèi)部將包含一個指向構(gòu)造函數(shù)的原型對象的指針(
__proto__
)托启。每當(dāng)代碼讀取某對象的某屬性時,都會首先從當(dāng)前這個對象的實例本身搜索攘宙,有則返回屯耸,沒有則會繼續(xù)指向到原型對象,在原型對象中搜索查找蹭劈。因此可以在實例上定義設(shè)置一些屬性和方法疗绣,對原型對象沒有影響,如果定義了與原型對象相同的屬性名或方法名链方,則將屏蔽原型上的值(如果需要回復(fù)持痰,則需要使用delete刪除實例上的值)。另外對原型對象所做的修改都將立即從實例上反映出來祟蚀,即便是修改前創(chuàng)建的實例工窍。
- isPrototypeOf: 判斷其原型對象是否存在于指定的對象實例中。
- hasOwnProperty: 判斷檢測指定屬性是否存在于實例中前酿,無法判斷是否在原型中存在患雏。
- in: 指定屬性是否通過對象可以訪問到,無論存在于實例還是原型罢维。
缺點: 原型中所有屬性都是共享的淹仑,顯然在某種程度上會帶來一些不方便,實例需要一些自己的屬性肺孵。
-
組合使用構(gòu)造函數(shù)模式和原型模式
使用構(gòu)造函數(shù)模式定義實例屬性匀借,原型模式定義方法和共享的屬性。這種是目前在ECMAScript中使用最廣泛平窘、認同度最高的一種創(chuàng)建自定義類型的方法吓肋。function Person(name, age){ this.name = name; this.age = age; } Person.prototype = { constructor: Person, sayName: function (){ console.log(this.name); } }; var person = new Person("rk-coder", 26); person.sayName();
-
動態(tài)原型模式
function Person(name, age){ this.name = name; this.age = age; if(typeof this.sayName != 'function'){ Person.prototype.sayName = function (){ console.log(this.name); }; //... ... } } var person = new Person("rk-coder", 26); person.sayName();
在初次調(diào)用構(gòu)造函數(shù)時,初始化原型對象瑰艘。
-
寄生構(gòu)造函數(shù)模式
function Person(name, age){ var o = new Object(); o.name = name; o.age = age; o.sayName = function (){ console.log(this.name); }; } var person = new Person("rk-coder", 26); person.sayName();
這種模式僅僅是封裝創(chuàng)建對象的代碼是鬼,然后再返回新創(chuàng)建的對象肤舞。通過return語句重寫調(diào)用構(gòu)造函數(shù)時返回的值。但返回的對象與構(gòu)造函數(shù)或者與構(gòu)造函數(shù)的原型屬性之間沒有關(guān)系均蜜,因此不能依賴instanceof操作符來確定對象類型李剖,不建議試用。
-
穩(wěn)妥構(gòu)造函數(shù)模式
function Person(name, age){ var o = new Object(); o.sayName = function (){ console.log(name); }; return o; } var person = Person("rk-coder", 26); person.sayName();
這種模式創(chuàng)建的對象囤耳,除了使用
sayName()
方法之外篙顺,沒有其他的方式訪問name的值。適合在某些安全執(zhí)行的環(huán)境下使用紫皇。