Why is there no implicit this in JavaScript
In JavaScript, this
must always be stated explici开发者_开发百科tly when accessing its properties. For example:
function Frobber(x) {
this.x = x;
return this;
}
Frobber.prototype.frob = function () {
// wrong:
return x * x;
// right:
return this.x * this.x;
}
I'm aware I can use with(this)
(which is deprecated and generally frowned upon), but why aren't properties of this
in scope automatically? I'm thinking there must be a reason for this design decision.
It's similar in Python. The reason is quite simple: You cannot add this, because it clashes with the default scoping rule of searching for non-local variables in the outer scopes. It's possible in statically-typed languages, because the members of the this
are known at compile-time.
And what if the made it a dynamic decision, such as "x
refers to this.x
if this.x !== undefined
and otherwise to the variable x
" (or any other rule for this that is decided at runtime)? That's very dangerous, as it can shadow local variables based on what this
happens to be, i.e. breaking perfectly valid code only for certain objects. Another issue: Should undeclaredVar = ...
add a new instance attribute? If not, that would be an ugly asymmetry between implicit and explicit this
. If it does create an instance attribute, you'd lose the ability to set global and closure variable from inside functions - not too much of a loss, many would say; but the JS designers seem to have thought otherwise, as they chose global scope as default.
Making "casual variables" shadow instance attributes would be less dangerous, but with deeply nested scopes filled with lots of names, you'd propably end up being forced to use this.
in most cases - so less of a net win. For this, and/or propably for other reasons, the designers deemed a shortcut infeasible.
You have to explicitly specify "this" because "window" is implicit instead
Code
function SomeFunc(x) {
y = x;
return this;
}
Is the same as
function SomeFunc(x) {
window.y = x;
return this;
}
What "this" refers to in Javascript is wholly a function of how the current function has been called.
If it is called as a method (i.e. with the . operator) then 'this' will be set to the object before the dot.
If it is called as a simple function, then 'this' will be the global object (usually the window).
IIRC if you use Function.call, you can set it explicitly.
Javascript is an OO language but does not have classes, and does not (strictly) have methods.
Each function object introduces a new namespace and populates it with its parameters, variables and inner function declarations. If all the properties of the this
object were to be injected into this same namespace, the names would collide.
To prevent this collision, you would have to explicitly make sure that each parameter name, local variable name or function declaration name is not the same as any of the properties of the object that is referenced by this
.
Since you can dynamically add new properties to an object, you would also have to make sure that any new property that you add, does not collide with all those parameters, variables,... in each of the objects methods.
This would be nearly impossible to deal with.
If x
is implied to be this.x
, how would you access variables defined as the name x
?
function Frobber(x) { this.x = x; }
Frobber.prototype.frob = function() {
var x = 'WHAT ABOUT ME';
return x;
}
From JavaScript: The Good Parts (Functions -- Invocation):
There are four patterns of invocation in JavaScript: the method invocation pattern, the function invocation pattern, the constructor invocation pattern, and the apply invocation pattern.
Basically, each of these "patterns" determine how the this
reference is defined. If a function is defined as a method of an object, this
will refer to the parent object. If the function is not a property of an object, this
refers to the global object. If the function is invoked with the new
keyword (i.e. as a constructor) then this
refers to the newly created object. And finally, if you use the function's apply() method the reference of this
is bound to whatever object you specify.
精彩评论