jquery / javascript,变量范围问题

时间:2013-04-24 16:51:00

标签: javascript jquery

我知道这可能是一个非常棒的问题,但我无法看到这里的问题是返回变量pic_real_width.

我认为它是一个范围的东西,但除了使它成为全局之外(不能这样做)我不确定如何设置和返回它。

提前致谢,

function get_real_width(img){
    var pic_real_width;
    $("<img/>") // Make in memory copy of image to avoid css issues
      .attr("src", $(img).attr("src"))
      .load(function() {
         pic_real_width = this.width;   
         console.log( pic_real_width ); // returns a number
       });
   console.log( pic_real_width ); //returns undefined
   return pic_real_width;
}

6 个答案:

答案 0 :(得分:1)

您的函数将在.load调用完成之前退出,因此没有值返回。

在负载的回调函数期间设置'pic_real_width',但同时,在等待.load完成之前,您的函数将继续执行,因此在设置值之前退出。

答案 1 :(得分:1)

简单地说,传递给加载的函数是异步的,异步函数具有不同的模式函数上下文。

在该示例中,无法遇到解决方案(我现在无法找到解决方案),但是,您可以重构代码以使图像的“实际宽度”异步,只需传递其他回调在传递给load()的函数内部调用。

如:

function get_real_width(img, callback){
    var pic_real_width;
    $("<img/>") // Make in memory copy of image to avoid css issues
    .attr("src", $(img).attr("src"))
    .load(function() {
        pic_real_width = this.width;   
        callback( img, pic_real_width ); // Call the function with the number expected
    });
}

因为它只是获得宽度并将其返回到函数。

但是,我知道,在某些情况下不能使用它。

祝你好运。

答案 2 :(得分:0)

.loadload事件处理程序附加到图像,并且该事件可能异步触发(如果浏览器缓存图像,它可能是同步的),这意味着.load调用立即返回,当您到达return pic_real_width;时,处理程序尚未执行。

但是,您可以使用$.Deferred以优雅的方式解决此问题。

function get_real_width(img){
    var def = $.Deferred();
    $("<img/>")
      .load(function() {
         def.resolve(this.width);
       })
      .attr("src", $(img).attr("src"));
    return def;
}

get_real_width().done(function (width) {
    console.log(width);
});

请注意,我在设置源代码之前附加了处理程序,以防图像被缓存并且事件被同步触发

答案 3 :(得分:0)

在英语中,这是get_real_width目前正在做的事情:

  1. 创建一个名为pic_real_width的本地变量。
  2. 使用复制的src属性创建新的<img/>元素,一次加载<img/>元素,然后运行内部函数。 “once / then”部分是每个人都描述为异步的部分,因为您不知道或无法控制何时会发生相对于其他代码的事件。
  3. 立即登录并返回pic_real_width
  4. 请注意,只有在调用内部函数并完成后才会设置pic_real_width,但在get_real_width退出时可能不会发生pic_real_width,因此当您使用时get_real_width将不会被定义记录并返回。

    那么,你如何解决这个问题?

    这取决于你如何使用get_real_width的结果。例如,如果您是根据alert(get_real_width(some_img)); 的结果创建警报,请执行以下操作:

    function alert_real_width(img){
        $("<img/>")
          .attr("src", $(img).attr("src"))
          .load(function() {
             var pic_real_width = this.width;   
             alert( pic_real_width );
           });
    }
    

    然后,您可以修改您的函数,以便在附加到.load的函数内发生警报:

    alert

    显然,我怀疑你是在做{{1}},但这应该会让你知道如何处理这个问题。对于更通用的解决方案,您可以像其他用户建议的那样使用回调。

答案 4 :(得分:0)

回复承诺只是一点点&#34;更好...

function get_real_width(img, callback) {
    var dfd= $.Deferred(function (dfd) {

        $("<img/>")
            .attr("src", $(img).attr("src"))
            .load(function () {
                dfd.resolve(this.width);
            });
    });

    return dfd.promise();
}

答案 5 :(得分:0)

默认情况下,ajax()请求是异步的,因此对ajax()的调用通常会在请求完成之前返回。您可以使用回调函数。

function get_real_width(img, callback){
    var pic_real_width;
    $("<img/>") // Make in memory copy of image to avoid css issues
    .attr("src", $(img).attr("src"))
    .load(function() {
        pic_real_width = this.width;   
        callback(pic_real_width ); // Call the function with the number expected
    });
}

 get_real_width(img, function(returnedData){ //anonymous callback function        
    console.log(myVariable);
    return returnedData;
 });

如果您绝对必须,可以使用async: false inside the call to ajax()