Javascript 简单“;类别”;实例化
: 尤其是这一行Javascript 简单“;类别”;实例化,javascript,oop,Javascript,Oop,: 尤其是这一行this.init.apply(this,args.callee?args:arguments) args和arguments之间有什么区别?args.callee是否可以false args和arguments之间有什么区别 是javascript创建的类似数组的结构,包含所有传入参数 Args是函数本身的一个参数 args.callee是否可以为false 当然, function makeClass(){ return function(args){ if (
this.init.apply(this,args.callee?args:arguments)代码>
args
和arguments
之间有什么区别?args.callee
是否可以false
args和arguments之间有什么区别
是javascript创建的类似数组的结构,包含所有传入参数
Args是函数本身的一个参数
args.callee是否可以为false
当然,
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 );
};
}
var class = makeClass();
class({callee: false});
在上面的例子中:
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 );
};
}
返回保存到变量类中的以下函数
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 );
}
所以当我调用类({args:false})时代码>
因此,args
使您能够覆盖问题标题下由javascript创建的默认参数,而不是关于示例的特定问题:
我真的不明白他们为什么要把事情复杂化。为什么不这样做呢?这是js中“简单”类实例化的一个更好的例子(根据我的说法):
function SomeClass(argument1, argument2) {
// private variables of this object.
var private1, private2;
// Public properties
this.public1 = 4;
this.public2 = 10;
// Private method that is invoked very last of this instantionation, it's only here
// because it's more logical for someone who is used to constructors
// the last row of SomeClass calls init(), that's the actual invokation
function init() {
}
// Another private method
var somePrivateMethod() {
// body here
}
// Public methods, these have access to private variables and other private methods
this.publicMethod = function (arg1, arg2) {
// arguments are only accessible within this method
return argument1 + argument2;
}
init();
}
// And then instantiate it like this:
var x = new SomeClass(1, 2);
// Arguments are always optional in js
alert(x.publicMethod());
你写道,现有的答案没有足够的细节,但即使在阅读了你的具体问题之后,我也不完全确定代码的哪些方面会让你陷入循环-它有许多棘手的部分-因此,如果这个答案中包含了你已经理解的细节,我提前道歉
由于makeClass
总是以相同的方式调用,因此如果我们删除一级间接寻址,就更容易对其进行推理。这:
var MyClass = makeClass();
相当于:
function MyClass(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 );
}
this.init.apply(this, arguments);
this.init('value');
由于我们不再处理匿名函数,因此我们不再需要参数。被调用方
表示法:它必须引用MyClass
,因此我们可以将它的所有实例替换为MyClass
,如下所示:
function MyClass(args)
{
if ( this instanceof MyClass )
{
if ( typeof this.init == "function" )
this.init.apply( this, args.callee ? args : arguments );
}
else
return new MyClass( arguments );
}
其中,args
是MyClass
的第一个参数的标识符,参数始终是一个类似数组的对象,包含所有MyClass
的参数
只有当“类”的原型中有一个名为init
的函数(即“构造函数”)时,才达到您要询问的那一行,所以让我们给它一个:
MyClass.prototype.init =
function (prop)
{
this.prop = prop;
};
一旦我们这样做了,考虑一下:
var myInstance1 = new MyClass('value');
在对MyClass
的调用中,this
将引用正在构造的对象,因此MyClass的这个实例将为true。并且typeof this.init==“function”
将为真,因为我们将MyClass.prototype.init
作为一个函数。所以我们达到了这条线:
this.init.apply( this, args.callee ? args : arguments );
return new MyClass( arguments );
return new MyClass( arguments );
这里的args
等于'value'
(第一个参数),因此它是一个字符串,因此它没有被调用方
属性;所以args.callee
是未定义的,这在布尔上下文中意味着它是false,所以args.callee?args:arguments
等同于arguments
。因此,上述行相当于:
function MyClass(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 );
}
this.init.apply(this, arguments);
this.init('value');
这相当于:
function MyClass(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 );
}
this.init.apply(this, arguments);
this.init('value');
(如果您还不知道apply
的工作原理,以及它与call
的区别,请参阅)
到目前为止,这有意义吗
另一个要考虑的情况是:
var myInstance2 = MyClass('value');
在对MyClass
的调用中,此
将引用全局对象(通常是窗口
),因此此MyClass实例将为false,因此我们到达这一行:
this.init.apply( this, args.callee ? args : arguments );
return new MyClass( arguments );
return new MyClass( arguments );
其中,参数
是一个类似数组的对象,包含一个元素:值
。请注意,这与newmyclass('value')
不同
术语说明:因此对MyClass('value')
的调用导致对MyClass
的第二次调用,这次是对new
的调用。我将把第一个调用(没有new
)称为“外部调用”,第二个调用(有new
)称为“内部调用”。希望这是直觉
在对MyClass
的内部调用中,args
现在引用外部调用的参数
对象:它不再是args
作为'value'
,而是一个类似数组的对象,包含'value'
。而不是未定义的args.callee
,它现在指的是MyClass
,所以args.callee?args:arguments
相当于args
。因此,对MyClass
的内部调用是调用this.init.apply(this,args)
,这相当于this.init('value')
因此,对args.callee
的测试旨在区分内部调用(MyClass('value')
→ <代码>新建MyClass(参数)
)从普通直接调用(新建MyClass('value')
)。理想情况下,我们可以通过更换以下线路来消除该测试:
this.init.apply( this, args.callee ? args : arguments );
return new MyClass( arguments );
return new MyClass( arguments );
假设有这样的情况:
return new MyClass.apply( itself, arguments );
但是JavaScript不允许这种表示法(也不允许任何等效的表示法)
顺便说一下,您可以看到Resig的代码存在一些小问题:
- 如果我们定义一个构造函数
MyClass.prototype.init
,然后通过编写var myInstance3=new MyClass()来实例化“类”
,则调用MyClass
时将未定义args
,因此对args.callee
的测试将引发错误。我认为这只是Resig的一个bug;无论如何,通过测试args&&args.callee
可以很容易地解决这个问题
- 如果构造函数的第一个参数恰好有一个名为
callee
的属性,那么对args.callee
的测试将产生一个假阳性,错误的参数将被传递到构造函数中。这意味着,例如,我们不能将构造函数设计为将参数
对象作为其第一个参数。但这个问题似乎很难解决,可能也不值得担心
@ruakh:G