new演算子を使わない

JavaScript The Good Partsでnew演算子は使わないほうがいいよと書かれてるものの、具体的な方法明示されてないので、少々調べてみた。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new より引用。

When the code new foo(...) is executed, the following things happen:

  1. A new object is created, inheriting from foo.prototype.

  2. The constructor function foo is called with the specified arguments and this bound to the newly created object. new foo is equivalent to new foo(), i.e. if no argument list is specified, foo is called without arguments.

  3. The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead.

ざっくり言うと、

  1. 新しいオブジェクトを作成し、コンストラクタ関数(foo)のプロトタイプ(foo.prototype)を継承
  2. コンストラクタ関数(foo)が呼び出され、thisは新しく作成されたオブジェクトにbindされる
  3. コンストラクタ関数からの戻り値がnew演算子の結果となる。明示的にreturnしてなければ、1で作成されたオブジェクトになる。

以上を踏まえて....

function Dog(name) {
  this.name = name;
}
Dog.prototype.say = function() {
  console.log(this.name);
};

new Dog('pochi').say();

これと同等なことをnewを使わずにやるなら、

function Dog(name) {
  var dog = Object.create(Dog.prototype);
  dog.name = name;
  return dog;
}
Dog.prototype.say = function() {
  console.log(this.name);
};

Dog('pochi').say();

でよい(と思う)。JavaScriptの理解がまだ浅いのでイマイチ自信ないんだが。。。

ついでに...

少々古いが、Douglas Crockford による Prototypal Inheritance の解説。 http://javascript.crockford.com/prototypal.html

    function object(o) {
        function F() {}
        F.prototype = o;
        return new F();
    }
    var newObj = object(oldObj);

oldObjをプロトタイプ継承したnewObjをつくれる、という話。 もちろん、F.prototype.methodFoo とすれば、newObj でも methodFooは継承される。