JavaScript開発者へ

# この記事を書くことになった動機
Quoraより…
[JavaScriptの開発者がよくする間違いは何ですか？](https://jp.quora.com/JavaScriptの開発者がよくする間違いは何ですか/)
という質問に回答させていただいた際の答えに準じたソースコードが必要であると気がついたためです。

## コンストラクタを継承する時。
（Javaでいう、クラスの継承）
初心者の方は素直にクラス構文を使うことをおすすめします。

~~~javascript
class Foo {
  constructor (foo) {
    this.foo = foo;
  }
  sayFoo () {
    alert(this.foo);
    return this;
  }
}

class Bar extends Foo{
  constructor (foo, bar) {
    super(foo);
    this.bar = bar;
  }
  sayBar () {
    alert(this.bar);
    return this;
  }
}

const bar = new Bar("hello", "bye");
bar.sayFoo(); //hello
~~~

上記を詳細に設定したものにしたい場合は、

~~~javascript
function Foo (foo) {
  this.foo = foo;
}
Object.assign(Foo.prototype, {
  sayFoo () {
    alert(this.foo);
    return this;
  }
});

function Bar (foo, bar) {
  Foo.call(this, foo);
  this.bar = bar;
}
Bar.prototype = Object.create(Foo.prototype, {
  constructor: {
    configurable: true,
    writable: true,
    value: Bar
  }
});

Object.assign(Bar.prototype, {
  sayBar () {
    alert(this.bar);
    return this;
  }
});

const bar = new Bar("hello", "bye");
bar.sayFoo(); //hello
~~~

## eventHandlerの中でのthisがeventTargetを指すことを忘れている。

これは初歩的な失敗ですが、実際には以下のような解決策があります。

~~~javascript
const MyButtonHandler = function (value) {
  this.value = value;
  this.click = this.value !== undefined ? this.what : this.that;
}

Object.assign(MyButtonHandler.prototype, {
  handleEvent (e) {
    this[e.type](e);
  },
  what (e) {
    this.value = e.target.innerText;
  },
  that (e) {
    alert(this.value);
  }
});

const myButtonHandler = new MyButtonHandler("I am not eventTarget");
document.getElementById("myButton")
.addEventListener("click", myButtonHandler, false);
~~~
_handleEvent_ という名前のメソッドを継承することで、_this_ は _eventTarget_ ではなく、そのメソッドを持つオブジェクトになります。
_addEventListener_ の追加時は関数名ではなくオブジェクトをまるごと追加します。

## イベントの補足先がクロージャになっていて、メモリーをリークしてしまう。
上記の様に実装していれば、その危険性は格段に下がるので割愛させていただきます。

## jQueryこそjavascriptだと思っている。
残念なことですが本気で思い込んでいる方は多いです。
jQueryを使わずに、生のjavascriptを使って見ることで、本当はこう書けるという実感が必要だと感じます。
ただし、現在は _CSS Selector_ によるクエリ検索が、生のjavascriptでも出来ます。
詳細は、以下をご参照ください。
[querySelector](https://developer.mozilla.org/ja/docs/Web/API/Document/querySelector)
[querySelectorAll](https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll)
## lodashが無いと動くコードが書けない。
いや、あの頃は良かったですね！
確かに便利な関数群を実装したとてつもなく強力なライブラリで、後のjavascriptへの発想を大きく転換していただけたライブラリです。
今、その精神は生のjavascriptに脈々と受け継がれています。
[Array.prototype](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype)
[分割代入](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)については、以下のような使い方もできます。

~~~javascript
Object.entries({a: 1, b: 2, c: 3}).forEach(([k, v]) => console.log(`{${k}: ${v}}`));

(({a, b, c}) => ({a, c}))({a: 1, b: 2, c: 3});
//{a: 1, c: 3}
~~~

スプレッドオペレータという書き方もあります。

~~~javascript
// argumentsを配列化したり、配列を展開代入したりに　ピリオド３つを使う。
((...v) => v.reduce((p, c) => p + c))(...[2, 3, 4])
~~~

## 関数は第１級オブジェクトだと言われても、その意味を理解できていない。
関数は、Functionをコンストラクタに取るオブジェクトなので、プロパティを追加できます。
その関数に関連のある名前の関数を定義する際には便利かもしれません。

~~~javascript
  const Foo = Object.assign(function (foo) {
    this.foo = foo
  }, {
    of (foo) {
      return new Foo(foo);
    }
  });

  Object.assign(Foo.prototype, {
    of(foo) {
      return Foo.of.call(this, foo);
    },
    sayFoo () {
      alert(this.foo);
      return this;
    }
  });

const foo = Foo.of("hello");
foo.sayFoo(); // hello
const foo2 = foo.of("Bye");
foo2.sayFoo(); // Bye
~~~

## オブジェクト指向にこだわりすぎて、柔軟にコードを書けない。
アラン・ケイ氏によると、
『「さらに良く」や「完璧」は、「必要なこと」に対する敵です』
と言明されました。

[Quora：プログラミング言語のデザインについて](https://jp.quora.com/%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AA%E3%82%89-%E5%AE%8C%E7%92%A7%E3%81%AA%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E%E3%82%92%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB)

つまり我々は美しいコードを書くために必要なことだけに着目すればよいということになります。

## 関数型の人々は、javascriptのオブジェクト指向的な側面の利点を言わない。
場合もあるという冗談にとどめておきたい回答です。
オブジェクト指向を圏論的に俯瞰できない方々は、オブジェクト指向を叩きがちです。
これも上記のアラン・ケイと同じ意見です。

## 非同期処理で関数を入れ子にし続けて、あとで何書いたか分からなくなる。
Promiseを使うほうが良いです。
出来ればそれに対応したものに書き換えたほうが良いですが、UIEvent系を非同期処理に対応しようとした際、酷い目に会いました（笑）
async awaitで記述できる場合はそれも視野にいれると良いでしょう。

~~~javascript
(async () => {
  return await fetch //...
})()
.then(ans => JSON.parse(ans))
.then(data => Object.assign(foo, data));
~~~

## コピーしたはずの元のオブジェクトのプロパティまで変更されている。
これについては、こういう事故が起こります。

~~~javascript
const foo = {bar: 3};
const foobar = foo;
foobar.bar = 5;
console.log(foo.bar === 3) // Ouch!
~~~

正しいオブジェクトのコピー方法は、以下で説明します。

## オブジェクトをコピーしたら、継承しているメソッドは消えると思い込む。

オブジェクトの正確なコピーは、以下のソースコードで得られます。

~~~javascript
const Foo = function (foo) {
  this.foo = foo
};

Object.assign(Foo.prototype, {
  sayFoo () {
    alert(this.foo);
    return this;
  }
});

let foo = new Foo("hello")

let copiedFoo = Object.assign(Object.create(Foo.prototype), foo);
copiedFoo.foo = "bye";

foo.sayFoo(); // hello
copiedFoo.sayFoo(); // bye
~~~

以上になりますが、言いたいことは…


### Object.assignは超便利！

失礼いたしました…