Krumia Krumia - 4 months ago 10
Javascript Question

Default binding of `this` is different from Chrome browser and Node.js

I was reading Chapter 2:

All Makes Sense Now! from You Don't Know JS, and decided to do this experiment.

I have this simple enough script
foo.js
:

var a = 'foo';
var output;

// lets find a way to output strings in both
// Chrome and Node.js
if (typeof alert === 'undefined') {
output = console.log;
} else {
output = alert;
}

function getA() {
return this.a;
}

var foo = getA();
output(foo);


I am expecting following things when
getA()
is called:


  1. Since the call site of
    getA
    is in global scope,
    getA()
    will be bound to global object.

  2. Since
    var a
    is declared in global scope, I take it that global object will have a property named
    a
    , and this property is same as the variable
    a
    .

  3. Because of that, I expect
    this.a
    to refer to variable
    a
    .

  4. Thus I expect
    output(foo)
    to print the string
    foo
    .



However, when run in Node.js (non-strict mode), this is the output:

$ node foo.js
undefined


Then I included the same script in a simple HTML page, and loaded it in chrome.

<html>
<head>
<script src="foo.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>


Chrome
alert
s the string
foo
, just as expected.

Why does the output of Chrome differ from Node.js?

Answer

Since the call site of getA is in global scope, getA() will be bound to global object.

no, that's not true for node - your script is wrapped into a function here so your example is actually this code:

(function (exports, require, module, __filename, __dirname) {
  var a = 'foo';
  var output;

  // lets find a way to output strings in both
  // Chrome and Node.js
  if (typeof alert === 'undefined') {
    output = console.log;
  } else {
    output = alert;
  }

  function getA() {
    return this.a;
  }

  var foo = getA();
  output(foo);
})(exports, require, module, 'file.js', '/dir/name');
Comments