這整個事情來了,因爲我創建了一個MVC框架,利用一個通用的類構造函數。我使用兩種不同的實現方法在Class構造函數的更大範圍內運行這些變體。方法1重新分配方法2擴展它的原型。方法1有一個統一的原型鏈,方法2在語法#1的對象原型的頂部添加函數原型。方法1和2的性能大致相同。
藍色& Red =語法#1。
Teal & Green =語法#2。
黃色& purple =語法#2的變體。
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
至於性能,你測試這個自己:http://jsperf.com/。關於結果:在第一個示例中,結果對象不是直接從Object.prototype繼承,而是從匿名函數的原型直接繼承。 –
@FelixKling你對原型鏈絕對正確,感謝把我轉到jsperf。結果#1慢了0%-25%。任何想法如何在沒有性能影響的情況下實現#1的語法?你認爲這是一個壞主意嗎? – arctelix
可能重複的[構造函數與工廠函數](http://stackoverflow.com/questions/8698726/constructor-function-vs-factory-functions) –