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

时间:2015-12-23 02:17:48

标签: javascript jquery scope global-variables

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

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

$( 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 - open the console to see the messages

3 个答案:

答案 0 :(得分:2)

它变为'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);
});

答案 1 :(得分:0)

如果你想声明并使用全局范围变量,我认为最好的方法之一就是要明确它:

window.someGlobalVariable = 4;

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

答案 2 :(得分:0)

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

// 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