2014-03-02 82 views
1

我通常會看到下面的語法#2所示的揭示原型模式的例子,但我發現語法#1更一致。除語法之外,他們有什麼不同嗎?在功能上,性能明智,還是其他?javaScript:揭示原型模式:這兩個版本有差別嗎?

語法#1:

完全一樣,這樣#2:

function MyClass2(name){ 
    this.name = name; 
} 
MyClass2.prototype = function() { 
    var static = 0; 

    function getStatic() { 
     return static; 
    } 
    function incStatic() { 
     static++; 
     return getStatic.call(this); 
    } 
    return { 
     incStatic:incStatic, 
     constructor:MyClass2 
    }; 
}(); 

這裏是一個小提琴證明完全相同的行爲:http://jsfiddle.net/arctelix/FSk8z/

看來,這兩種語法有完全相同的結果。但是,我從來沒有見過#1所示的例子,所以我不得不想知道爲什麼?對我來說,#1只是一個更常量的語法,我討厭在一個特殊的返回塊中識別公共成員。

+1

至於性能,你測試這個自己:http://jsperf.com/。關於結果:在第一個示例中,結果對象不是直接從Object.prototype繼承,而是從匿名函數的原型直接繼承。 –

+0

@FelixKling你對原型鏈絕對正確,感謝把我轉到jsperf。結果#1慢了0%-25%。任何想法如何在沒有性能影響的情況下實現#1的語法?你認爲這是一個壞主意嗎? – arctelix

+0

可能重複的[構造函數與工廠函數](http://stackoverflow.com/questions/8698726/constructor-function-vs-factory-functions) –

回答

0

我個人認爲重新分配something.prototype不合適。相反,擴展原型:

(function() { 
    var static = 0; 
    MyClass.prototype.getStatic() {return static;} 
    MyClass.prototype.incStatic() {return static++;} 
})(); 
+2

這並沒有真正回答這個問題,但... –

0

這整個事情來了,因爲我創建了一個MVC框架,利用一個通用的類構造函數。我使用兩種不同的實現方法在Class構造函數的更大範圍內運行這些變體。方法1重新分配方法2擴展它的原型。方法1有一個統一的原型鏈,方法2在語法#1的對象原型的頂部添加函數原型。方法1和2的性能大致相同。

藍色& Red =語法#1。

Teal & Green =語法#2。

黃色& purple =語法#2的變體。

enter image description here

var Class = function (methods, options) { 
    //allow for Proper class name to show up in browser devtools 
    options = options || {} 
    var debug = options.debug || false 
    var protoTest = options.protoTest || 0 
    var pInternal = options.pInternal || true 
    var klassName = methods.constructor.name 
    console.log('------protoTest =', protoTest, '/ debugClass =', debug, '/ pInternal =', pInternal, '/ klassName = ',klassName) 

    //compile the constructor & internalMembers 
    var Class = function() { 
     //console.log('Class() is building:', !(init instanceof init)) 
     //provide inernal object for constructor 
     if (pInternal) this.internal = {} 
     this.constructor.apply(this, arguments); 
     //remove internal from public scope 
     if (pInternal){ 
      var int = this.internal 
      delete this.internal 
     } 
     //populate self with this and internal vars 
     if (pInternal){ 
      var self = {pub:this, int:{}}; 
      for (var v in int){ 
       self.int[v] = int[v]; 
      } 
     }else var self = this 
     // Instantiate internalMembers with self 
     var include = methods.include; 
     if (include) include.call(this, self); 
    }; 

    //create constructor function with className (fixes class name in debugger) 
    if (debug == true && klassName) { 
     var klass = new Function("init", "return function " + klassName + "(){ init.apply(this,arguments) };")(Class); 
    }else var klass = Class 


    console.log('---type', typeof methods.prototype) 
    if (typeof methods.prototype == 'object'){ 
     //must use traditional revealing prototype 
     var prototype = methods.prototype; 
     if (protoTest==0){ 
      //overides prototype 
      if (prototype) klass.prototype = prototype; 
     }else{ 
      //does not overide prototype 
      for (var p in prototype) klass.prototype[p] = prototype[p] 
     } 
    } 
    //create prototype from Class method 
    //----------------test 0 
    else if (protoTest==0){ 
     //overides prototype (new has extra proto in chain) 
     var prototype = methods.prototype; 
     if (prototype) klass.prototype = new prototype(); 
    } 
    //----------------test 1 
    else if (protoTest == 1){ 
     //does not overide prototype and has uniform chain 
     var pms = new methods.prototype() 
     for (var p in pms) klass.prototype[p] = pms[p] 
    } 
    //----------------end test 

    //add other Class methods to prototype 
    var exclude = ['include', 'initialize', 'prototype']; 
    for (var property in methods) { 
     if (exclude.indexOf(property) == -1) { 
      klass.prototype[property] = methods[property]; 
     } 
    } 

    return klass; //return the class 
}; 

所有的測試:http://jsperf.com/revealing-proto-test/4

小提琴:http://jsfiddle.net/arctelix/Cp4nG/

沒有與測試調試模式,以及:http://jsperf.com/revealing-proto-test/3