简体   繁体   English

绑定,调用和应用方法超时

[英]Timeout with bind, call & apply methods

Up until now, I've always used var self = this before creating a function that would need access to its parent. 到目前为止,在创建需要访问其父级的函数之前,我一直使用var self = this However the bind() method seems like a more appropriate way to do so and I'm exploring that option, along with the apply() and call() methods. 但是, bind()方法似乎是一种更合适的方法,我正在研究该选项以及apply()call()方法。

This is what I came up with to compare all three: 这是我想比较所有三个方面的结果:

jsFiddle 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(); })(); 

But the script leaves me with some questions: 但是脚本给我一些问题:

  1. Why don't the call() and apply() methods respect the timeout like the bind() method does and which one should I use? 为什么call()apply()方法不像bind()方法那样遵守超时,我应该使用哪一个?

  2. Is there any difference between the following syntaxes which behave similarly: 下列行为类似的语法之间是否有任何区别:

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

You're missing a key point here (but the key point is very obfuscated in documentation). 您在这里缺少关键点(但是关键点在文档中非常模糊)。

You know whenever you write a function like this: 您知道只要编写这样的函数:

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

It's just a function reference sitting there by itself. 它本身就是一个函数引用。 It hasn't been called yet. 尚未被调用。

When you write something like this: 当您编写如下内容时:

(function something() {

})()

Or this: 或这个:

function something() { ... }

something();

You've now called the function. 您现在已经调用了该函数。 Those are two very completely different concepts. 这是两个完全不同的概念。

In the first one where the function is just sitting there without having been called, it's referred to as a function reference , and that's exactly what .bind returns: a function reference . 在第一个函数没有被调用的情况下,它只是坐在那里,它被称为函数引用 ,而这正是.bind返回的内容: 函数引用

.call and .apply return the return value of whatever function, in the new context. .call.apply返回任何函数的返回值 ,在新的环境。 So in fake JavaScript la-la land, it would look something like this: 因此,在伪造的JavaScript la-la领域中,它看起来像这样:

function() {

}.bind(this)

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

Whereas: 鉴于:

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

You see... 你看...

You would probably never do something like this: 您可能永远不会做这样的事情:

function hello() {
    return true;
}

setTimeout(hello(), 100);

You'd get an error: setTimeout expected a Function, and it received a Boolean , or something like that. 您会得到一个错误: setTimeout expected a Function, and it received a Boolean或类似的东西。

功能错误

^ That's not a very semantic error, but it's an error nonetheless. ^这不是一个非常语义上的错误,但是仍然是一个错误。

But, what you would do is something like this: 但是,您执行以下操作:

function hello() {
    return true;
}

setTimeout(hello, 100);

See the difference? 看到不同? That last example is okay, because you passed in a function reference . 最后一个示例是可以的, 因为您传入了函数reference

Because internally, setTimeout does something like this: 因为在内部, setTimeout执行以下操作:

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

    callback();
};

As far as your second question goes... 至于第二个问题...

Those are pretty much all equivalent. 这些几乎都是等效的。 Closures make sense though whenever you're declaring variables that you don't want to give other objects access to. 闭包是有意义的,尽管每当您声明不想让其他对象访问的变量时。

To help you understand closures a little bit, let's pretend we're not even talking about JavaScript. 为了帮助您稍微了解一下闭包,让我们假设我们甚至没有在谈论JavaScript。

In math, you know how you can do something like a + b * c ? 在数学中,您知道如何做类似a + b * c事情?

Well, when you group them by parentheses, it kind of changes the behavior: (a + b) * c . 好吧,当您用括号将它们分组时,它会改变行为: (a + b) * c

Now, obviously that's not quite related to JavaScript in the sense that in JavaScript we're not worried about order of operations (unless you're actually doing math in JavaScript), but the whole idea is that those parentheses just act as a container (what we call a closure) for whatever is inside of it. 现在,显然这与JavaScript并不完全相关,因为在JavaScript中,我们不必担心操作的顺序(除非您实际上是在JavaScript中进行数学运算),但是整个想法是,这些括号仅充当容器 (我们称之为闭包的内容)。

So when you put a function inside parentheses, you're just hiding that function from the outside world, but it can still return stuff, and it can still have access to parent scopes (like window , for example). 因此,当您将函数放在括号内时,您只是将函数隐藏在外部世界中,但是它仍然可以返回内容,并且仍然可以访问父作用域(例如window )。

A cool example: 一个很酷的例子:

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

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

Both .call and .apply execute the functions on which they are called immediately. 无论.call.apply执行它们所立即打电话的功能。 What this means is that in those cases you are passing the result of call or apply on your anonymous function to setTimeout and that result is undefined because those functions don't return anything. 这意味着在这种情况下,您要将call 结果传递给setTimeoutapply到匿名函数上,而该结果是undefined因为这些函数不返回任何内容。

bind on the other hand returns a new function, which you are then correctly passing to setTimeout . 另一方面, bind返回一个新函数,然后将其正确传递给setTimeout To get call and apply to behave similarly, move them inside the anonymous function: 要获得呼叫并申请具有类似行为,请将其移至匿名函数内:

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

for example. 例如。

  1. Afaik those are equivalent. Afaik那些是等效的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM