JS創建對象的幾種方法


題外話:昨天手欠,試圖用alert(window.appName)到ff之下去查看瀏覽器版本,結果彈出的竟然是Netscape,咋不是 firefox。繼而又跑去chrome下試驗,又一次彈出了Netscape。baidu搜 Netscape 竟然發現js就出自Netscape公司。慚愧啊慚愧!!!研究了這么久的js都不認識祖師爺。於是又跑去找了找族譜,原來js出自Brendan Eich之手,95年他創造js時候,也不過就31歲。哎呀,真是白活了,如他一般老的我,到現在都學不會js,真是人比人氣死人。。js當初設計的時候,沒有想到自己能從一部打電話用的手機變成集拍照,上網,游戲,電話於一身的智能機。真是造化弄人!!!也許各中的神奇,連Brendan Eich本人都沒有想到。應該說Brendan Eich創造了js,而一大批的js牛人成就了今天如此復雜的js。

js不是木有類么?沒關系,人家不是設計了原型屬性么~

js不是木有塊級作用域么?沒關系,人家不是有作用域鏈么~

js怎樣實現成員變量私有化?哦,用閉包解決吧~

哦,這么多基本概念,徹底的暈掉了,路漫漫其修遠兮。

 

言歸正傳,本文討論幾種js創建對象的方法,先從最好理解的工廠模式開始:

function createPerson(name,age,job){
    var o = {};
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
     alert(this.name);
    };
    return o;
}

var tanya = createPerson("tanya","30","female");
var ansel = createPerson("ansel","30","male");

tanya.sayName();
ansel.sayName();

這里先定義o為一個空的對象,然后為o設置了一堆屬性。其實也可以直接給o屬性的嘛,所以如果這樣寫也是ok的。

function createPerson(name,age,job){
    var o = {
        name : name,
        age : age,
        job : job,
        sayName : function(){
         alert(this.name);
        }
    };
    return o;
}

var tanya = createPerson("tanya","30","female");
var ansel = createPerson("ansel","30","male");

tanya.sayName();
ansel.sayName();

還有一種辦法是利用無敵的this,因為this就表示當前運行時的對象,將構造函數this的作用域指向新對象,將當前運行對象的屬性和方法都賦給新對象,這樣對象模式稱為構造函數模式

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

var tanya = new Person("tanya","30","female");
var ansel =  new Person("ansel","30","male");

tanya.sayName();
ansel.sayName();

在這個例子中,tanya和ansel都有一個constructor屬性,該屬性指向person。

考慮一下如下的情況:

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

Person("tanya","30","female");
Person("ansel","30","male");

window.sayName();
window.sayName();

發現兩次彈出的都是ansel,這是因為不用new的話,就不是一個person的實例,而僅僅在執行函數。而在全局作用域調用一個函數時this總是指向Global對象。而Global對象在瀏覽器中就是window對象。

我們還可以用構造模式在另外一個對象中調用sayName方法,還記得Apply和call么,來吧再考慮另外一種情況,

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

var olivia = {};
Person.call(olivia,"tanya","30","female");
olivia.sayName();

var philip = {}
Person.apply(philip,["ansel","30","male"]);
philip.sayName();

原型模式就要考慮原型鏈了,分析一下,sayName方法在實例中被重復定義了兩次,但其實沒有必要創造兩個一樣的副本。使用原型方法,可以使是tanya和ansel的共享一個sayName方法。

於是原型模式的寫法如下:

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

Person.prototype.sayName= function(){
     alert(this.name);
    };

var tanya = new Person("tanya","30","female");
var ansel =  new Person("ansel","30","male");

tanya.sayName();
ansel.sayName();

實際應用時,不是一成不變的套用某種模式,活學活用。需要共享方法的時候就用原型模式,需要使用副本的時候就用構造模式,還可以結合起來,把所有信息都封裝在構造函數中,而通過在構造函數中初始化原型,使得對象保持了同時使用構造函數和原型的優點。

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    if (typeof sayName != "function" ){
            Person.prototype.sayName= function(){
            alert(this.name);
        };
    }
}

var tanya = new Person("tanya","30","female");
var ansel =  new Person("ansel","30","male");
ansel.sayName = function () {
    alert("Hi ansel, how hansome you are!");
}

tanya.sayName();
ansel.sayName();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM