【问题标题】:Anonymous function losing scope匿名函数失去作用域
【发布时间】:2011-12-09 05:46:16
【问题描述】:

为什么这不起作用?

var img = new Image();
this.dimensions = [ ];
var m = this;
img.onload = function(){ 
    return function(){
        m.dimensions = [ this.width, this.height ]; 
    }
};
img.src = 'images/whatever.jpg';


console.log(this.dimensions);
[]

(在 JS 对象内部,因此是“this”)

编辑:工作代码

var img = new Image();
this.dimensions = [  ];
var m = this;
img.onload = function(){ 
    m.dimensions.push(this.width, this.height);  
    console.log(m.dimensions) // had to wait
};
img.src = 'whatever.jpg';

【问题讨论】:

  • 维度数组未设置为图像的宽度和高度
  • 在函数内部,console.log([ this.width, this.height ]) 可以很好地返回它们。我正在创建 m 变量以保持其范围正确。
  • 您可能希望确保您的函数被调用:最后的评论不可能是真的。一个或另一个是错误的。
  • 我修好了。 return function() 是不必要的,出于某种原因,m.dimensions.push( this.width, this.height ) 有效,而 m.dimensions = [ this.width, this.height ] 仍然无效。
  • 你的代码不符合我的逻辑:(请考虑一个jsfiddle。

标签: javascript scope anonymous-function


【解决方案1】:

你确定console.log(this.dimensions) 是在图像加载后运行的吗?您添加到 img.onload 的是一个回调函数,用于在图像在 DOM 中完成加载后运行。在该 img 完成加载之前,尚未设置 m.dimensions。添加回调时,图片不会立即加载,而是异步加载,随时可以完成。

换句话说,您在设置维度之前(在运行 onload 回调之前)运行 console.log(this.dimensions)。我敢打赌,如果你将 console.log 包装在一个 setTimeout 调用中,比如 5 秒,那么它会记录你所期望的。

【讨论】:

  • 你是对的。我以前犯过这个愚蠢的错误,我希望 Javascript 能够逐行执行。
【解决方案2】:

这是因为this 在新函数定义中改变了含义。您可以通过将其缓存在局部变量中来解决此问题。在这里,这已经完成了;您将其保存在变量m 中。所以只需使用m 而不是this

var img = new Image();
this.dimensions = [ ];
var m = this;
img.onload = function(){ 
    return function(){
        m.dimensions = [ m.width, m.height ]; 
    }
};
img.src = 'images/whatever.jpg';

这是一个很好的教程,解释了this 如何在不同的上下文中改变含义:http://javascriptweblog.wordpress.com/2010/08/30/understanding-javascripts-this/

【讨论】:

  • 这仍然会有问题。 m.dimensions = ...从未被执行
【解决方案3】:

请考虑此代码不会提醒:

img.onload = function(){ 
    return function(){
        alert("hi")
    }
};

然后考虑标准(可能需要)“双重封闭”:

img.onload = (function(m){ 
    return function(){
        alert(m)
    }
})(this)

编码愉快。

【讨论】:

  • 这就是JS中所谓的自调用函数吗?
  • @RussellDias 它不是自动调用的,因为它是手动调用的 :) 我认为,也许是“一个立即执行的匿名函数”。
猜你喜欢
  • 1970-01-01
  • 2011-03-11
  • 2017-08-13
  • 2011-09-10
  • 2011-12-15
  • 2011-06-22
  • 2011-12-11
  • 2013-07-07
  • 1970-01-01
相关资源
最近更新 更多