addyosmani / es6-equivalents-in-es5

WIP - ES6 Equivalents In ES5

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Incorrect conversion of fat arrow function

elijahdorman opened this issue · comments

A fat arrow function binds to the local execution context differently. Execute the following in FF:

var __slice = Array.prototype.slice;

var extendWithFunc = function (fn, obj) {
  return fn.apply(obj, __slice.call(arguments, 2));
};

var myExtend = () => {
  this.newData = __slice.call(arguments, 0);
  return this;
};

var newObj = extendWithFunc(myExtend, {some: "object"}, "a", "b", "c");

Notice that if you inspect the value of 'newObj' it is Window. This is because the fat arrow does something much closer to a .bind(this) behind the scenes. Inside of 'extendWithFunc', the function application is ignored (because .bind() uses a special [[Call]] and [[BoundThis]] that cannot be overridden). Therefore, when 'myExtend' is called, the 'this' is the execution context of the global where 'myExtend' was defined (which happens to be Window).

Implementing fat arrow in ECMAScript5.1 as the following is probably closer to accurate.

[1, 2, 3].map(function(n) { return n * 2; }.bind(this));

According to the draft spec from mozilla http://people.mozilla.org/~jorendorff/es6-draft.htm

14.2.17 Runtime Semantics: Evaluation

ArrowFunction[Yield] : ArrowParameters[?Yield] => ConciseBody

  1. If the code of this ArrowFunction is contained in strict mode code or if any of the conditions in 10.2.1 apply, then let strict be true. Otherwise let strict be false.
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let parameters be CoveredFormalsList of ArrowParameters[?Yield].
  4. Let closure be FunctionCreate(Arrow, parameters, ConciseBody, scope, strict).
  5. Return closure.

NOTE Any reference to arguments, super, or this within an ArrowFunction are resolved to their bindings in the lexically enclosing function. Even though an ArrowFunction may contain references to super, the function object created in step 4 is not made into a method by performing MakeMethod. An ArrowFunction that references super is always contained within a non-ArrowFunction and the necessary state to implement super is accessible via the scope that is captured by the function object of the ArrowFunction.