2

I have several Node JS modules, some use strict mode, others don't.

How does the mode change when calling from a strict-mode module into a non-strict mode module? How does the mode change during such a call?

And vice-versa, what is the logic of changing the mode when calling a method in a strict-mode module from a non-strict mode module?

What are the rules for changing strict mode in general and for NodeJS in particular? How does it work?

vitaly-t
  • 24,279
  • 15
  • 116
  • 138
  • I think u can get some part of your anwser here http://stackoverflow.com/questions/18417381/in-node-js-how-the-use-strict-statement-is-interpreted – brielga Sep 14 '15 at 11:43
  • @brielga all that is about what strict mode is, nothing about how it changes across context, which is what I'm trying to understand. – vitaly-t Sep 14 '15 at 11:52

1 Answers1

1

Code is parsed, compiled (where relevant), and executed in the mode in which it's written, regardless of what mode it's called from. The only time you can cross a boundary between the two modes is when calling a function, which raises the question, which mode is used to do the work of making that call? (Since strict mode affects several aspects of calling functions.) The answer is: The mode of the function being called. So when a loose function calls a strict one, the strict rules for function calls are used; when a strict function calls a loose one, the loose rules for function calls are used.

When you call a function, strict mode comes into play in several ways:

  1. In strict mode, the call can specify that this be a non-object value; in loose mode, any non-object is coerced to object.
  2. In strict mode, the default this for calls that don't specify it (e.g.: foo()) is undefined instead of the global object as it is in loose mode.
  3. In strict mode, the called function's arguments object has caller and callee properties that throw a TypeError when accessed; in loose mode, the spec defines arguments.callee as a reference to the called function; there's no arguments.caller in the spec, but some implementations provide a reference to the calling function on it.
  4. In fact, in strict mode code, implementation-specific extensions (like caller) to arguments are forbidden, while in loose mode they're allowed.
  5. The arguments object created by the call for use by the called function is complete disassociated from the named parameters of the function in strict mode, instead of being dynamically linked to them as in loose mode.

Here's an example of a loose function calling a strict one and vice-versa, demonstrating that it's the rules of the function called are the ones that are followed:

// Loose calling strict
const strictFunction1 = (function() {
  "use strict";
  return function(a, b) {
    console.log("=== strict function called:");
    console.log("#1 and #2", typeof this); // undefined
    console.log("#2", this === window); // false
    try {
      const x = arguments.callee;
      console.log("#3", "result of trying to access `arguments.callee`: got a " + typeof x);
    } catch (e) {
      console.log("#3", "result of trying to access `arguments.callee`: " + e.message);
    }
    // #5:
    a = 42; // Setting 'a'
    console.log("#5", a === arguments[0]); // false
  };
})();
function looseFunction1() {
  strictFunction1(67);
}
looseFunction1();

// Strict calling loose
const looseFunction2 = (function() {
  return function(a, b) {
    console.log("=== loose function called:");
    console.log("#1 and #2", typeof this); // object
    console.log("#2", this === window); // true
    try {
      const x = arguments.callee;
      console.log("#3", "result of trying to access `arguments.callee`: got a " + typeof x);
    } catch (e) {
      console.log("#3", "result of trying to access `arguments.callee`: " + e.message);
    }
    // #5:
    a = 42; // Setting 'a'
    console.log("#5", a === arguments[0]); // true
  };
})();
function strictFunction2() {
  looseFunction2(67);
}
strictFunction2();
.as-console-wrapper {
  max-height: 100% !important;
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875