我正在编写一个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
答案 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
希望这会有所帮助:)