带有bind,call& amp;的超时应用方法

时间:2015-06-19 21:38:48

标签: javascript closures this settimeout iife

到目前为止,在创建需要访问其父级的函数之前,我总是使用var self = this。但是,bind()方法似乎是更合适的方法,我正在探索该选项以及apply()call()方法。

这是我想出来比较所有三个:

jsFiddle

(function(){

    this.say = function(text){
        
        console.log(text);
    }
        
    this.run = function(){
        
        console.clear();
        
        setTimeout(function(){
            this.say('bind');
        }.bind(this), 1000);
        
        setTimeout(function(){
            this.say('call');
        }.call(this), 1000);
        
        setTimeout(function(){
            this.say('apply');
        }.apply(this), 1000);
    }
    
    this.run();
    
})();

但剧本给我留下了一些问题:

  1. 为什么call()apply()方法不像bind()方法那样遵循超时,我应该使用哪一种?

  2. 以下类似行为的语法之间有什么区别:

    setTimeout( function(){ this.say('bind'); }.bind(this) , 1000);
    
    setTimeout( (function(){ this.say('bind'); }).bind(this) , 1000);
    
    setTimeout( (function(){ this.say('bind'); }.bind(this)) , 1000);
    

2 个答案:

答案 0 :(得分:3)

你在这里错过了一个关键点(但关键点在文档中非常模糊)。

你知道什么时候写这样的函数:

function something() {
    // ... whatever
}

它只是一个独立的功能参考。它还没有被召唤。

当你写这样的东西时:

(function something() {

})()

或者这个:

function something() { ... }

something();

您现在 调用 这个功能。这是两个完全不同的概念。

在第一个函数只是坐在那里而没有被调用的情况下,它被称为函数引用,而这正是{{1} } return:一个函数引用

.bind.call会在新的上下文中返回任何函数的 返回值 。所以在假的JavaScript la-la land中,它看起来像这样:

.apply

鉴于:

function() {

}.bind(this)

// returns a function reference: function() {  }

你看......

你可能永远不会做这样的事情:

function() {
    return 'hello';
}.call(this)
// returns hello... NOT A FUNCTION REFERENCE!

您收到错误:function hello() { return true; } setTimeout(hello(), 100); ,或类似的内容。

function error

^这不是一个非常语义错误,但它仍然是一个错误。

但是,你 做的事情是这样的:

setTimeout expected a Function, and it received a Boolean

看到区别?最后一个例子没问题,因为你传递了一个函数引用

因为在内部,function hello() { return true; } setTimeout(hello, 100); 做了类似的事情:

setTimeout

至于你的第二个问题......

这几乎是完全相同的。只要您声明不想让其他对象访问的变量,闭包就会有意义。

为了帮助您了解一些关闭,让我们假装我们甚至不讨论JavaScript。

在数学方面,你知道如何做window.setTimeout = function(callback) { // a bunch of other stuff, and... callback(); }; 之类的事情吗?

好吧,当你用括号对它们进行分组时,它会改变行为:a + b * c

现在,显然这与JavaScript并不完全相关,因为在JavaScript中我们并不担心操作顺序(除非您实际上在JavaScript中进行数学运算),但整体而言我们的想法是,这些括号只是作为容器(我们称之为闭包)的内容。

因此,当您将一个函数放在括号中时,您只是将该函数隐藏在外部世界中,但它仍然可以返回内容,并且它仍然可以访问父作用域(如(a + b) * c),例如)。

一个很酷的例子:

window

答案 1 :(得分:1)

.call.apply都会立即执行调用它们的函数。这意味着,在这些情况下,您将匿名函数的callapply结果传递给setTimeout,结果为{{1}因为那些函数不返回任何东西。

另一方面,

undefined返回一个新函数,然后您正确地传递给bind。要获得调用并应用于类似的行为,请将它们移到匿名函数中:

setTimeout
例如,

  1. Afaik那些是等价的。