"这"正在返回undefined

时间:2016-05-11 15:49:51

标签: javascript object this

我正在编写一个JavaScript程序,每秒运行一个对象的方法。该方法只记录对象的属性" x",然后添加一个。

构造对象(称为" player")的类被称为" Snake"和属性" x"明确定义为0.但是,当通过我的" everyTick"功能,记录' undefined'。

这很奇怪,因为该方法还记录了player.x,它正是它应该做的。但是当我使用"这个"而不是"播放器",它记录未定义。任何人都可以解释为什么以及如何解决它?

这是代码。

var FPS = 1;
var toBeRun = {
  func: function() {},
  index: 0
};

function tickFunction(func) {
  this.func = function() {
    func();
  }
}

function everyTick() {
  toBeRun.func()
  setTimeout(function() {everyTick();}, 1000 / FPS);
}

function forever(func) {
  toBeRun = new tickFunction(func);
}


function Snake() {
  this.x = 0;

  this.say = function() {
    console.log(player.x);
    console.log(this.x);

    player.x++;
    this.x++;
  }
}


var player = new Snake();

function start() {
  forever(player.say);
}

everyTick();

当你看到它时,它真的很混乱,所以这里是在CodePen中: http://codepen.io/Plygon/pen/jqJZvq?editors=0011

4 个答案:

答案 0 :(得分:2)

这是因为,当您调用forever时,您正在传递对player.say函数的引用,但该引用未绑定到Snake对象。因此,当调用函数时,它不知道this是什么。

这是一个简单的例子:

function Person(name) {
    this.name = name;
    this.say = function () {
        return this.name;
    };
}

var p = new Person('Bob');
console.log(p.say()); // Bob
var fn = p.say;
console.log(p.say()); // undefined;

您需要做的是将函数绑定到对象。函数的bind方法返回一个新函数,其中this绑定到传递给bind的任何对象:

var boundFn = p.say.bind(p);
console.log(boundFn()); // Bob

所以,如果你这样做:

forever(player.say.bind(player));

您应该可以在this功能中使用say

答案 1 :(得分:1)

这里的问题是scope this试试这个:

function Snake() {
  this.x = 0;
  var parent =  this;

  this.say = function() {
    console.log(player.x);
    console.log(parent.x);

    player.x++;
    parent.x++;
  }
}

this内的this.say {}}具有say函数的本地范围,您需要从this函数引用parent

答案 2 :(得分:1)

问题在于:

function start() {
  forever(player.say);
}

当你发送要在循环中使用的player.say函数时,你失去了与player对象的连接。

然后在调用funcion的地方,你做一个简单的函数调用,但不是播放器对象上的方法

function tickFunction(func) {
  this.func = function() {
    func(); // simple function invocation, which has `this` as `undefined`
  }
}

要解决此问题,只需将start功能更新为此功能:

function start() {
  forever(player.say.bind(player));
}

bind()将创建一个新函数,在调用它时,上下文始终与player实例连接。

This article提供了有关JavaScript中this关键字的大量详细信息。

答案 3 :(得分:1)

问题是你的函数失去了它的上下文(“this”)。

第一个选项是保存“this”(var self = this)。

另一种选择是使用bind,call或apply

希望这会有所帮助:)