全局javascript变量在对象构造函数的一部分中变得未定义



我正在尝试重构一些代码,但遇到了一个问题,即全局变量在对象构造函数的一部分中正确定义,但在同一函数的另一部分中未定义。

我定义了一些全局变量如下:

$( document ).ready(function() {
  var imgWidth;
  var imgHeight;

然后我写了一个对象构造函数。最终目标是为图像创建一个对象,该对象包含:实际图像对象、宽度(定义为实际图像宽度/2)、高度(定义为真实图像高度/2)、x位置(手动指定)和y位置(手动规定)。

function Character(name, x, y){
    //define the image object within the Character
    this.imageObject = new Image();
    //using base-64 encoded data in place of an image url, just for the demo
    this.imageObject.src = name+'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAW0lEQVR42mL8//8/AzpgZGTcC6KBcs5wMRwK/0MVMsLEmLAoEmXAApiwiKUhaRJCltgLsQVsWwIQ/wTx0fBeRigD7B6Y24i1mj4Kn4KI7Uie2Y7FI8+B2AMgwABjRynfWgpcxQAAAABJRU5ErkJggg==';
    console.log(this.imageObject);
    console.log(this.imageObject.src);
    //set natural width and natural height once the image is loaded
    if (this.imageObject.addEventListener){
        this.imageObject.addEventListener('load', function(){
            console.log('this.naturalWidth for '+this.src+' = '+this.naturalWidth);
            window.imgWidth = this.naturalWidth/2;
            window.imgHeight = this.naturalHeight/2;
            console.log('imgWidth inside imageObject event listener for '+this.src+' = '+window.imgWidth);
        });
    } else if (this.imageObject.attachEvent){
        this.imageObject.attachEvent('onload', function(){
            console.log('this.naturalWidth for '+this.src+' = '+this.naturalWidth);
            window.imgWidth = this.naturalWidth/2;
            window.imgHeight = this.naturalHeight/2;
            console.log('imgWidth inside imageObject event listener for '+this.src+' = '+window.imgWidth);
        });
    }
    //set natural width and natural height to object
    this['w'] = this['w0'] = window.imgWidth;
    this['h'] = this['h0'] = window.imgHeight;
    //set initial x and y position
    this['x'] = x;
    this['y'] = y;
    console.log('imgWidth inside character constructor = '+window.imgWidth);
}

我这样调用函数,立即在文档内部准备好:

var sun0 = new Character('data:text/javascript;base64,', 1, 0);

在Chrome中检查控制台时,console.log行输出如下:

console.log(this.imageObject); //the image object as expected
console.log(this.imageObject.src); //the image url as expected
console.log('this.naturalWidth for '+this.src+' = '+this.naturalWidth); //10 as expected
console.log('imgWidth inside imageObject event listener for '+this.src+' = '+window.imgWidth); //5 as expected
console.log('imgWidth inside character constructor = '+window.imgWidth); //undefined

为什么此处未定义window.imgWidth?有没有更好的方法来创建这个对象,使其具有w的属性,即图像自然宽度的1/2?

JS Fiddle-打开控制台查看消息

它变为"undefined"的原因是因为您在事件处理程序函数中设置了imgWidth变量,该函数只在将来某个时候执行。事件处理程序函数是异步发生的,也就是说,在未来的某个时刻,程序在事件处理程序声明后继续执行代码。

当声明事件处理程序函数时,在调用onload事件处理程序之前,代码将继续运行并执行这些行:

//set natural width and natural height to object
this['w'] = this['w0'] = window.imgWidth;
this['h'] = this['h0'] = window.imgHeight;
//set initial x and y position
this['x'] = x;
this['y'] = y;

此时,尚未调用(激发)onload事件处理程序,因此运行时环境将正确地报告window.imgWidth未定义。

如果您希望运行此代码,最简单的方法是将以上内容添加到事件处理程序例程中,如下所示:

this.imageObject.attachEvent('onload', function(){
    console.log('this.naturalWidth for '+this.src+' = '+this.naturalWidth);
    window.imgWidth = this.naturalWidth/2;
    window.imgHeight = this.naturalHeight/2;
    console.log('imgWidth inside imageObject event listener for '+this.src+' = '+window.imgWidth);
    //set natural width and natural height to object
    this['w'] = this['w0'] = window.imgWidth;
    this['h'] = this['h0'] = window.imgHeight;
    //set initial x and y position
    this['x'] = x;
    this['y'] = y;
    console.log('imgWidth inside character constructor = '+window.imgWidth);
});

如果你想声明和使用全局范围变量,我认为最好的方法之一是非常清楚:

window.someGlobalVariable=4;

你似乎遇到的问题是,你实际上不在全局范围内,而是在函数范围内。确切地说:在DOM ready上的回调中。

这应该说明本地和全局范围变量的问题:

// imgWidth hasn't been defined yet
console.log('before ready statement: ' + typeof imgWidth);
$(window).ready(function() {
  // here we are defining a local variable named imgWidth 
  var imgWidth = 100;
});
console.log('after ready statement: ' + typeof imgWidth);

// imgWidth hasn't been defined yet
console.log('before ready statement: ' + typeof imgHeight);
$(window).ready(function() {
  // here we are defining a a global variable named imgHeight 
  window.imgHeight = 200;
});
console.log('after ready statement: ' + typeof imgHeight);
console.log('imgHeight is ' + imgHeight);

输出:

before ready statement: undefined
after ready statement: undefined
before ready statement: number
after ready statement: number
imgHeight is 200

相关内容

最新更新