可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Hi I have following JavaScript code that I am trying to run. My aim is to grasp the meaning of this
in different scopes and different types of invocations in JavaScript.
If you look in code below: I have a inner anonymous function, which is getting assigned to innerStuff
variable. In that anonymous function as such this
points to window
object and not the outer function object or anything else. Event though it still has access to out function's variables.
Anyway, I am not sure, why that would be; but if you look at code below, I pass this
in form of that
to innerStuff
later and it works just fine and prints object with doofus
attribute in console.
var someStuff = {
doofus:"whatever",
newF: function()
{
var that = this;
console.log(that);
var innerStuff = function(topThis){
console.log(topThis);
};
return innerStuff(that);
}
}
someStuff.newF();
Now I am changing a code only little bit. And instead of assigning it to innerStuff
, I'll just directly return the function by invoking it as shown below:
var someStuff = {
doofus:"whatever",
newF: function()
{
var that = this;
console.log(that);
return function(that){
console.log(that);
}();
}
}
someStuff.newF();
This prints undefined for the inner anonymous function. Is it because there is a clash between a that
that is being passed as parameter and a that
defined in outside function?
I thought the parameter would have overriden the visibility. Why would the value be not retained?
This is utterly confusing.
On the other hand if I don't pass that
, but instead just use it, because visibility is there, the outcome is proper and as expected.
What is it that I am missing? Is it the clash between the variables, present in same scope?
Is there a good reason, that inner functions have this
bound to window
object?
回答1:
this
in JavaScript refers to the object that you called a method on. If you invoke a function as someObject.functionName(args)
, then this
will be bound to that object. If you simply invoke a bare function, as in functionName(args)
, then this
will be bound to the window
object.
Inside of newF
in the second example, you are shadowing the that
variable in your inner function, but not passing anything into it, so it is undefined.
var that = this;
console.log(that);
return function(that){
console.log(that);
}();
You probably want the following instead, if you want something that is equivalent to your first example (passing that
in to the inner function):
var that = this;
console.log(that);
return function(that){
console.log(that);
}(that);
Or the following, if you don't want to shadow it and just use the outer function's binding:
var that = this;
console.log(that);
return function(){
console.log(that);
}();
回答2:
In your second example, when you invoke the anonymous function, the parameter that
is not defined (you aren't passing anything to it.) You can do this:
newF: function()
{
var that = this;
console.log(that);
return function(that){
console.log(that);
}(that); // note that we are passing our 'that' in as 'that'
}
That will keep the proper value of the variable around.
However, since you are scoping var that
above, you could just remove the function parameter as well:
newF: function()
{
var that = this;
console.log(that);
return function(){
console.log(that);
}(); // 'that' is referenced above.
}
As far as why anonymous functions have window
as their this
: whenever you call a function without a context (i.e. somef()
vs context.somef()
) this
will point to the window
object.
You can override that and pass a this
using .apply(context, argumentsArray)
or .call(context, arg1, arg2, arg3)
on a function. An example:
newF: function()
{
console.log('Outer:', this);
var innerF = function(){
console.log('Inner:', this);
};
return innerF.apply(this,arguments);
}
回答3:
In your first code example, the anonymous function, though declared within a function that is a member of the someStuff
object, is not a member of the someStuff
object. For that reason, this
in that function is a reference to the window object. If you wanted to invoke the anonymous function and have control over the this
reference, you could do the following:
var someStuff = {
doofus:"whatever",
newF: function()
{
var that = this;
console.log(that);
var innerStuff = function(){
console.log(this);
};
return innerStuff.apply(this);
}
}
someStuff.newF();
In your second example, your actually creating an anonymous function, executing it, and then returning the value that the anonymous function returned. However, your anonymous function did not return anything. Additionally, you have a variable name conflict. You could do:
var someStuff = {
doofus:"whatever",
newF: function()
{
var that = this;
console.log(that);
return function(){
console.log(that);
return true;
}();
}
}
someStuff.newF();
I added the return true because your function should return something, since the function that is executing it is returning the return value of the anonymous function. Whether it returns true or false or a string or an object or whatever else depends on the scenario.