1. 程式人生 > >javascript高階程式設計讀書筆記———建立物件

javascript高階程式設計讀書筆記———建立物件

2. 建立物件的幾種方式

2.1 工廠模式

function createPeople(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        console.log(this.name);
    }
    return o;
}

var p1 = createPeople("landy", "20", "fe");

2.2 建構函式模式

function Person
(name, age, job) {
this.name = name; this.age = age; this.job = job; this.sayName = function(){ console.log(this.name); }; } var p1 = new Person("landy", "20", "fe");

    注意: 與工廠模式不同的地方主要有:
    
    1. 沒有顯示建立物件。
    2. 直接將屬性和方法賦給this物件
    3. 沒有return語句

 
    建構函式的缺點:方法無法複用。例如以上例子中的sayName函式。 我們可以將方法移到外部來實現複用。

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}

function sayName(){
        console.log(this.name);
 };

var p1 = new Person("landy", "20", "fe");

但是如果很多方法的話,就需要定義很多全域性函式,而且這些函式只能被某個物件呼叫。這種情況下,已經破壞了該引用型別的封裝性。

2.3 原型模式

function Person() {
}

Person.prototype.name = "landy";
Person.prototype.age = "20";
Person.prototype.job = "fe";
Person.prototype.sayName = function(){
    console.log(this.name);
};

var p1 = new Person();
var p2 = new Person();

p1.sayName();  // landy
console.log(p1.sayName == p2.sayName) // true

方法 說明
isPrototypeOf() 確定物件是否存在原型關係
hasOwnProperty() 確定是例項擁有某一屬性還是原型擁有該屬性
in 判斷是否物件擁有某一屬性。但不能準確判斷出是例項屬性還是原型的屬性
function Person() {
}
var p = new Person();
Person.prototype.sayHi = function() {
    console.log("hi");
}
p.sayHi();  // no error


function Person() {
}
var p = new Person();
Person.prototype = {
    constructor: Person;
    sayHi: function() {
        console.log("hi");
    }
}
p.sayHi(); // error

// 第二種情況對原型進行了重寫,p的原型是之前的person.prototype.而不是重寫後的。所以會報錯。

注意:原型模式的問題: 資料共享。

2.4 組合使用建構函式模式和原型模式
    
    集合兩者之長,建構函式定義例項屬性,原型定義方法和constructor屬性。

function Person(name, age, job){
    this.name = name;
    this,age = age;
    this.job = job;
}
Person.prototype = {
    constructor: Person,
    sayName: function() {
        console.log(this.name);
    }
}

注意:目前使用最廣泛,認同度最高的方式。

2.5 動態原型模式
 
     將所有資訊封裝在建構函式中,通過建構函式初始化原型

function Person(name, age, job) {
    // 屬性
    this.name = name;
    this.age = age;
    this.job = job;

    if(typeof this.sayName !== "function") {
        Person.prototype.sayName = function() {
            console.log(this.name);
        }
    }
    //  在動態原型模式中,不能進行原型重寫,否則會切斷現有例項與新原型之間的聯絡
}

2.6 寄生建構函式模式

//  注意比較程式碼和工廠模式以及建構函式模式的區別

function Person(name, age, job) {
    var o = new Obect();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        console.log(this.name);
    }
    return o;
}

var p1 = new Person('landy', '20', 'fe');
// 建構函式在無返回值的時候,會預設返回新物件例項。可以使用return重寫建構函式返回的值。

注意:該種情況下,p1和建構函式Person以及Person的原型屬性沒有任何關係。所以不能使用instanceof來確定物件型別。

2.7 穩妥建構函式模式
 
    穩妥物件是指沒有公共屬性,而且方法也不引用this物件。適合在安全環境中引用(這些環境會禁止使用 this 和 new)

funtion Person(name, age, job) {
    var o = new Object();
    // 在這裡定義私有變數,eg  name = name;
    // 有點類似C++類中的 private name = ?;

    o.sayName = function(){
        console.log(name);
    }

    return o;
}

// 以上處理通過sayName,沒有其他辦法訪問內部成員。穩妥建構函式提供了較高的安全性。