Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Javascript (http://www.velocityreviews.com/forums/f68-javascript.html)
-   -   Unexpected scope question (http://www.velocityreviews.com/forums/t944431-unexpected-scope-question.html)

risingfish 02-06-2012 03:39 AM

Unexpected scope question
 
Hello, I would call myself a fairly competent JavaScript programmer,
but I ran into something expected today. Here's a snippet:

NS.MyClass = function () {

var initialize = function() {
/* do something */
NS.Instances[<uniqueId>] = this;
}

initialize();
}

var obj = new NS.MyClass();

The object that ends up in NS.Instances[<uniqueId>] is DOMWindow, not
the particular instance of that class. I can obviously fix it with
call() but I've found a hole in my knowledge and am trying to
understand. Could someone explain what is happening there?

Thanks!
R

Michael Haufe (TNO) 02-06-2012 06:30 AM

Re: Unexpected scope question
 
On Feb 5, 9:39*pm, risingfish <risingf...@gmail.com> wrote:
> Hello, I would call myself a fairly competent JavaScript programmer,
> but I ran into something expected today. Here's a snippet:
>
> NS.MyClass = function () {
>
> * * var initialize = function() {
> * * * * /* do something */
> * * * * NS.Instances[<uniqueId>] = this;
> * * }
>
> * * initialize();
>
> }
>
> var obj = new NS.MyClass();
>
> The object that ends up in NS.Instances[<uniqueId>] is DOMWindow, not
> the particular instance of that class. I can obviously fix it with
> call() but I've found a hole in my knowledge and am trying to
> understand. Could someone explain what is happening there?



The bigger question is why you've decided to write JavaScript in this
manner. Why do you have an inner function in the first place?

Scott Sauyet 02-06-2012 12:52 PM

Re: Unexpected scope question
 
On Feb 5, 10:39*pm, risingfish <risingf...@gmail.com> wrote:
> Hello, I would call myself a fairly competent JavaScript programmer,
> but I ran into something expected today. Here's a snippet:
>
> NS.MyClass = function () {
>
> * * var initialize = function() {
> * * * * /* do something */
> * * * * NS.Instances[<uniqueId>] = this;
> * * }
>
> * * initialize();
>
> }
>
> var obj = new NS.MyClass();
>
> The object that ends up in NS.Instances[<uniqueId>] is DOMWindow, not
> the particular instance of that class. I can obviously fix it with
> call() but I've found a hole in my knowledge and am trying to
> understand.


From version 5.1 of the ECMA-262 spec (June, 2011) [1]:

| 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.
| ...

So, when you call `initialize` from within your constructor function
without specifically binding `this`, the ThisBinding defaults to the
global object.

As you say, you can fix this with `call`:

| initialize.call(this);

You also might want to reconsider having the initialize function
redefined for each call to the constructor by storing it in a local
closure. Or, if it's as simple as what you've exposed here, remove
the inner function altogether, as Michael suggests.

-- Scott

[1]: http://www.ecma-international.org/pu...T/Ecma-262.pdf


All times are GMT. The time now is 04:14 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.