Ben Bacarisse
6/7/2015 6:58:00 PM
Steven D'Aprano <steve@pearwood.info> writes:
> I thought I understood what "this" means inside a function. I thought that
> when you called a function, "this" was the local scope, which is an
> object.
> That's why you can use a function as an object constructor:
>
> js> function Person1(name, age){
> > this.name = name;
> > this.age = age;
> > }
> js> fred = new Person1("Freddy", 23);
> [object Object]
> js> print(fred.name, fred.age);
> Freddy 23
No, it's the 'new' part that makes this work. Without it, what "this"
means depends on strict mode.
The expression new F(...args...) calls the [[Contruct]] internal method
on F and that method is defined to bind this to an empty object. The
[[Construct]] method goes on to call the [[Call]] internal method so the
main difference between new F(...args...) and F(...args...) is this
special binding for that.
(This is not the correct terminology because 'this' is not a name has no
bindings, but it simpler to put it this way.)
> Constructors are just functions, except they implicitly return "this",
> right?
Not really. Constructors are just functions and they can return
whatever they like, and when called without new, they return that value.
It's the new expression that returns the new object, probably modified
by the function that was called. The value the function returns is
ignored in a new expression.
> So at this point I thought I'd be clever:
>
> js> function Person2(name, age){
> > this.name = name;
> > this.age = age;
> > return this;
> > }
> js> george = new Person2("George", 42);
> [object Object]
> js> george.name;
> George
The 'return this' is harmless in this case because the function's return
value is ignored.
> And that seems to work. But if I do this:
>
> js> henry = Person2("Henry", 87);
> [object global]
> js> name;
> Henry
> js> age;
> 87
> js> henry === this;
> true
>
> the function seems to be operating on the global scope.
Without the 'new' you get whatever the function returns. In old JS, and
in non-strict mode, that will be the global object (not scope).
> Obviously my reasoning is invalid. Can somebody explain what is happening
> here? What is the role of this inside a function, and how does it sometimes
> refer to the object being constructed and sometimes to the global
> scope?
It's all down to using new F(...) rather than F(...).
> The above examples are using Rhino.
Rhino is a little old. In strict mode with a newer implementation
(e.g. nodejs) your last example gives an error because 'this' will refer
to the undefined value (rather than the global object) during the call
to Person2.
--
Ben.