javascript let

jsのES6でブロックスコープが利用可能になった。
ブロックスコープの変数を宣言するにはvarではなくletを使用する。
letは、同じスコープ内の変数の重複を認めない。

if(true) {
  let test = 'test';
  //let test = 'テスト';//重複エラー
  console.log(test);//test
}

console.log(test);//ブロックスコープエラー

javascript prototype_chain

jsで継承を行う仕組みとしてプロタイプチェーンがある。

var Car = function() {};

Car.prototype = {
  getOwner : function() {
    console.log('Owner is', this.owner);
  }
};

var SmallCar = function(owner) {
  this.owner = owner;
};

// 継承したいオブジェクトのインスタンスを
// 自身のprototypeプロパティに格納する
SmallCar.prototype = new Car();

SmallCar.prototype.start = function() {
  console.log('start');
}

var myCar = new SmallCar('yamada');
myCar.getOwner();
myCar.start();

var otherCar = new SmallCar('suzuki');
otherCar.getOwner();
otherCar.start();


なお、jsはES5よりObject.createを使用しても継承できる。

javascript prototype

jsにはクラスが無く、プロトタイプを使って
オブジェクト指向のような実装を行う。なお、
ECMAScript6ではクラスの概念が用意されている。

// コンストラクタ
var Beef = function(name, type) {
  this.name = name;
  this.type = type;
};

// prototypeプロパティメソッド
// Beef.prototype.getName = function() {
//   return this.name;
// };

// Beef.prototype.getType = function() {
//   return this.type;
// };

// prototypeプロパティメソッド
// オブジェクトリテラル使用版
Beef.prototype = {
  getName : function() {
    return this.name;
  },
  getType : function() {
    return this.type;
  }
}

var kobeBeef = new Beef('kobeBeef', 'momo');
var oumiBeef = new Beef('oumiBeef', 'harami');

console.log(kobeBeef.getName() + ':' + kobeBeef.getType());
console.log(oumiBeef.getName() + ':' + oumiBeef.getType());

コンストラクタ内にメソッドを定義せず、
プロパティを使ってメソッドを定義する理由は、
メモリ使用量の削減のため。

インスタンス化したオブジェクトは、
コンストラクタで定義されているメンバ分の
メモリ領域を都度確保してしまう。

メソッドはインスタンスを通して全て
同じ振舞いをするため、個別にメモリを
確保するのは無駄になる。

prototypeプロパティでメソッドを管理することで、
同一メモリへの参照が可能になる。

メソッドは必ずprototypeプロパティで管理すること。

javascript closure

jsのクロ―ジャとは
「ローカル変数を参照している、
関数の中に定義している関数」

function countNum(num) {
  var local_num = num;
  var local_func = function() {
    return local_num++;
  }
  return local_func;
}

var myCountNum = countNum(10);
console.log(myCountNum());//10
console.log(myCountNum());//11
console.log(myCountNum());//12

クロージャの実体は関数の中のローカル関数。
通常、関数の中で定義されるローカル変数は、
関数の処理が終わるとその時点で破棄される。
ただ上記のように、myCountNumがlocal_numを参照し続けている場合、
local_numは、myCountNumが有効な限り破棄されない。

javascript primitive

jsのプリミティブ型

・真偽値 boolean
・文字列 string
・null値 null
・未定義値 undefined

プリミティブ型は、通常は値そのものだが、
一時的にオブジェクトになるケースがある。
なお、nullとundefinedは常にプリミティブ型。

var num1 = 100;
var num2 = new Number(200);

console.log(typeof num1);//number
console.log(typeof num2);//object

console.log(num1);//100
console.log(num2);//Number {[[PrimitiveValue]]: 200}

console.log(num1.toString());//100
console.log(num2.toString());//200

javascript new

newは「オブジェクトのインスタンスを返却せよ」と、
コンストラクタに命令する演算子

new使用時と不使用時の比較

var hello = function(name) {
  this.name = name;
  this.say = function() {
    return 'hello! ' + this.name; 
  }
}

var hello1 = new hello('太郎');//new使用
var hello2 = hello('太郎');//new不使用

//new使用
console.log(hello1);//hello {name: "太郎"}
console.log(hello1.say());//hello! 太郎

//new不使用
console.log(hello2);//undefined
console.log(hello2.say());//エラー

helloに代入する無名関数にはreturnが記述されていない。
jsの関数は、returnが明記されていないと、undefinedが返る。
しかし、newを用いると、returnが無くても、
自動的にオブジェクトのインスタンスが返る。