绑定、调用和应用方法超时
Timeout with bind, call & apply methods
到目前为止,在创建需要访问其父项的函数之前,我总是使用 var self = this
。然而,bind()
方法似乎是更合适的方法,我正在探索该选项,以及 apply()
和 call()
方法。
这是我想出的比较所有三个的方法:
(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();
})();
但是脚本给我留下了一些问题:
为什么 call()
和 apply()
方法不像 bind()
方法那样遵守超时,我应该使用哪一个?
以下行为相似的语法之间是否有任何区别:
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
returns:函数引用。
.call
和 .apply
return return 值 随便什么功能,在新的上下文中。所以在假 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 expected a Function, and it received a Boolean
,或类似的东西。
^ 这不是一个非常语义化的错误,但它仍然是一个错误。
但是,你会做的是这样的:
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), 但整个想法是那些括号只是作为一个 容器 (我们称之为闭包)来容纳其中的任何内容。
所以当你将一个函数放在括号内时,你只是将该函数从外部世界隐藏起来,但它仍然可以 return 东西,并且它仍然可以访问父范围(如 window
,例如)。
一个很酷的例子:
var name = (function(name) {
return name
})(function() {
return 'Jane';
}());
console.log(name); // => Jane
.call
和 .apply
都立即执行调用它们的函数。这意味着在这些情况下,您将匿名函数上的 call
或 apply
的 result 传递给 setTimeout
,结果是 undefined
因为这些函数没有 return 任何东西。
另一方面,bind
return 是一个新函数,您可以将其正确传递给 setTimeout
。要获得调用和应用以类似的行为,请将它们移动到匿名函数中:
setTimeout(function(){
this.say.call (this, 'call');
}, 1000);
例如。
- Afaik 这些是等效的。
到目前为止,在创建需要访问其父项的函数之前,我总是使用 var self = this
。然而,bind()
方法似乎是更合适的方法,我正在探索该选项,以及 apply()
和 call()
方法。
这是我想出的比较所有三个的方法:
(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();
})();
但是脚本给我留下了一些问题:
为什么
call()
和apply()
方法不像bind()
方法那样遵守超时,我应该使用哪一个?以下行为相似的语法之间是否有任何区别:
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
returns:函数引用。
.call
和 .apply
return return 值 随便什么功能,在新的上下文中。所以在假 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 expected a Function, and it received a Boolean
,或类似的东西。
^ 这不是一个非常语义化的错误,但它仍然是一个错误。
但是,你会做的是这样的:
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), 但整个想法是那些括号只是作为一个 容器 (我们称之为闭包)来容纳其中的任何内容。
所以当你将一个函数放在括号内时,你只是将该函数从外部世界隐藏起来,但它仍然可以 return 东西,并且它仍然可以访问父范围(如 window
,例如)。
一个很酷的例子:
var name = (function(name) {
return name
})(function() {
return 'Jane';
}());
console.log(name); // => Jane
.call
和 .apply
都立即执行调用它们的函数。这意味着在这些情况下,您将匿名函数上的 call
或 apply
的 result 传递给 setTimeout
,结果是 undefined
因为这些函数没有 return 任何东西。
bind
return 是一个新函数,您可以将其正确传递给 setTimeout
。要获得调用和应用以类似的行为,请将它们移动到匿名函数中:
setTimeout(function(){
this.say.call (this, 'call');
}, 1000);
例如。
- Afaik 这些是等效的。