What is 'this' before an object is created in js?

I do not understand the following:

var x = function() { this.foo="foo"; return function() { this.bar = "bar"; return foo+bar; }; }(); // returns inner alert(x()); // 'foobar', so both 'this' variables are set alert(x.bar); // undefined - but wasn't it used correctly? alert(new x().bar); // ok, works 

My assumption was that when creating and using the default 'this' scope / variable-map is generated and used for the first time, and then when the 'new' is called, a new object (function?) With a new 'this' is sent through and returned . Or maybe x is not a proper object? But then, how does 'this' end up being installed and used to create a foobar?

What do I need to know to understand this?

+4
source share
4 answers

First, let's look at some of the intricacies of JavaScript, and then we'll look at your example.

function context

One point of misunderstanding is context. Each function is called in a context accessible with the this keyword. Let's write a function that we can use to check contexts:

 var probe = function(){ // if the context doesn't have a name, let name it if(!this.name){ this.name = "lumberjack"; } // print the name of my context console.log(this.name); }; 

Here we go:

 name = "global!"; // when we call a function normally it still have a context: // the global context probe(); // prints: global! var ctx = {name: "ctx"}; // we can set a context explicitly using call() probe.call(ctx); // prints: ctx // we can set a context explicitly using apply() probe.apply(ctx); // prints: ctx // it is set implicitly, if we call a function as a member ctx.fun = probe; ctx.fun(); // prints: ctx // or we can create a brand new object and set it as a context: // that what "new" does var t = new probe(); // prints: lumberjack // let sum it up: console.log(name); // prints: global! console.log(ctx.name); // prints: ctx console.log(t.name); // prints: lumberjack 

This is why it is so easy to spoil and inadvertently fall into a global context.

Return value in constructor

Many people are confused when they see a constructor that returns a value. It is legal. A constructor can return an object, function, or array. This value will be used as an instance. The old instance will be discarded.

 var myClass = function(){ // if it is called as a constructor, "this" will be a new instance // let fill it up: this.a = 42; this.b = "Ford"; this.c = function(){ return "Perfect"; }; // done? let discard it completely! // and now for something completely different... return { owner: "Monty Python", establishment: "Flying Circus" }; }; var t = new myClass(); alert(t.owner + " " + t.establishment); 

As expected, it features Monty Python's Flying Circus.

If the constructor returns something else (for example, a number, a string, zero, undefined), the return result will be discarded, and the old instance will be used.

Example

Your example is hard to understand, mainly because of how it was written. Let it simplify by rewriting.

First, let's look at x :

 var x = function() { this.foo = "foo"; return function() { this.bar = "bar"; return foo + bar; }; }(); // returns inner 

As we can see, an anonymous function (1 st function ) is executed immediately, so we can embed it:

 // next assignment can be simplified because // top "this" is window or the global scope //this.foo = "foo"; => foo = "foo"; x = function() { this.bar = "bar"; // this line depends on its context, or "this" return foo + bar; // this line uses global "foo" and "bar" }; 

So, at the end, we have two global variables: foo (string) and x (function).

Now open the warning 1 st :

 alert(x()); // 'foobar', so both 'this' variables are set 

Again, let the string x() :

 // next assignment can be simplified because // top "this" is window or the global scope //this.bar = "bar"; => bar = "bar"; // at this moment both global "foo" and "bar" are set alert(foo + bar); // => "foo" + "bar" => "foobar" 

Warning 2 nd is equally simple:

 alert(x.bar); // undefined - but wasn't it used correctly? 

No need to rewrite a lot. x is a function, we did not add any properties to it, therefore x.bar is undefined. If you add it, you will see the results:

 x.bar = "bar2"; alert(x.bar); // bar2 

Warning 3 rd demonstrates the effect of OOP JavaScript:

 alert(new x().bar); // ok, works 

(Note: it only works because you first ran x() , otherwise it explodes because bar is undefined).

Rewrite it like this:

 var t = new x(); alert(t.bar); // bar 

Now let's analyze the constructor. It has two statements: assignment and return. The latter is ignored because it returns a string. Therefore, we can rewrite it like this:

 x = function(){ this.bar = "bar"; }; var t = new x(); alert(t.bar); // bar 

I hope everything looks simple now.

+9
source

That the main one complains about the new operator ...

This statement creates a new object that inherits from the prototype of the operand constructor function, and then calls the function, assigning a new this object.

If you forget to use the new operator when calling the constructor function, you will get a regular function call instead, and this bound to the global object ( window ) instead of the new object.

Your function will add global variables whenever it uses this , trying to initialize its own instance.

In your example, the global object ends with two new variables:

 window.foo window.bar 

Because of this, some people prefer prototype inheritance instead of a pseudo-classical approach.

+4
source

To answer the question that you ask in your title: this will refer to the global object.

Keep in mind that this does not work in JavaScript, such as in languages ​​such as Java or C ++; it is used solely for context and will not necessarily refer to the same object every time this function is called. From the MDC documentation :

There are four ways to convey this
[...]
If none of the above methods is used, the global object is passed as a context object, for example, when this happens at the top level outside any constructor or when a function is called without calling as an object method, since in func(arg1, arg2) .

For the answers to the rest of your question, see Only when I think I finally understand the realm of Javascript ...

+3
source

As Shog9 said, this is not the same as in normal mode, as in Java, etc.

AFAIK Javascript uses dynamic scaling, as Common LISP / eLisp does, rather than a lexical region like Scheme / Lisp -1.

+3
source

All Articles