2015年11月17日火曜日

アロー関数はコンストラクタとして使えない

util.inheritsでアロー関数を渡すとエラーになるので調査していたところ、アロー関数はコンストラクタとして使えないことが分かった。
原因はアロー関数のprototypeがundefinedになるため。

再現コード

'use strict';
var util = require('util');
var EventEmitter = require('events');

function InputDialog() { }

console.log('InputDialog prototype: ' + InputDialog.prototype)
util.inherits(InputDialog, EventEmitter);

const InputDialog2 = () => { }

console.log('InputDialog2 prototype: ' + InputDialog2.prototype)
util.inherits(InputDialog2, EventEmitter);

出力

InputDialog prototype: [object Object]
InputDialog2 prototype: undefined
util.js:764
  Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
         ^

TypeError: Object.setPrototypeOf called on null or undefined
    at Function.setPrototypeOf (native)
    at Object.exports.inherits (util.js:764:10)
    at Object.<anonymous> (/Users/shinichi/code/silkedit/test.js:13:6)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:457:10)
    at startup (node.js:136:18)
    at node.js:972:3

util.inheritsのコード
https://github.com/nodejs/node/blob/v5.1.0/lib/util.js

exports.inherits = function(ctor, superCtor) {

  if (ctor === undefined || ctor === null)
    throw new TypeError('The constructor to `inherits` must not be ' +
                        'null or undefined.');

  if (superCtor === undefined || superCtor === null)
    throw new TypeError('The super constructor to `inherits` must not ' +
                        'be null or undefined.');

  if (superCtor.prototype === undefined)
    throw new TypeError('The super constructor to `inherits` must ' +
                        'have a prototype.');

  ctor.super_ = superCtor;
  Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
};

参考

Arrow functions versus normal functions
An arrow function is different from a normal function in only three ways: First, it always has a bound this. Second, it can’t be used as a constructor: There is no internal method [[Construct]] (that allows a normal function to be invoked via new) and no property prototype. Therefore, new (() => {}) throws an error. Third, as arrow functions are an ECMAScript.next-only construct, they can rely on new-style argument handling (parameter default values, rest parameters, etc.) and don’t support the special variable arguments. Nor do they have to, because the new mechanisms can do everything that arguments can.

Node.jsのバージョン間での挙動の違い

ちなみにv0.12.0はアロー関数をコンストラクタとしてutil.inheritsに渡しても動作する。
v5.1.0ではダメ。

0 件のコメント:

コメントを投稿