javascript
【JavaScript 学习笔记】创建对象
2019獨角獸企業重金招聘Python工程師標準>>>
因為最近一直在讀《JavaScript高級程序設計》,深感從前對JavaScript的了解實在過于膚淺,所以打算順手做些摘抄筆記,總結一下,給自己做個備忘。
在JavaScript里創建對象總共有以下幾種實現方式:
工廠模式 構造函數模式 原型模式 原型和構造函數的混合模式 動態原型模式 寄生構造函數模式 穩妥構造函數模式下面對以上諸方式舉例說明:
1. 工廠模式
最簡單的模式,直接看例子即可:
1: function createPerson(name, age, job){ 2: var o = {}; 3: o.name = name; 4: o.age = age; 5: o.job = job; 6: return o; 7: } 8: var p = createPerson("Bob", 22, "spy");缺點:該方法的缺憾是類似對象的識別問題, 無法準確判斷兩個object實例是否是同一類型。
2. 構造函數模式
1: function Person(name age, job){ 2: this.name = name; 3: this.age = age; 4: this.job = job; 5: this.sayName = function(){ 6: alert(this.name); 7: } 8: } 9: var p1 = new Person("Bob", 22, "Spy"); 10: var p2 = new Person("Mike", 25, "Engineer")在使用這種模式創建對象時,其實主要有以下幾個步驟:
創建一個對象; 將構造函數的作用域綁定為這個對象,也就是說構造函數的this其實就指向新創建的這個對象; 執行構造函數,返回這個新的對象優點:可以用 instanceof 標識對象的類型, 如上面的 p1,p2 在 instanceof Person時都可以返回true值
缺點:每個實例上都定義了sayName方法,不夠環保,而且不同實例上的同名函數(這里是sayName)是不相等的。
3. 原型模式
1: function Person(){ 2: } 3: Person.prototype.name = "Bob"; 4: Person.prototype.age = 22; 5: Person.prototype.job = "Spy"; 6: Person.prototype.sayName = function(){ 7: alert(this.name) 8: }; 9: ? 10: var p1 = new Person(); 11: p1.sayName();// "Bob" 12: var p2 = new Person(); 13: p2.sayName();//"Bob" 關于原型的敘述,請點傳送門,這里就不贅述了。原型模式的特點是新對象的所有屬性和方法都是共享的。這既是優點也是缺點,共享方法很棒,但是我們可能并不想共享屬性 ,也許把構造函數和原型結合起來是個不錯的主意,所以就有了下面的4.原型和構造函數的混合模式
1: function Person(name, age, job){ 2: this.name = name; 3: this.age = age; 4: this.job = job; 5: } 6: Person.prototype.sayName = function(){ 7: alert(this.name); 8: } 9: ? 10: var p1 = new Person("Bob", 22, "Spy"); 11: var p2 = new Person("Mike", 24, "Engineer");把實例屬性定義在構造函數中,把共享的方法定義在prototype中,是ECMAScript中使用最廣泛,認同度最高的一種創建自定義類型的方法。
5. 動態原型模式
習慣了其他語言面向對象的編程人員,在看到JavaScript里采用上面的模式定義對象是可能會感到困惑,為什么要在兩個地方去定義一個類型呢?于是就誕生了動態原型模式,如下
1: function Person(name, age, job){ 2: this.name = name; 3: this.age = age; 4: this.job = job; 5: if(typeof this.sayName != "function"){ 6: Person.prototype.sayName = function(){ 7: alert(this.name); 8: } 9: } 10: } 11: ? 12: var p1 = new Person("Bob", 22, "Spy");所以說,動態原型模式 跟 原型和構造函數的混合模式 并沒有本質上的不同,僅僅是動態原型模式會在第一次調用構造函數是才會在原型上定義共享的方法。
6. 寄生構造函數模式
1: function Person(name, age, job){ 2: var o = new Object(); 3: o.name = name; 4: o.age = age; 5: o.job = job; 6: o.sayName = function(){ 7: alert(this.name); 8: } 9: } 10: var p = new Person("Bob", 22, "Spy");除了使用了new操作符,這個方式跟工廠模式并無很大差別。在上面的構造函數模式里曾經說過,當采用 new Person() 時,會先創建一個新的對象實例,再去綁定調用構造函數云云,這里應該把返回值這部分補全一下,當構造函數沒有返回值時,就默認返回了第一步創建的那個新對象實例,但是如果構造函數里有return語句,并且返回了一個object,那么最終的返回結果就是這個在構造函數里創建的object,而不是最初創建的那個新對象實例。(這里必須要保證構造函數內部返回值是object,如果是數字,字符串等基本型,是無法覆蓋在第一步創建的對象實例的,這個是我自己試驗的 )。
這里還有一點需要注意的就是由構造函數內部返回出來的這個object,它的原型和Person的prototype是沒有關系的,其實在Chrome里不妨試一試,當使用構造函數模式創建了一個對象實例后,輸出這個實例所得結果如下
Person {name: "Bob", age: 22, job: "Spy", … }
但是如果用寄生構造函數創建一個對象實例,輸出該實例所得結果如下
Object {name: "Bob", age: 22, job: "Spy", …}
所以,使用該模式創建的實例與使用工廠模式創建的實例一樣,沒法使用 instanceof 來判斷類型。
關于這個寄生構造函數模式使用的場合,一般是想在某種已有類型的基礎上添加方法等,但是又不方便直接去修改已有類型的構造函數,這時候,寄生構造函數模式就比較適合了,下面是個例子
1: function SpecialArray(){ 2: var values = new Array(); 3: values.push.apply(values, argumeents); 4: values.toPipedString = function(){ 5: return this.join("|"); 6: } 7: return values; 8: } 9: var arr = new SpecialArray("Tiger", "Lion", "Dog");這里就在Array的基礎上定義了SpecialArray,初始化數組,并添加了新的方法toPipedString。
7. 穩妥構造函數模式
先來看看實例,再來說說這種模式有什么特點吧
1: function Person(name){ 2: var o = new Object(); 3: o.sayName = function(){ 4: alert(name); 5: }; 6: return o; 7: } 8: ? 9: var p = Person("Bob");- 創建的對象實例沒有公共屬性
- 方法中不使用this
其實滿足了以上條件的對象就叫做穩妥對象,穩妥對象適合在一些安全環境中使用,這些環境中,會禁止使用 new 和 this , 或者防止數據被其他應用改動,從示例中可以看到,除了sayName, 外界是無法訪問 name 的,(這里用了一個閉包)。
?
哦,暫時就到這里吧,實在有些困了,如果示例代碼里有小毛病,還請多包涵。
轉載于:https://my.oschina.net/himerlin/blog/136889
總結
以上是生活随笔為你收集整理的【JavaScript 学习笔记】创建对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “寒假”建站创业 选购虚拟主机是关键
- 下一篇: ECSHOP在打印订单时打印出商品序号