文章出處

該文為閱讀高級程序設計(第三本)p144-p164的理解與總結!  接受指導與批評。

對于我,我一直是使用字面量的方式創建對象,然而體系上的創建對象的方法卻并不局限于此。

創建對象的方法

  1. 工廠模式
  2. 構造函數模式
  3. 原型模式
  4. 組合使用構造模式和原型模式
  5. 動態原型模式
  6. 寄生構造函數模式
  7. 穩妥的構造函數模式

1 工廠模式:

  定義工廠函數創建并返回包含特定屬性的對象, 

function createPerson(name, age, job) {
    var o = new Object();    // var o = {}; //一樣
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function() {
        alert(this.name);
    }
    return o;
}
var person0 = createPerson('jody', 22, 'wife');

 

2 構造函數模式:

  先貼出代碼

function Person(name) {
    this.name = name;
    this.sayName = function() {
        console.log(this);
    }
}
var person1 = new Person('xxx');
var person2 = new Person('bbb');
console.log(person1)

 

  2.1 new Person() 的發生了什么?步驟分解:這是重點(new的工作原理)

    1. 新建一個對象: instance = new Object(); 
    2. 設置原型鏈: instance.prototype = Person.prototype 
      1.   任意函數在創建的時候都會創建prototype對象,并自動為它添加constructor屬性
    3. 讓 Person 中的 this 指向 instance, 然后執行函數:
      1.   相當于在instance中定義屬性(name,sayName)
    4. 判斷 Person 函數的返回 :
      1.   Person 中沒有寫return,相當于return undefined(值類型),因此返回instance
      2.   如果返回值類型,則丟棄該值類型, 然后返回 instance。
      3.   如果返回引用類型,則丟棄instance, 返回該引用類型。

  2.2 構造函數也是函數,

    它是可以直接執行的,然后給執行作用域綁定屬性。    

    任何函數,只要使用new 操作符,這個函數函數就變成了構造函數

  2.3 構造函數的優缺點

      1.優點:

person1 instanceof Person
person2 instanceof Object   //都為ture,用于判斷類型(工廠模式不行)

      2.缺點:公共屬性(如sayName)在每一個Person實例中都創建了,不能做到復用

 

3 原型模式

function Person() {
};
Person.prototype.sayName = function() {
    console.log(this.name);
}
Person.prototype.name = 'miaowwwwww';
var person1 = new Person();
var person2 = new Person();
person1.sayName();
console.log(person1)

 

  3.1 什么是原型對象??

    當創建一個函數的時候,js根據一組特定的規則自動地為函數創建 prototype 屬性 和 一個原型對象。

    prototype 屬性是一個指針,指向原型對象。

    原型對象自動獲得一個 constructor(構造函數) 指針屬性,該屬性指向 被創建的函數。

  3.2 實際應用重點:

        使用構造函數創建的每一個實例,都自動包含一個[[prototype]] 指針屬性。(在瀏覽器prototype是隱藏的,一些瀏覽器提供__proto__)。

        并且這個屬性指向,構造函數的 prototype (即原型對象, 所以每一個實例共享一個原型對象

  3.3 構造函數-原型-實例的關系如圖:

 

 

 

 

 

 

 

 

 

 

   3.4 注意:

    1.  原型對象上的可遍歷屬屬性將會出現在 實例的 for-in 遍歷中  
    2.  構造函數 Person.prototype 是一個指針
      1.   若使用 Person.prototype.sayName = function() {...}  表示在原 原型中添加屬性
      2.   若使用如下方式:表示 改變了 Person.prototype 的指針, 讓它指向了一個新的對象,該對象的屬性被實例共享,當缺失了constructor屬性
        Person.prototype = {
            constructor: Person,    // 可手動添加,補全constructor屬性
            name: 'miaowwwww',
            sayName: function() {
                console.log(this.name);
            }
        }

   3.5 原型模式的優缺點

       1.優點:

      1.   完善構造函數模式的缺點,所有實例可以共享原型的方法,而不需要是個實例創建副本,提高復用性
      2.   類型判斷
person1 instanceOf Person 
Person.isPrototypeOf(person1)
Object.getPrototypeOf(person1) === Person
// 都可以正確判斷結果

 

       2.缺點:若原型中使用引用類型,則實例可以修改原型中的

function Person() {};
Person.prototype = {
    constructor: Person,
    name: 'miaowwwww',
    friends: ['jody', 'robin'],
    sayName: function() {}
}
var person1 = new Person();
var person2 = new Person();
person1.friends.push('mike');
// person2.friends : ['jody', 'robin', 'mike'];

  

 4. 組合構造函數模式與原型模式

function Bird(name) {
    this.name = name;
    this.friends = ['mike', 'jody'];
}
Bird.prototype = {
    sayName: function() {
        console.log(this.name);
    }
}

 

   4.1 優點: 結合構造函數模式與原型模式的優點,把引用類型的屬性,放到構造函數中,為每一個實例創建副本,同時復用原型上的方法

 

5.動態原型模式

function Cat(name) {
    this.name = name;
    this.friends = ['a', 'b'],
    if(typeof this.sayName !== 'function') {
        Cat.prototype.sayName = function() {
            console.log(this.name);
        }
    }
}

  5.1 解讀:就是把第四種模式,變異一下,在判斷實例沒有 sayName 方法的時候才添加 該方法到 原型上

       每次新建對象的時候都會執行判斷代碼, 然后只有第一次執行, if 才為true

 

6.寄生構造函數模式

function Book(name) {
    var o = new Array();
    o.name = name;
    o.sayName = function() {
        console.log(this.name);
    }
    return o;
}
var book1 = new Book('javascript');

 

   6.1 請回顧上面說過的 2.1 new 的工作原理

   6.2 理解:

    1. 這種方法除了 return 以及 new Book()  之外,跟工廠函數基本沒有區別。
    2. 可以理解為對已有對象的增強(如這里的Array,因為不能直接修改Array對象)

  6.3 缺點:

    1. book1 的原型中不包含 Book, 而是Array, 所以叫寄生
    2. 與構造函數一樣,每一個實例都有 sayName.. 的副本,復用性降低

 7 穩妥的構造函數模式

function Fish(_name){
    var o = new Object(); // new Person(); 或其他對象
    
    // 私有變量和函數
    var name = _name;
    function sayHi() {
        console.log('hi')
    };
    // ...

    // 添加方法
    o.sayName = function() {
        console.log(name);
        sayHi();
        return name;
    }
    o.setName = function(value) {
        name = value;
    }
    return o;
}
var aa = Fish('miaowwwww');
var bb = Fish('jody');
aa.sayName();
bb.sayName();

 

  7.1 這個竟然是平時一直在用的閉包。

  7.2 優點:變量私有化,并且只能通過特定接口訪問

    缺點: 又是每一個實例一個函數副本,復用性降低了;

  

 


文章列表


不含病毒。www.avast.com
全站熱搜
創作者介紹
創作者 大師兄 的頭像
大師兄

IT工程師數位筆記本

大師兄 發表在 痞客邦 留言(0) 人氣()