JavaScript - “this”指向Window而不是object

时间:2013-12-28 23:45:13

标签: javascript oop

我第一次面对JavaScript中的OOP以及随之而来的所有麻烦......

我有这个函数/ Object / class /具有方法mainLoop()的任何应该显示一些下降文本的东西 - 就像在电影 The Matrix 中一​​样。当我调用它时虽然我得到了未定义的变量错误并使用调试器,但我发现mainLoop() this内部指的是Window而不是调用该方法的对象。

以下是代码:

function Matrix(config) {

    return {
        //[...lots of other vars...],
        drops: [],
        lines: [],
        //final string to put in the container
        str: "",

        mainLoop: function(){
            var tmp = "";
            //randomly create a "character drop"
            //(not if there's already a drop)
            for(var i = 0; i < this.cols; i++){
                if(this.drops[i] == 0 && Math.random() < this.freq){
                    this.drops[i] = irandom(this.rows) + 1;//new drop
                    tmp += randomChar();//output drop
                }
                else tmp += lines[0].charAt(i);
            }
            this.lines[0] = tmp; // <-------------- ERROR

            //update already created drops
            tmp = "";
            for(var j = 0; j < this.cols; j++){
                if(this.drops[j] > 0){
                    tmp += this.randomChar();
                    this.drops[j]--;
                }
                else tmp += " ";
            }
            this.lines[this.rowIndex] = tmp;
            this.rowIndex = (this.rowIndex+1) % this.rows;

            //render the entire text
            this.str = "";
            for(var l in this.lines)
                this.str += l + "<br/>";

            $(container).html = this.str;

        },

        start: function(){
            for(var i = 0; i < this.cols; i++)
                this.drops[i] = 0;
            timer = setInterval(this.mainLoop ,this.delay);
        },

        stop: function(){
            clearInterval(this.timer);
        },

        randomChar: function(){
            return this.chars.charAt(irandom(this.chars.length));
        },

        irandom: function(x){
            return Math.floor(Math.random()*x);
        }
    }
};

然后我将此函数称为:

var config = {
    container: "#container",
    rows: 20,
    cols: 20,
    delay: 2000
};
var m = Matrix(config);
m.start();

浏览器控制台说:

TypeError: this.lines is undefined

(代码注释显示错误的确切点)。此外,调试器说,此时,this指向Window,而不是m正如我所期望的那样...我的推理有什么问题?提前感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

更改start功能:

    start: function(){
        var self = this;
        for(var i = 0; i < this.cols; i++)
            this.drops[i] = 0;
        timer = setInterval(function() {
            self.mainLoop(); 
        }, this.delay);
    }

this指向window,因为范围已发生变化。

答案 1 :(得分:1)

由于JavaScript是基于原型的,可能(如果你还没有)尝试按照这个模型进行:

function Matrix(config) {

    this.property = config.firstmember;
    this.property2 = config.secondmember;

    return function() { console.log('hello world') };

}

Matrix.prototype = {

    someMethod: function() {
        //do something
    },
    start: function() {
        //console.log('hello world');
    },
    stop: function() {
        //do something
    }

}

var config = {
    firstMember: 'foo',
    secondMember: 'bar'
}

var m = new Matrix(config);

//console output: "hello world"

/*var m = {
    property: 'foo',
    property2: 'bar',
    ____proto___: Matrix: {
            someMethod: function() {
                //do something
            },
            start: function() {
                //console.log('hello world');
            },
            stop: function() {
                //do something
            }
        }

}*/

另请参阅有关setInterval的the answer to this question

setInterval回调函数是Window对象的成员;因此,'this'指的是窗口。您需要将当前对象的参数传递给setInterval内的回调。有关详细信息,请参阅上面的链接。

答案 2 :(得分:0)

如果您需要对调用对象的引用,我建议将其作为参数传递给函数。