Make Local Happiness

自分の幸せは自分で作る!!!

はじめての読書会で「開眼!Javascript」を読んだ

f:id:iwate_takayu:20180202001455j:plain

最近会社のメンバーと読書会をはじめました。 週に1回カフェで30分で1章から3章ほど読み進め、残りの30分で呼んだ部分で意見を言い合うというのをやっています。

これが意外と面白いです。

今回読んだ「開眼!JavaScript」はJavaScriptの言語仕様について解説してくれている本のため、 私にとっては少し退屈で最後まで読めるか心配になる本だったのですが、
時間が決まっていること、意見を言い合うことで楽しく進めることができ、合計5回で読み終えることができました。

呼んだ中で気づいた点について書いていきます。

作者はCodyさんと気づく

本書にはCodyオブジェクトやクラスが多様されるので、嫌でもCodyさんが著者と気づきます。

第1章 JavaScriptオブジェクト

コンストラクター関数という呼び方を知らなかった

デフォルトのプロパティとメソッドを持ったオブジェクトを生成するためのクッキーの抜き型のようなものです。

※ 以下のコードは本書とは異なり、ES6に対応させた形で記載しています。 アロー関数ではコンストラクタとして使用はできないため、functionを使用しています。

const Person = function(living, age, gender){
  this.living = living;
  this.age = age;
  this.gender = gender;
  this.getGender = () => { return this.gender; };
};

const cody = new Person(true, 33, 'male');
console.log(typeof cody);
console.log(cody);
console.log(cody.constructor);

null, undefined, 'string', 0, true, falseはオブジェクトではなくプリミティブ型

プリミティブ型は値そのものが保存される。 オブジェクトの場合は、参照が渡されるため参照元が変更されると参照先も変更される。 よく、オブジェクトを更新する場合に、変数を引き継いた場合に、 値が参照渡しになっている場合があるので注意です。

オブジェクの変更ではObject.assignで新しくオブジェクトを作成、 配列の場合はmapで新しい配列を作成すると安心です。

// プリミティブ型の場合

let myString = 'foo';
let myStringCopy = myString;
myString = null;

console.log(myString, myStringCopy); // 出力:'null "foo"'

// オブジェクトの場合

let myArray = [0];
let myArrayCopy = myArray;
myArray.push(1);

console.log(myArray, myArrayCopy); // 出力:'[0,1] [0,1]'

第2章 オブジェクトとプロパティを扱う

ブラケット記法

※ブラケット記法というのを初めて知りました。

const cody = new Object();
cody.living = true; // ドット記法
cody["living"] = false; // ブラケット記法

delete演算子でグローバルオブジェクトが削除できるわけ

delete演算子はプロパティを削除することができる。 そのため、varやconst、letで宣言した変数は削除できないが、 宣言せずに定義した変数はグローバル(this)のプロパティとなるため、deleteで削除できる。

const a = 1;
b = 1;

delete a; // 削除されない
delete b; // 削除される

第7章 スコープとクロージャ

classではクロージャーが実装できない? functionでクロージャーは作成できるのですが、 classを使ってクロージャー(内部に隠蔽する変数を保持する実装)を作成する方法はなさそうです。 ※ もし実現できる方法あれば教えてください

function版

const Foo = function() {
  let count = 0;
  
  this.add = () => {
    count++;
  }
  this.get = () => {
    return count;
  }
}

const a = new Foo();
const b = new Foo();

a.add();
a.add();
a.get(); // 2
a.count; // undefined

b.get(); // 0

class版

① functionと同じように書く  ⇒ 定義できない。そもそもエラーになります。

class Foo {
  let count = 0;

  get() {
    return count;
  }
  add() {
    count++;
  }
}

コンストラクター内でcountを定義する  ⇒ addやgetのメソッドからcountが参照できない

class Foo {
  constructor() {
    let count = 0;
  }
  
  get() {
    return count;
  }

  add() {
    count++;
  }
}

const a = Foo();
a.get() //エラーになる

コンストラクターのメンバー変数にcountを入れる  ⇒ privateな変数ではなくなる  

class Foo {
  constructor() {
    this.count = 0;
  }
  
  get() {
    return this.count;
  }

  add() {
    this.count++;
  }
}

const a = Foo();
a.add()
a.get() // 1
a.count // 1

まとめ

普段の業務では気づいているんだけど、 わりとなんでそうなっているのかわからないような処理が明文化されているので頭の整理になりました。

最近は綺麗にコードが書けるように意識していたので、ちょうどいいタイミングで読めてよかったです。読んでいて沢山の気付き与えてくれ、議論も活発になり後半は30分以上かかるときもありました。

読書会だからこそ読めた本だと思うので、 これからもちょっととっつきづらそうな本は読書会のテーマで乗り切ろうと思います。