JavaScript对象如何调用自身函数

13

我一直在阅读有关HTML5和JavaScript的游戏设计,并且这让我了解到对象。因此,在阅读完该书并完成项目后,我决定将这个新发现的知识融入到我的项目中。所以我有一个问题,对象能否或者应该调用它们自己的函数?例如:

var someObject = {
    start: function() {
        check();
    },
    check: function() {
        console.log("Check!");
    }
};

someObject.start();

这本书展示了一个使用计时器的例子,其做法是:

var timer = {
    start: function() {
        var self = this;
        window.setInterval(function(){self.tick();}, 1000);
    },
    tick: function() {
        console.log('tick!');
    }
};

在计时器对象的示例中,它使用self来调用内部函数的引用,那么这是否意味着我应该使用self来调用内部函数,还是这是使用对象的正确方式?还是最佳实践?提前谢谢。

var someObject = {
    start: function() {
        var self = this;
        self.check();
    },
    check: function() {
        console.log("Check!");
    }
};

someObject.start();

3
setTimeout的例子中使用它的原因是因为它的回调在全局范围内执行,所以setTimeout回调中的this值是window。为了保留对原始对象的引用,必须使用该方法(将其存储在self中)或某种形式的Function.bind() - Ian
4个回答

12

JavaScript的名称具有词法作用域,因此每当脚本中遇到一个名称(变量),JavaScript运行时必须从定义函数的范围向上搜索。

在定义时,该函数:

start: function() {
    check();
}

在其外部作用域中没有访问任何check函数。声明self并将其绑定到this是一种处理JavaScript中有关于(有点有趣的)引用当前对象的复杂性的技术(因为示例代码使用了window.setInterval)。

要引用当前对象中的函数,只需使用this即可。

var someObject = {
    start: function() {
        this.check();
    },
    check: function() {
        console.log("Check!");
    }
};

3

这是JavaScript函数上下文,每次创建函数都会创建一个新的上下文(作用域)。

setInterval()函数中,您将创建一个新的作用域,因此this不再指代上面相同的this

var self = this;
setInterval(function() {
    self.tick();
}, 1000);

您也可以使用bind()手动绑定函数的正确上下文(因此不再需要self):

setInterval(function() {
    this.tick();
}.bind(this), 1000);

更多信息:


1
声明和初始化变量"self"的目的是处理每次函数调用时确定this值的事实。当您在一个函数嵌套另一个函数中,并且该内部函数需要访问外部上下文中this的值时,this必须以另一个变量(在您的情况下为"self")中保留。(当然,该变量的名称并不重要。)
在您的示例代码中:
var timer = {
    start: function() {
        var self = this;
        window.setInterval(function(){self.tick();}, 1000);
    },
    tick: function() {
        console.log('tick!');
    }
};

在调用setInterval()时传入的那个函数需要使用"start"函数中this的值。然而,当定时器函数被调用时,this被设置为其他值(全局上下文或在"严格模式"下为null)。因此,在实例化定时器函数的上下文中保存this的值,它的代码就可以使用它来访问定时器对象。

在第二个示例中,声明和初始化一个"self"变量不会有任何影响,但是这是不必要的。有时候,这样做很方便,只是为了澄清代码,当然,比"self"更有意义的名称会更好。


不过第二个示例并不是在做这个。 - aaronman

0

当然,一个对象可以并且应该调用自己的函数,这是在 JavaScript 中模拟 OOP 的唯一方法。我会说书中使用的做法 self = this 是不好的,因为 this 可以单独使用,但在第一个示例中它被用于保存 this 的值,否则将是函数本身的 this 而不是外部类。


"仿真"; 只要不停地告诉自己,可能同时点击你的鞋跟说出来... - dandavis
var self = this 有多个原因;一个完全无关的原因是使脚本压缩更有效。 - voithos
@voithos 请阅读整个答案,我只是说第二种用法不好。 - aaronman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接