Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/59.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 - Fatal编程技术网

Javascript类和变量引用

Javascript类和变量引用,javascript,Javascript,我正试图解决这个思维混乱的Javascript OOP问题 因此,我有以下课程: var ClassA = function() { this.initialize(); } ClassA.prototype = { methods : ['alpha','beta','gama'], initialize : function() { for ( var i in this.methods ) { this[this.met

我正试图解决这个思维混乱的Javascript OOP问题

因此,我有以下课程:

var ClassA = function() {
    this.initialize();
}

ClassA.prototype = {

    methods : ['alpha','beta','gama'],

    initialize : function() {
        for ( var i in this.methods ) {
            this[this.methods[i]] = function() {
                console.log(this.methods[i]);
            }
        }
    }
}

var a = new ClassA();
当我调用每个方法时,我希望打印它的名称,对吗?但我得到的是:

a.alpha(); // returns gama ?!?
a.beta();  // returns gama ?!?
a.gama();  // returns gama
但是当我的班级看起来像这样的时候:

var ClassB = function() {
    this.initialize();
}

ClassB.prototype = {

    methods : ['alpha', 'beta', 'gama'],

    initialize: function() {
        for ( var i in this.methods ) {
            this.addMethod(this.methods[i]);
        }
    },

    addMethod: function(method) {
        this[method] = function() {
            console.log(method);
        }
    }

}

var b = new ClassB();

b.alpha(); // returns alpha
b.beta();  // returns beta
b.gama();  // returns gama
为什么会这样

for ( var i in this.methods ) {
      this[this.methods[i]] = function() {
          console.log(this.methods[i]);
       }
}
你的问题就在这里。当此循环结束时,
i
是最后一个元素。每个函数使用相同的
i
,因此它们都是最后一个元素

当您使用
addMethod
时,您正在进行闭包以“捕获”正确的值

编辑:当您调用
addMethod
时,您是在“复制”该值,而不是使用
i
值,该值随每次循环迭代而变化。

在您的第一个版本中:

initialize : function() {
    for ( var i in this.methods ) {
        this[this.methods[i]] = function() {
            console.log(this.methods[i]);
        }
    }
}
initialize
中创建的方法都引用来自
initialize
的同一
i
变量,并且在
initialize
运行后
i
具有值
“gama”
,因此无论调用哪种方法,它们都将登录到控制台。在创建方法时,JS不存储
i
的当前值

JS为每个函数创建一个“闭包”-在
初始化
函数(即
i
)中声明的变量即使在
初始化
完成后仍然在嵌套函数的范围内

第二个版本调用
addMethod
来添加每个方法:

addMethod: function(method) {
    this[method] = function() {
        console.log(method);
    }
}
…因此,当它们运行时,它们将引用自己的
方法
参数的“副本”,因为每个方法都有一个单独的闭包


编辑:另请参见此问题:(这里有几个答案比我解释得更清楚)。

您可以通过添加匿名闭包修复第一个示例:

initialize : function() {
    for ( var i in this.methods ) {
        (function (i) { // anonymous closure
            this[this.methods[i]] = function() {
                console.log(this.methods[i]);
            }
        }).call(this, i); // use .call() if you need "this" inside
    }
}
现在,它将以与第二个示例相同的方式工作。“匿名”意味着闭包是由没有名称的函数完成的,并且在“创建”时立即被调用

侧面注意:使用
.call(this,…)
this
保存在被调用函数中,或者您可以执行
var that=this
,使用
that
而不是
this
并正常调用函数:

for ( var i in this.methods ) {
    var that = this;
    (function (i) { // anonymous closure 
        that[that.methods[i]] = function() {
            console.log(that.methods[i]);
        }
    })(i); // Called normally so use "that" instead of "this"!
}

首先,停止在数组上使用for(对象中的属性)循环。这一切都是有趣的游戏,直到有人原型阵列对象,这是一个非常合理和非常有用/流行的事情做。这将导致将自定义方法添加到for x in数组循环中


至于这个问题,它正在做你在版本1中告诉它要做的事情。问题是,当你准备发射它时,我是最后一个我是“伽马”的东西。当您将引用作为参数传递到函数中时,函数会在传递时保持值的状态。

我几乎每天都回答这样的问题。。。我很困惑。。。console.log不是另一个函数吗?通过addMethod,我只是将它包装到另一个函数中?@drinchev:
console.log
在这里并不重要。这里重要的是,当您调用
addMethod
时,您将值复制到每个函数中,但当您不使用它时,您使用的是相同的值。(如果我没有很好地解释的话,很抱歉。)第一个例子是闭包,因为它创建了一个引用其封闭范围中某个内容的新范围。第二个函数在函数调用期间复制值,因此它不是闭包@dtanders:但是
addMethod
函数内部有一个闭包:-这不是通过JS中的数组进行循环的闭包吗?@RepWhoringPeeHaa-是的,应该使用普通的for循环,但这不是问题所在。@nnnnnn我知道这就是为什么它是注释而不是答案:-)他已经解决了问题,他首先想知道为什么这是一个问题。是的,但这种解决方法更直接、更简单。我同意,但它仍然不能回答最初的问题。