1

I'm not understanding how this in the BigObject constructor can be undefined when not using the new keyword -- see examples below. Given the following code snippet in Firebug:

( function( global ){  
  "use strict";   
  var fromunderbutter = "fun"; 
  global.BigObject = function( options ){      
       console.log( this );      
       console.log( this instanceof BigObject );  
  };    
})( this );

The following code makes sense:

>>> var x = new BigObject();
>>> Object { }  // new constructor creates blank object context that is assigned to BigObject 
>>> true  // BigObject was the object context ( this ) that invoked BigObject()

From what i understand, this refers to the current object context. In the above example because of the new keyword, this will refer to a blank object which will be newly created and applied to the function invocation.

But this next part doesn't make sense to me:

>>> BigObject()
>>> undefined  
>>> false

Why is this undefined? I assumed that this would refer to something -- probably global object window. Not sure how to think about this result.

Thanks

maztaz
  • 133
  • 3
  • Some references: [Understanding Javascript scope with “var that = this”](http://stackoverflow.com/a/12371105/710446) and [In Javascript, why is the “this” operator inconsistent?](http://stackoverflow.com/a/80478/710446) – apsillers May 29 '13 at 19:47

4 Answers4

4

In strict mode when a function is called without a context, this is undefined.

10.4.3 Entering Function Code # Ⓣ

The following steps are performed when control enters the execution context for function code contained in function object F, a caller provided thisArg, and a caller provided argumentsList:

  1. If the function code is strict code, set the ThisBinding to thisArg.
  2. Else if thisArg is null or undefined, set the ThisBinding to the global object.
  3. Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).
  4. Else set the ThisBinding to thisArg.
  5. Let localEnv be the result of calling NewDeclarativeEnvironment passing the value of the [[Scope]] internal property of F as the argument.
  6. Set the LexicalEnvironment to localEnv.
  7. Set the VariableEnvironment to localEnv.
  8. Let code be the value of F’s [[Code]] internal property.
  9. Perform Declaration Binding Instantiation using the function code code and argumentList as described in 10.5.

The code provided is strict code, and the thisArg for the call is undefined (no context was provided for the call).

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • Ok, so removing strict mode now produces `Window about:newtab`. I guess i don't understand what it means to **call a function without a context**. For example, using the above `strict` keyword isn't this providing context? >>> var Caller = function() { BigObject() }; >>> Caller(); undefined false – maztaz May 29 '13 at 19:44
  • There is always an implicit context. On browsers it is the `window` object. See @apsillers comment above for more details. – Lucas May 29 '13 at 19:46
  • 1
    @maztaz The easiest case to think about is object methods: doing `obj.myMethod()` calls `myMethod` with `this` set to `obj`. Calling just `myFunction()` calls `myFunction` with `this` set to the global object or to `undefined` in strict mode (as you do in your question). – apsillers May 29 '13 at 19:55
  • @maztaz, calling `myFunction.call(context)` explicitly specifies a context for the function. `myfunction()` doesn't specify any context. – zzzzBov May 29 '13 at 20:16
0

this cannot be defined without an event of an element.

Ramesh
  • 163
  • 1
  • 2
  • 11
0

Because that's what the language spec says it should do.

Sounds like a flip answer, but it isn't. Strictly speaking, it's arbitrary: You can write a compiler to do just about anything, but most of what it could imaginably do would be a bad idea. There's usually a good reason for these things.

In this case, the reason would be that the same function would do radically different things when called with and without new. That would never be a good idea. You might be able to come up with a bizarre case where it does something useful, but there would always be a more readable and maintainable way to do the same thing.

Language features are the opposite of laws: You don't add them just because it takes more than three seconds to think of any reason offhand why they'll always be utterly intolerable to absolutely everybody. You only add them if and when you have a compelling, very well-considered, thoroughly-researched and tested reason to believe they'll be very useful very often to a lot of people, and almost never destructive. Or if you're designing Visual Basic or tcl, of course.

0

If you want to fix this, use:

(function(global){  
  "use strict";   
  var fromunderbutter = "fun"; 
  global.BigObject = function (options) {
    if (!(this instanceof BigObject)) return new BigObject(options);     
    console.log(this);      
    console.log(this instanceof BigObject);  
  };    
})(this);

As zzzzBov mentioned, you would need to bind this to mimic BigObject being this in order to use your current code. That requires doing: BigObject.bind(new BigObject())({ /* options */ }). That's obviously not the ideal way to be calling your code.

Sly
  • 1,145
  • 7
  • 19