参考:http://ejohn.org/blog/simple-class-instantiation/
// makeClass - By John Resig (MIT Licensed)
function makeClass(){
return function(args){
if ( this instanceof arguments.callee ) {
if ( typeof this.init == "function" )
this.init.apply( this, args.callee ? args : arguments );
} else
return new arguments.callee( arguments );
};
}
我想知道,如果有任何符合ECMAScript 5的方式来实现相同的功能。问题是,在严格模式下不允许访问arguments.callee
。
答案 0 :(得分:4)
据我所知,arguments.callee
在严格模式下不是已弃用,在这种情况下您可以继续使用它;相反,它已被删除并尝试使用将(或应该)抛出异常。
解决方法是使用命名的匿名函数,如果你原谅矛盾的话。我真的应该说"named function expressions"。一个例子:
function someFunc(){
return function funcExpressionName(args){
if (this instanceof funcExpressionName) {
// do something
} else
return new funcExpressionName( arguments );
};
}
在我的示例funcExpressionName
中,您提供的名称不应该从其应用的函数内部的任何位置访问,但不幸的是IE有其他想法(如您Google it所见)。
对于您问题中的示例,我不知道如何处理args.callee
,因为我不知道调用函数是如何设置的,但是arguments.callee
的使用将被替换按照我的例子。
答案 1 :(得分:2)
nnnnnn 给出的上述想法非常好。为了避免IE问题,我建议采用以下解决方案。
function makeClassStrict() {
var isInternal, instance;
var constructor = function(args) {
// Find out whether constructor was called with 'new' operator.
if (this instanceof constructor) {
// When an 'init' method exists, apply it to the context object.
if (typeof this.init == "function") {
// Ask private flag whether we did the calling ourselves.
this.init.apply( this, isInternal ? args : arguments );
}
} else {
// We have an ordinary function call.
// Set private flag to signal internal instance creation.
isInternal = true;
instance = new constructor(arguments);
isInternal = false;
return instance;
}
};
return constructor;
}
请注意我们如何通过使用内部标记来避免引用args.callee
部分中的// do something
。
答案 2 :(得分:1)
John Resig的原始代码因无参数构造函数而失败。
var Timestamp = makeClass();
Timestamp.prototype.init = function() {
this.value = new Date();
};
// ok
var timestamp = Timestamp();
alert( timestamp.value );
// TypeError: args is undefined
var timestamp = new Timestamp();
alert( timestamp.value );
但可以使用以下行修复
this.init.apply( this, args && args.callee ? args : arguments );