サイトアイコン 上尾市のWEBプログラマーによるブログ

「JavaScriptの理解を深めた人がさらにもう一歩先に進むための本」の感想・備忘録1

kindle本「JavaScriptの理解を深めた人がさらにもう一歩先に進むための本」のまとめ。

点数

85点

感想

前作の「何となくJavaScriptを書いていた人が一歩先に進むための本」に引き続き良書だった。
「thisの振る舞いが関数とメソッドで異なる」は勉強になった。 Object.assign()は使えそう。
「イテレータ」も勉強になったが、IEやchromeでは動作しないメソッドを使っていたのが残念。他にもいろいろ勉強になったが、実際に使うことは少ないかもしれない。

主な内容

Strictモード

StrictモードはECMAScript5(2009年12月)で追加された機能である。

Strictモード:thisの振る舞いが変わる

callメソッドなどでthisが渡された場合の挙動が異なる。

function nostrict() {
    console.log(typeof this);
}
function strict() {
    'use strict';
    console.log(typeof this);
}
nostrict.call('foo'); // object
strict.call('foo'); // string

Strictモード:thisの振る舞いが変わる(その2)

非Strictモードではnull, undeinedを渡すと、thisはなぜかGlobalオブジェクトとして扱われる。

function nostrict() {
    console.log(this === null);
}
function strict() {
    'use strict';
    console.log(this === null);
}
nostrict.call(null); // false
strict.call(null); // true

Strictモード:argumentsの独立

非Strictモードではargumentsと引数がお互いに影響し合う。
例えば、最初の引数の値を変更すればarguments[0]にも反映され、その逆も同じである。
ただし、引数の値がオブジェクトの場合は参照渡しとなるため、argumentsにも同じオブジェクトへの参照が格納される。

function nostrict(val) {
    val = 1;
    console.log(val);
    console.log(arguments[0]);
}
function strict(val) {
    'use strict';
    val = 1;
    console.log(val);
    console.log(arguments[0]);
}
nostrict(0); // 1 1
strict(0); // 1 0

関数から呼び出した時のthis

関数から呼び出した時のthisはGlobalオブジェクトを指す。
多くの場合、JavaScriptはブラウザで動作するので、windowオブジェクトを指すことになる。

function checkThis() {
    console.log(this);
    this.val = 100; // Globalオブジェクトへのメンバ追加
}
checkThis(); // Window
console.log(val); // 100

関数から呼び出した時のthis(その2)

次の例のようになると混乱しやすいが、関数かメソッドかを意識すれば簡単である。
checkThisはメソッドなのでthisはオブジェクト自身、innerCheckThisは関数なのでthisはGlobal、をそれぞれ参照します。

var obj = {
    val: 'hoge',
    checkThis: function() {
        console.log(this.val);
        this.val = 'fuga';
        function innerCheckThis() {
            console.log(this.val);
        }
        innerCheckThis();
    }
    
};
obj.checkThis(); // hoge undefined
console.log(obj.val); // fuga

※上記の例のinnerCheckThis関数内でvalを参照したい場合は、checkThisメソッド内でvar self =this;のようにthisを退避してあげる。

アロー関数から呼び出した時のthis

ES6で追加されたアロー関数の場合は、定義された場所のthisを常に参照するようになる。
これを使えばthisの退避をしなくてもすむが、まだ広く認知されていないため使わない方が無難。

var obj = {
    val: 'hoge',
    checkThis: function() {
        var innerCheckThis1= function() {
            console.log(this.val);
        };
        var innerCheckThis2= () => {
            console.log(this.val);
        };
        innerCheckThis1(); // undefined
        innerCheckThis2(); // hoge
    }    
};
obj.checkThis(); 

ES6で追加されたObjectのクラスメソッド

  1. Object.is(val1, val2)
    同一かどうか。
    ===との違いは、NaN === NaNはfalseだがObject.is(NaN, NaN)はtrue
  2. Object.assign(target, ...src)
    Objectの複製・マージ。
    var copyObj = Object.assign({}, obj); // コピー
    var mergeObj = Object.assign(obj1, obj2); // コピー

ES6で追加されたNumberのクラスメソッド

ES6で追加されたArrayのクラスメソッド

ES6で追加されたSymbol

イテレータとは

イテレータとはオブジェクトの中身を列挙するためのオブジェクトで、以下の2つの条件を満たしている必要がある。

自前でイテラブルなオブジェクトを定義することは、ほとんどないはず。
ES6より配列がイテレータを持つようになったので、それを利用(for..of文)することはあるかもしれない。

イテレータの使い方

イテレータを持つオブジェクトは、[Symbol.iterator]()メソッドを実行するとイテレータを返却する。
※本文ではvalues, keys, entriesの各メソッドを使用していたが、IEで動作しないため非推奨になっていた
※valuesメソッドに関してはchromeでも動作しない

var arr = [1, 2];
var itr = arr[Symbol.iterator]();
console.log(itr.next().value); // 1
console.log(itr.next().value); // 2
console.log(itr.next().value); // undefined

※ただし、普通はこんな使い方をすることはなく、for…of文を使うことがほとんどである

モバイルバージョンを終了