關於js對象創建

在js中,創建對象最簡單的方法就是new 一個Object的實例出來(new Object()),例如:
    var person=new Object();
    person.name='chan';
    person.age='11';
    person.sayHi=function(){alert('hi')};
後來,人們開始使用 對象字面量 來創建對象,語法如下:
    var person={
        name:'chan',
        age:'age',
        sayHi:function(){
            alert('hi');
        }
    };    
但是,這麼創建對有個缺點,創建同樣的一個對象就會產生大量重複的代碼,這不會碼農們想要的。所以,就有了以下的一些方法。
No.1,想到了用工廠模式。用一種函數來封裝創建特定對象的接口。例如:
    function createPerson(name, age) {
        var obj = new Object();
        obj.name = name;
        obj.age = age;
        obj.sayHi = function () {
            alert('hi');
        };
        return obj;
    }
    調用的時候:
    var person = createPerson('chan', 11);
    person.sayHi();
可是,這種方法不推薦。它雖然避免了創建重複對象時的重複代碼,但是,不能知道這個對象的類型。還是以上面的例子說明,person不知道是什麼類型的。
No.2,利用構造函數模式。所謂的構造函數,其實就是相應的方法,js中沒有類的概念,所以,一個用於創建對象的function可以理解成一個構造函數。
    function Person() {//按照編碼規則,構造函數的首字母大寫
        this.name = 'chan';
        this.age = 11;
        this.sayHi = function () {
            alert('hi');
        };
    }
    var person =new Person();//創建實例要new一個
    person.sayHi();
利用這種方法創建的對象,它們constructor屬性(這個屬性用來標識對象是什麼類型的)都指向了Person。
        alert(person1.constructor == Person);//true
        alert(person2.constructor == Person);//true
同樣,用instanceof檢測對象類型都指向了Person。
        alert(person1 instanceof Person);//true
        alert(person2 instanceof Person);//true
但是,alert(person1.sayHi == person2.sayHi);//false.這是因為,用構造函數new出來的對象,都把構造函數中的內容重新創建了一次,這似乎是沒有必要的事情,完成同樣一項功能的方法似乎沒必要再創建一次,因此,不推薦。
No.3,利用原型模式。每個函數都有一個prototype的屬性,這個屬性指向一個對象,這個對象包括了而特定類型的所有實例共享的屬性與方法。換句話說,利用原型模式創建的對象,其屬性和方法都是共享的,不像構造函數那樣,都只是獨享。
    function Person() { }
        Person.prototype.name = 'chan';
        Person.prototype.age = 11;
        Person.prototype.sayHi = function () {
            alert('hi');
    };
    var person1 = new Person();
    person1.sayHi();
    alert(Person.prototype.isPrototypeOf(person1));//true;
    var person2 = new Person();
    person2.sayHi();
    alert(person1.sayHi == person2.sayHi);//true
正如之前提到的,原型模式共享所有的屬性與方法,方法的共享尚可接受,但是屬性的共享似乎不太好。特別是一些引用型的屬性,一旦修改,將影響所有實例。
綜上,不推薦。
No.4,構造函數與原型模式的綜合。簡而言之就是屬性在構造函數中寫而方法在原型模式中寫。這樣既滿足了每個實例不同的屬性值,又共享了方法。節省內存啊!
    function Person(name,age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.sayHi = function () {
        alert('hi, i’m '+this.name+' and i‘m '+ this.age+' years old.');
    };
    var person1 = new Person('chan',11);
    person1.sayHi();
    var person2 = new Person('ky',12);
    person2.sayHi();
推薦!!
No.5,動態原型模式。感覺就像一個類,把屬性和方法都寫在了構造函數中,類似於 類 的格式。
    function Person(name, age) {
        this.name = name;
        this.age = age;
        if (typeof this.sayHi != 'function') {//這裡的if判斷,只有該方法不存在的時候,才會調用構造函數進行執行
            Person.prototype.sayHi = function () {
                alert('hi, i’m ' + this.name + ' and i‘m ' + this.age + ' years old.');
            };
        }
    }
    var person1 = new Person('chan', 11);
    person1.sayHi();
    var person2 = new Person('ky', 12);
    person2.sayHi();
推薦!!
No.6,寄生構造函數模式。這種模式類似於構造函數魔術與工廠模式。它創建一個構造函數,封裝了創建對象的代碼,然後返回這個對象。
代碼類似工廠模式,此處省略。
這種模式返回的對象與構造函數、構造函數原型屬性沒有關係。無法用instanceof確定對象類型。因此,不推薦。
No.7,穩妥構造函數模式。穩妥對象就是沒有公共屬性,其方法也不引用this的對象。適合在一些安全的環境中(禁用this,that)或者防止數據被其他應用程序改動時使用。
    function Person(name) {
        var obj = new Object();
        name = name;
        obj.sayHi = function () {
            alert('hi ' +name);
        };
        return obj;
    }


    var person1 = Person('chan');
    person1.sayHi();
    alert(person1.name);//undefined,即無法訪問到name的值。
與寄生構造函數模式區別:1.新創建對象的實例方法不引用this。2.不使用new操作符調用構造函數。

猜你喜欢

转载自blog.csdn.net/chenpeggy/article/details/51241181
今日推荐