我通常会看到如下面的语法#2所示的显示原型模式的示例,但我发现语法#1更加一致。除了语法之外,它们有什么不同吗?功能上,性能方面还是其他?
语法#1:
function MyClass1(name){
this.name = name;
}
MyClass1.prototype = new function () {
var static = 0;
var getStatic = function () {
return static;
}
this.incStatic = function () {
static++;
return getStatic.call(this);
}
this.constructor = MyClass1
};
与#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只是一个更常量的语法,我讨厌在特殊的返回块中识别公共成员。
答案 0 :(得分:0)
我个人认为重新分配something.prototype
是不合适的。相反,扩展原型:
(function() {
var static = 0;
MyClass.prototype.getStatic() {return static;}
MyClass.prototype.incStatic() {return static++;}
})();
答案 1 :(得分:0)
这一切都是因为我正在创建一个利用泛型类构造函数的MVC框架。我使用两种不同的实现方法在Class构造函数的较大上下文中运行这些变体。方法1重新分配方法2扩展它的原型。方法1具有统一的原型链,其中方法2在语法#1的对象原型之上添加函数原型。方法1和方法2的性能大致相同。
蓝&红色=语法#1。
Teal&绿色=语法#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