0

Why the following happens?

function f1() {
    this.myRefVar = 30;
    this.myRefVar2 = 30;
    var parent = this;

    return function() {
        this.myRefVar = 20;
        console.log('parent contains ' + Object.keys(parent).filter(function(k) {
            return k.indexOf('myRefVar') > -1;
        }));
        console.log('parent value of myRefVar: ' + parent.myRefVar);
        console.log('this value of myRefVar: ' + this.myRefVar);
    };
}

f1()();

Output:

parent contains myRefVar,myRefVar2
parent value of myRefVar: 20
this value of myRefVar: 20
Muhammad Hewedy
  • 26,344
  • 42
  • 116
  • 201
  • 1
    Just add `"use strict";` to `f1` and see what happens. –  Jul 30 '16 at 18:10
  • I think I understand now, using `this` inside a function (not a `constructor` now object `method`) is the same as defining a variable without using `var`, which is a bad thing, because this makes the variable refer to the global scope, not the function local scope. – Muhammad Hewedy Jul 30 '16 at 23:08

2 Answers2

2

Because there is actually no scoping here. All of this accesses refer to the window object. Hence, when you are editing this.myRefVar at the inner scope, you are actually editting the value at the window.

var theName = "SO";
var myObject = function(){
    this.theName = "SO2";
    this.foo = function() {
        this.theName = "SO3";
    }
}

Here, I defined some variables, and functions. The variable theName, first declared at root(window) scope, then inside myObject scope (There is no scope like this, just for the explanation, and then inside foo scope.)

console.log(theName); // SO
console.log(this.theName); // SO
console.log(window.theName); // SO
console.log(myObject.theName); // undefined
console.log(myObject.foo); // undefined
console.log(this.foo); // undefined
console.log(window.foo); // undefined

And here, I am trying to access theName variable via different ways. If there is actually scopping here 4th one should work after function call. The others just representing same idea, but different way.

myObject();

console.log(theName); // SO2
console.log(this.theName); // SO2
console.log(window.theName); // SO2
console.log(myObject.theName); // undefined
console.log(myObject.foo); // undefined
console.log(this.foo); // function myObject/this.foo()
console.log(window.foo); // function myObject/this.foo()

After function call, I still can't access myObject.theName as I hoped. That's because, calling it this way myObject.theName does not actually accessing myObject scope, rather than I am trying to access theName property of myObject function. And, without actually defining/instantiating/creating this function as an object, I cannot access the properties.

myObject.theName;// undefined. Accessing myObject as a function
new myObject().theName // SO2. Accessing an object derived from myObject.

What's going on in your code is actually not scopping but closure. For better understanding:
Scopping
Closures
Similar SO question

Community
  • 1
  • 1
Ramazan Kürkan
  • 136
  • 1
  • 10
1

In JavaScript function have global scope For example

function parent() {
  var self_parent = this;
  function firstChild() {
    var self_first_child = this;
    function childOfChild() {
        var self_child_of_child = this;
    }
  }
}

in the above code following will be true

self_parent === self_first_child === self_child_of_child

for more Info see JavaScript-Garden-About-this

suraj.tripathi
  • 337
  • 1
  • 14