「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる②

4章まで読んだ。知らない文法だけメモ。

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる① - チョキチョキかにさん

symbol

symbolは常に一意な値を返す。enum的に使う。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol

const A = Symbol();
const B = Symbol();
A === A // true
A === B // false

Array

リテラルで初期化できる配列はArrayオブジェクト。

let array = new Array(1,2,3);

forEach

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

let array = [1,2,3];
array.forEach(function(value, index, array){
        console.log(index + ":" + value)
});

このfunctionキーワードはなんなのだろう。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions_and_function_scope

なるほど関数式。

要するに関数オブジェクトが生成されてforEachで一個ずつキックしてる感じか。Lambda式のあれみたいな感じか。

map

let array1 = [1,2,3];
let array2 = array1.map(function(value){
    return value + 1;
});
console.log(array2); // [2,3,4]

returnの値で新しい配列ができる。

some

let array = [1,2,3];
let result = array.some(function(value){
  return value === 4;
});

console.log(result)

result = array.some(function(value){
  return value === 3;
});

console.log(result)

どれかマッチしたかどうかの判定って感じ。

filter

コールバックでtrueが返った要素だけの配列を返す。

sort

let array = ["aa", "a", "aaa"];
let value = array.sort(function(x,y){
  return x.length - y.length;
})

console.log(value);

文字列でソート。

Map

  • オブジェクトと違って文字列以外をキーにできる。
  • 初期化時は要素が空。
  • Mapのキーの場合のみNaN===NaNがtrue。

キーを参照型にする場合、参照が同じじゃないとMapから値を引けない。(要するに===の結果がどうなるか。) Equals的なものはないのかな。

Set

まあなんかSetって感じ。

正規表現

let val = "1234-5678-9999";
let result = val.match(/[0-9]+/g);
console.log(result);

for(let i = 0; i < result.length; i++){
  console.log(result[i]);
}

resultにはマッチした文字列は配列で格納される。この場合gスイッチがついてるので複数マッチしてる。

マッチしてるかどうか?はRegexp.testで確認できる。

console.log(/[0-9]+/.test("abc")); // false
console.log(/[0-9]+/.test("123")); // true

マッチしてるとは?が混乱するがString.matchの結果が1件以上あるかと同義だと思えばしっくりきそう。

置換はString.replaceでできる。後方参照も使える。

Object

Objectは全てのオブジェクトの基底オブジェクト。 ここでいうオブジェクトをクラスと言っても間違いではないのだろうか。

assign

let a = {a:1, b:1};
let b = {c:2};
console.log(Object.assign({}, a, b)); // {a: 1, b: 1, c: 2}

assignの第一引数に以降のオブジェクトがマージされる。戻り値も同様の値。破壊的。

Imutable

let obj = {a:1, b:2};
Object.preventExtensions(obj); // プロパティ追加不可
Object.seal(obj); // プロパティ削除不可
Object.freeze(obj); // プロパティ変更不可

ただしstrictモードでのみ有効。

関数

関数はデフォルトでundefinedを返す。returnがあればその値を返す。

アロー関数

関数リテラルをすっきり表現できるやつという理解でいいのだろうか。

let func = (a,b) => a+b;
let val = func(1, 2);
console.log(val); // 3

関数を複数行書きたければ中括弧でくくって戻り値はreturnで返す。

function命令

function命令はコンパイル時に解析されてるので、宣言より前に呼び出せる。リテラルで初期化して値に格納する場合はあくまで値なので、その値が初期化される前に呼び出すことできない。

スコープ

変数の巻き上げ

let value = "global";
function f(){
  console.log(value); // ここでundefinedでエラー
  let value = "local";
  console.log(value);
}
f();

f関数内でのvalueの定義がなければエラーにならない。ローカル変数そのものは関数全体で有効だが、最初の出力ではまだ初期化されていないため。

ブロックスコープ

letで宣言された変数はブロックスコープになる。

let a = 1;
{    
  console.log(a);
  let a = 2;
}

巻き上げのルールは同様なのでこの場合はエラーになる。

仮引数の数

引数の数をチェックしない。足りない分はundefinedになる。

function test(a,b,c){
  console.log(a);
  console.log(b);
  console.log(c);
}

test(1); // 1, undefined, undefined

逆に仮引数がなくても引数を受け取れる。arguments経由で参照する。

引数のデフォルト

function test(a = 1){
  console.log(a);
}

test(); // 1
test(2); // 2

デフォルトは明示的に値が渡されたなかったか、undefinedが渡された場合にのみ適用される。

デフォルトがある値は後ろに宣言しないと、呼び出しが変な感じになる。(明示的にundefinedを渡してデフォルトを表現する感じになる)

// TODO オプションが複数ある場合はどうすればいいいんだろう。

必須の引数を表現

デフォルト値に例外がスローされる関数を指定しとくと必須を表現できる。めんどくさい気がしなくもない。

可変長引数

function test(...nums){
  console.log(nums);
  for(let val in nums){
    console.log(val);
  }
}
test(1,2,3);

numsは[1,2,3]になる。

function test(a, ...nums){
  console.log(nums);
  for(let val in nums){
    console.log(val);
  }
}
test(1,2,3);

この場合a=1,num=[2,3]になる。

...演算子

function test(a,b,c,d) {
  console.log(a);
  console.log(b);
  console.log(c);
  console.log(d);
}

test([1,2,3,4]); // aに配列が格納され、bcdはundefined。
test(...[1,2,3,4]); // abcdそれぞれに1,2,3,4が代入

名前付き引数

function test({a = 1, b = 2}){
  console.log(a);
  console.log(b);
}

test({a:3, b:4});

デフォルトはなくても良い。どっちかっていうとオブジェクトを渡された時それぞれのプロパティに分解する機能という理解で良さそう。

クロージャ

関数オブジェクトが参照している変数が、関数の参照が残っていると変数も確保されたままになることを利用した仕組み?

function test(arg){
    let val = arg;
    return () => ++val;
}

let a1 = test(1);
console.log(a1()); // a1の関数は参照が残る 2
console.log(a1()); // a1のスコープにあるvalも保持される 3
console.log(a1()); // なので関数が呼ばれるたびにvalのが値が増える 4

用途がわかってない。

http://d.hatena.ne.jp/artgear/20120115/1326635158

なるほど? パフォーマンスがシビアじゃない場合使わないやつくらいの認識でいいんだろか?