javascript - 使用绑定(bind)、调用和应用方法设置超时

标签 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);
    

最佳答案

您在这里遗漏了一个关键点(但关键点在文档中非常模糊)。

你知道每当你写这样的函数时:

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

它本身只是一个函数引用。尚未调用。

当你这样写的时候:

(function something() {

})()

或者这个:

function something() { ... }

something();

您现在已经调用了该函数。这是两个截然不同的概念。

在函数未被调用的第一个函数中,它被称为函数引用,这正是 .bind 返回的内容:< strong>函数引用。

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

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);

你会得到一个错误:setTimeout 需要一个函数,它收到了一个 bool 值,或者类似的东西。

function error

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

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

function hello() {
    return true;
}

setTimeout(hello, 100);

看出区别了吗?最后一个示例没问题,因为您传入了一个函数引用

因为在内部,setTimeout 做了这样的事情:

window.setTimeout = function(callback) {
    // a bunch of other stuff, and...

    callback();
};

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

这些几乎都是等价的。尽管当您声明不想让其他对象访问的变量时,闭包是有意义的。

为了帮助您稍微理解闭包,让我们假装我们甚至没有在谈论 JavaScript。

在数学中,您知道如何做 a + b * c 吗?

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

现在,显然这与 JavaScript 没有太大关系,因为在 JavaScript 中我们不担心操作顺序(除非你实际上在 JavaScript 中进行数学运算),但整个想法是那些括号只是作为一个容器(我们称之为闭包),用于存放其中的任何内容。

所以当你将一个函数放在括号内时,你只是将该函数从外界隐藏起来,但它仍然可以返回东西,并且它仍然可以访问父作用域(比如 window ,例如)。

一个很酷的例子:

var name = (function(name) {
    return name
})(function() {
    return 'Jane';
}());

console.log(name); // => Jane

关于javascript - 使用绑定(bind)、调用和应用方法设置超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30947650/

相关文章:

java - groovy 中的闭包与 java 8 中的闭包(lambda 表达式)?

javascript - 创建具有值参数而不是引用的函数引用

java - Java “this”-在Eclipse内容帮助中标记为静态的关键字

javascript - Jquery nextUntil 和行单元格

javascript 奇怪的语法 : c. name=i+ +new Date;

javascript - 带有条件的 jQuery 切换类

generics - Rust说,即使设置了适当的生命周期,功能参数的生命周期也不够

c++ - *this-> 不能作为函数使用

javascript - 将 this 绑定(bind)到高阶函数中的原始对象

c# - charCodeAt 到 C# 的转换