Stories

Detail Return Return

從JQuery出發總結的關於原型使用上的一些淺薄理解 - Stories Detail

比如我們現在的需求如下。

有一個函數MyObj,支持如下功能:

  • 可以通過MyObj()的方式返回一個對象,這個對象和new MyObj()是等價的
  • MyObj本身是一個對象,可以通過MyObj.doit()的方式調用其上的方法或屬性
    為了實現需求,第一反應是:

    var MyObj=function(){
      return new MyObj();
    };

    然後在MyObj上掛載靜態方法,在MyObj.prototype上掛載對象方法。

看起來穩的很,其實這明顯是一個死循環:

// VM160:2 Uncaught RangeError: Maximum call stack size exceeded
MyObj();

為了解決這個問題,我們在MyObj的原型上定義了一個方法:

MyObj.prototype.init=function(){
    return this;
};

執行下面的方法:

var temp=MyObj.prototype.init();

上面返回的temp很明顯就是MyObj.prototype,其實就是MyObj對象(例如:new A(),其實就是取A.prototype,這樣對比就很好理解了)。

因此可以改造代碼如下:

var MyObj = function (param) {
    return MyObj.prototype.init();
};

這樣MyObj和new MyObj()就分別表示類和對象。

問:看起來是不是實現了?
答:是的,實現了。
問:可是總感覺有點不好,説不出為什麼。
答:是不是感覺MyObj()打印出來的東西有點多?
問:是的。

事實上,因為直接取MyObj.prototype作為new MyObj(),理論上説,使用上區別不大,唯一不足的是,掛載在MyObj.prototype上的方法會在打印MyObj對象的時候看見,不舒服。

為了看起來好看些,代碼再次改造:

var MyObj = function () {
    return new MyObj.prototype.init();
};

// 為了讓MyObj()返回的是MyObj對象,需要修改MyObj.prototype.init的原型
MyObj.prototype.init.prototype = MyObj.prototype;

此刻的原型關係變成了:

MyObj() ==
return new MyObj.prototype.init() ==
MyObj.prototype.init.prototype ==
MyObj.prototype ==
new MyObj()

此時需求就實現了,而且打印MyObj()的時候,對象上的方法都在原型上,看起來就比較舒服了。

user avatar Leesz Avatar alibabawenyujishu Avatar haoqidewukong Avatar zaotalk Avatar smalike Avatar linlinma Avatar yinzhixiaxue Avatar littlelyon Avatar zourongle Avatar linx Avatar anchen_5c17815319fb5 Avatar u_17443142 Avatar
Favorites 111 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.