当你传递'this'作为参数时 [英] When you pass 'this' as an argument
问题描述
我正在尝试了解这个
,这让我有点困惑:
var randomFunction = function(callback){
var data = 10;
回调(数据);
};
var obj = {
initialData:20,
sumData:function(data){
var sum = this.initialData + data;
console.log(sum);
},
prepareRandomFunction:function(){
randomFunction(this.sumData.bind(this));
}
};
obj.prepareRandomFunction();
此
旨在将自己设置在哪里首先在代码中呈现?例如,在我的示例中,我成功地使用它来引用 obj
并将函数绑定到 obj
,但是因为这个
被作为回调函数传递,所以阻止它被设置为 randomFunction
(即什么停止它从字面上传递this.sumData.bind(this),以便此
设置为 randomFunction
从那里打来电话)?
我是一个努力学习的菜鸟。谢谢。
已更新
我并不是一般都会问这是如何工作的(我不认为)。我很想知道为什么这个
被设置为我将其定义为我的 randomFunction
调用的参数,并且而不是在 randomFunction
中调用回调
的地方。我可能是错的,但如果我要用回调(数据)交换
我目前认为我会得到不同的结果。是因为 this.sumData.bind(this)
callback
是对 this.sumData.bind(this)
的引用,它是在第一次定义时(以及此
是 obj
)?
我想我已经通过这个场景了解到这个
在执行时设置了。当参数被调用时,它不会作为参数传递。
函数调用中的这个
根据函数的调用方式设置。 这个
设置有六种主要方式。
-
普通函数调用:在正常函数调用中,例如
foo()
,此
设置为全局对象(在浏览器中为窗口
)或未定义
(在Javascript的严格模式下)。 -
方法调用:如果调用方法,例如
obj.foo()
,然后此
在函数内设置为obj
。 -
.apply()或.call():如果
.apply()
或.call使用()
,然后根据传递给
.apply()$ c $的内容设置此
c>或.call()
。例如,您可以执行foo.call(myObj)
并将此
设置为myObj
在该特定函数调用的foo()
内。 -
使用new:如果您使用
new
调用函数,例如new foo()
,然后创建一个新对象,并使用调用构造函数
设置为新创建的对象。 / p>foo
,将此 -
使用.bind():使用
.bind()
a时从该调用返回新的存根函数,该调用在内部使用.apply()
来设置传递给的
指针.bind()
。仅供参考,因为.bind()
可以用.apply()
实现。 -
使用ES6 Fat Arrow函数通过ES6 +中的箭头语法定义函数将绑定<$ c $的当前词汇值c>这个。因此,无论在其他地方如何调用该函数,解释器都会将
此
值设置为此值
具有定义函数的时间。这与所有其他函数调用完全不同。
有一种第七种方法,通过回调函数,但它实际上不是它自己的方案,而是调用回调的函数使用上述方案之一并确定的值
将在调用回调时。您必须查阅文档或调用函数的代码,或自行测试以确定在回调中将设置为$ c> c>。
在Javascript中要理解的重要一点是,Javascript中的每个函数或方法调用都为设置了一个新的值
。并且,设置的值取决于函数的调用方式。
因此,如果将方法作为普通回调传递,默认情况下,该方法不会被称为 obj.method()
,因此不会为此设置这个
的正确值。您可以使用 .bind()
来解决该问题。
了解一些回调函数也很有用(例如DOM事件处理程序)使用特定值调用此
来调用,这是由调用回调函数的基础结构设置的。在内部,它们都使用 .call()
或 .apply()
所以这不是新规则,但是是值得注意的。回调函数的契约可能包括它如何设置这个
的值。如果它没有明确设置这个
的值,那么它将根据规则#1设置。
在ES6中,通过箭头函数调用函数,维护当前词汇值 this
。这是一个数组函数的例子,从 this 参考/功能/ Arrow_functions#Lexical_thisrel =noreferrer> MDN :
function Person(){
this.age = 0;
setInterval(()=> {
this.age ++; // | this |正确引用person对象
},1000);
}
var p = new Person();
obj的例子.prepareRandomFunction();
是上面的规则#2所以这个
将被设置为 obj
。
你的 randomFunction(this.sumData.bind(this))
的例子是上面的规则#1所以
将设置为全局对象或中的
randomFunction undefined
(如果是严格模式)。
由于randomFunction正在调用一个回调函数,该函数本身使用 .bind()
,那么<$ c的值回调函数内的$ c> this 在被调用时将被设置为传递给的
在这个
的值.bind() this.sumData.bind(this)
中,通过上面的规则#5。 .bind()
实际上创建了一个新功能,它的工作是调用原始功能AFTER设置自定义值 this
。
以下是关于该主题的其他几个参考文献:
注意,使用 .apply()
或 .call()
或 .bind()
,你可以创建各种各样的有些奇怪的事情,有时是非常有用的事情,在C ++这样的事情上永远无法做到。您可以使用世界上的任何函数或方法,并将其称为某种其他对象的方法。
例如,这通常用于将 arguments
对象中的项目副本复制到数组中:
var args = Array.prototype.slice.call(arguments,0);
或类似情况:
var args = [] .slice.call(arguments,0);
这需要数组的 .slice()
方法并调用它,但为它提供一个arguments对象作为 this
指针。 参数
对象(虽然不是实际数组),具有足够的类似于数组的功能, .slice()
方法可以对它进行操作,最终将 arguments
项的副本复制到一个实际的数组中,然后可以直接使用实数组操作进行操作。这种类型的chicanery不能无所事事地完成。如果数组 .slice()
方法依赖于 arguments
对象上不存在的其他数组方法,那么这个技巧不起作用,但因为它只依赖于 []
和 .length
,两者都是 arguments
对象有,它确实有用。
所以,这个技巧可以用来从任何对象借用方法和只要您应用它们的对象支持该方法实际使用的任何方法或属性,就将它们应用于另一个对象。这不能在C ++中完成,因为方法和属性在编译时是硬绑定的(即使C ++中的虚方法绑定到在编译时建立的特定v表位置),但可以在Javascript中轻松完成,因为属性并且方法在运行时通过它们的实际名称进行实时查找,因此任何包含正确属性和方法的对象都可以使用任何操作这些属性和方法的方法。
I'm trying to learn about this
, and it's confusing me a bit here:
var randomFunction = function(callback) {
var data = 10;
callback(data);
};
var obj = {
initialData: 20,
sumData: function(data) {
var sum = this.initialData + data;
console.log(sum);
},
prepareRandomFunction: function() {
randomFunction(this.sumData.bind(this));
}
};
obj.prepareRandomFunction();
Is this
designed to set itself where it is first rendered in code? For instance, in my example I'm successfully using it to refer to obj
and also binding the function to obj
, but since this
is being passed as a callback function, what is stopping it from being set as randomFunction
(i.e. what's stopping it from literally passing "this.sumData.bind(this)" so that this
is set to randomFunction
when it gets called from there)?
I'm a noob trying to learn. Thanks.
Updated
I'm not exactly asking how this works generally (I don't think). I'm mainly curious to know why this
gets set where I define it as the argument of my randomFunction
call, and not where callback
gets called within randomFunction
. I could be wrong, but if I were to swap this.sumData.bind(this)
with the callback(data)
that I currently have I think I would get a different result. Is that because callback
is a reference to this.sumData.bind(this)
when it was first defined (and where this
is obj
)?
I think I've learned through this scenario that this
is set when it's executed. It's not passed as a argument to be set later when the argument is called down the line.
this
inside a function call gets set according to how a function is called. There are six main ways that this
gets set.
Normal Function Call: In a normal function call such as
foo()
,this
is set to either the global object (which iswindow
in a browser) or toundefined
(in Javascript's strict mode).Method Call: If a method is called such as
obj.foo()
, thenthis
is set toobj
inside the function..apply() or .call(): If
.apply()
or.call()
is used, thenthis
is set according to what is passed to.apply()
or.call()
. For example, you could dofoo.call(myObj)
and causethis
to be set tomyObj
inside offoo()
for that particular function call.Using new: If you call a function with
new
such asnew foo()
, then a new object is created and the constructor functionfoo
is called withthis
set to the newly created object.Using .bind(): When using
.bind()
a new stub function is returned from that call that internally uses.apply()
to set thethis
pointer as was passed to.bind()
. FYI, this isn't really a different case because.bind()
can be implemented with.apply()
.Using ES6 Fat Arrow Function Defining a function via the arrow syntax in ES6+ will bind the current lexical value of
this
to it. So, no matter how the function is called elsewhere, thethis
value will be set by the interpreter to the value thatthis
has when the function was defined. This is completely different than all other function calls.
There's sort of a seventh method, via a callback function, but it isn't really its own scheme, but rather the function calling the callback uses one of the above schemes and that determines what the value of this
will be when the callback is called. You have to consult either the documentation or the code for the calling function or test it yourself to determine what this
will be set to in a callback.
What is important to understand in Javascript is that every single function or method call in Javascript sets a new value for this
. And, which value is set is determined by how the function is called.
So, if you pass a method as a plain callback, that method will not, by default, get called as obj.method()
and thus will not have the right value of this
set for it. You can use .bind()
to work around that issue.
It's also useful to know that some callback functions (such as DOM event handlers) are called with a specific value of this
as set by the infrastructure that calls the callback function. Internally, they all use .call()
or .apply()
so this isn't a new rule, but is something to be aware of. The "contract" for a callback function may include how it sets the value of this
. If it does not explicitly set the value of this
, then it will be set according to rule #1.
In ES6, calling a function via an arrow function, maintains the current lexical value of this
. Here's an example of the array function maintaining the lexical this
from MDN:
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();
Your example of obj.prepareRandomFunction();
is rule #2 above so this
will be set to obj
.
Your example of randomFunction(this.sumData.bind(this))
is rule #1 above so this
inside of randomFunction
will be set to the global object or undefined
(if in strict mode).
Since randomFunction is calling a callback function which itself used .bind()
, then the value of this
inside the callback function when it is called will be set to the value of this
that was passed to .bind()
in this.sumData.bind(this)
as via rule #5 above. .bind()
actually creates a new function who's job it is to call the original function AFTER setting a custom value of this
.
Here are a couple other references on the topic:
How to avoid "this" refering to the DOM element, and refer to the object
A better understanding of this
How does the "this" keyword work?
Note, that with the use of .apply()
or .call()
or .bind()
, you can create all sorts of somewhat odd things and sometimes quite useful things that could never be done in something like C++. You can take any function or method in the world and call it as if it were a method of some other object.
For example, this is often used to make a copy of the items in the arguments
object into an array:
var args = Array.prototype.slice.call(arguments, 0);
or similarly:
var args = [].slice.call(arguments, 0);
This takes the array's .slice()
method and calls it, but supplies it with an arguments object as the this
pointer. The arguments
object (though not an actual array), has just enough array-like functionality that the .slice()
method can operate on it and it ends up making a copy of the arguments
items into an actual array which can then be operated on directly with real array operations. This type of chicanery can't be done willy-nilly. If the array .slice()
method relied on other array methods that are not present on the arguments
object, then this trick would not work, but since it only relies on []
and .length
, both of which the arguments
object has, it does actually work.
So, this trick can be used to "borrow" methods from any object and apply them to another object as long as the object you are applying them to supports whatever methods or properties that the method actually uses. This can't be done in C++ because methods and properties are "hard bound" at compile time (even virtual methods in C++ are bound to a specific v-table location established at compile time), but can be easily done in Javascript because properties and methods are looked up live at runtime via their actual name so any object that contains the right properties and methods will work with any method that operates on those.
这篇关于当你传递'this'作为参数时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!