简体   繁体   English

JavaScript闭包无法访问外部变量

[英]JavaScript closure can't access outer variables

I have such a code and don't know why in anonymous function passed to nv.addGraph() I can't access variables from outer function like a , zcls or this.model . 我有这样的代码,不知道为什么在传递给nv.addGraph()的匿名函数中我无法访问外部函数中的变量,如azclsthis.model

function (out) {
// Here you call the "this" means the widget instance. (@see Mylable.js)
var zcls = this.getZclass(),
uuid = this.uuid;

// The this.domAttrs_() means it will prepare some dom attributes,
// like the pseudo code below
/*
 * class="${zcls} ${this.getSclass()}" id="${uuid}"
 */
var a = this.domAttrs_();
out.push('<span ', this.domAttrs_(), '>fds</span><div id="chart"><svg></svg></div>');



nv.addGraph(function() {
    var chart = nv.models.multiBarChart()
    .transitionDuration(350)
    .reduceXTicks(true)   // If 'false', every single x-axis tick label
    // will be rendered.
    .rotateLabels(0)      // Angle to rotate x-axis labels.
    .showControls(true)   // Allow user to switch between 'Grouped' and
    // 'Stacked' mode.
    .groupSpacing(0.1)    // Distance between each group of bars.
    ;

    chart.xAxis.tickFormat(d3.format(',f'));

    chart.yAxis.tickFormat(d3.format(',.1f'));

    var data = [{
        key: 'Some key',
        color: '#ff44ee',
        values: [{
            x: 1,
            y: 3
        }, {
            x: 3,
            y: 4
        }]
    }]

    d3.select('#chart svg').datum(data).call(chart);
//      d3.select('#chart svg').datum(this.model.data).call(chart);

    var someData = this.model.data;

    nv.utils.windowResize(chart.update);
    return chart;
});

This function is in some way used in ZKoss Widget so in this function it's possible to access its properties like this.model, but it's not possible in inner anonymous function. 这个函数以某种方式在ZKoss Widget中使用,所以在这个函数中可以访问它的属性,比如this.model,但是在内部匿名函数中是不可能的。 I have no idea what's wrong with it, I just started coding in JS. 我不知道它有什么问题,我刚开始用JS编写代码。

You don't access a or zcls in your closure but you should have no problem doing so. 你不能在你的闭包中访问azcls ,但你应该没有问题。

As for this , it is always a function local reference that is set by the caller of the function. 对于this ,它始终是由函数的调用者设置的函数本地引用。 If you want access to this as viewed by the parent function you need to either copy it to a local variable such as, 如果你想获得this由你需要或者将它复制到一个局部变量如父功能看,

var that = this;

in the parent and then refer to that instead of this in the closure, or, alternately, you can call bind() on the function passing in this such as. 在父然后参照that代替的this在封闭,或者,可替换地,可以调用bind()在经过在此,如功能。

nv.addGraph(function () {
   ...
}.bind(this));

which will cause the this in the function to be the same value as the parent's this . 这将导致this在功能相同的值作为父母的this

The this keyword in JavaScript doesn't work the same as in other OO languages for example Java . JavaScript中的this关键字与其他OO语言(例如Java)的工作方式不同。 It's value is determined during run-time and it depends exclusively on the way we invoke a function. 它的值是在运行时确定的,它完全取决于我们调用函数的方式。

There are four different ways that a function can be called: 可以通过四种不同的方式调用函数:

  1. Constructor call: Using the new keyword; 构造函数调用:使用new关键字; This refers to the newly created instance 这是指新创建的实例

    function Car = function(){ //... } var car = new Car(); function Car = function(){// ...} var car = new Car();

  2. Function call: When invoking a function that is defined in some scope eg global scope.In this case, this refers to the global object 函数调用:调用在某个范围内定义的函数,例如全局范围。在这种情况下,它指的是全局对象

    function someFunc(){} someFunc(); function someFunc(){} someFunc();

  3. Method call: When invoking a function that is defined as a member of an object. 方法调用:调用定义为对象成员的函数时。 eg 例如

    var obj = { func: function(){} } obj.func(); var obj = {func:function(){}} obj.func();

In this case this points to the object itself. 在这种情况下,这指向对象本身。

4 Call/Apply: Finally a function can be called with the help of two methods that are defined on the prototype of the Function constructor. 4调用/应用:最后,可以在Function构造函数原型上定义的两个方法的帮助下调用函数。 In this case we are free to set the value of this ourselves; 在这种情况下,我们可以自己设定价值; var obj = { func: function(){} } function someFunc(){} var obj = {func:function(){}} function someFunc(){}

someFunc.call(obj);

In your case, in order to access this.model you need to explicitly define where you want the this keyword to point. 在您的情况下,为了访问this.model您需要明确定义this关键字指向的位置。

You have to options: 你必须选择:

  1. Define a local variable eg var that = this; 定义一个局部变量,例如var that = this;
  2. Use the ES5 bind method 使用ES5 bind方法

    nv.addGraph(function () { ... }.bind(this)); nv.addGraph(function(){...} .bind(this));

An inner anonymous function will have the same scope as it's containing function. 内部匿名函数的范围与包含函数的范围相同。

You may consider passing-in zcls , or defining it within the function you are passing to nv.addGraph 您可以考虑传入zcls ,或者在传递给nv.addGraph的函数中定义它

MDN explains this really well: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope MDN解释得非常好: https//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope

You could define the function argument, then pass it by name. 您可以定义函数参数,然后按名称传递它。 For example: 例如:

var fcnArg = function() { ... }

nv.addGraph(fcnArg);

Another good discussion on this available here: Passing a function as an argument in a javascript function 关于这个的另一个很好的讨论在这里: 在javascript函数中传递函数作为参数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM