Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 简单“;类别”;实例化_Javascript_Oop - Fatal编程技术网

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