JavaScript
es6

JavaScript再入門

クォーテーションはシングル?ダブル?

違いはないよう。
シングルを採用することの方が多い。

関数?メソッド?

オブジェクトのプロパティはメソッド。
そうでないものは関数。
のよう。

obj.hoge();  // (オブジェクトの)メソッド
hoge();  // 関数

セミコロンがあったりなかったりする

なくても動く。
が、絶対つけた方がいい。

書き方によっては、誤訳する可能性あり?

文字列の結合は

様々な言語を触っていると、つい忘れがちなのでメモ。

「+」 でつなげるのが一番いい。
参考:文字列の結合方法による速度差

スコープについて

ブロックスコープはない

var i = 1;
for (i = 0; i<4; i++) {
}

console.log(i); // 4

ただし、下記のletで実現が可能。

関数スコープ

関数の中で定義された変数は、その中でしか参照できない。

ただし関数がネストしている場合、
子の関数は親の関数の変数を参照できる。

var、let、const

varとletはスコープの違い。
varは関数スコープ、letはブロックスコープ。

理由がない限り、letを使っていく方が良い。

constは名前の通り、定数。ブロックスコープ。
ただし、オブジェクトのkeyは保護されないので、全くの不変ではない。

const HOGE = { key: 1 };
HOGE.key = 2;  // これはできてしまう

レキシカル?

評価のたびに変わるものではなく、定義時に決まるもの。
静的なものと言えるかもしれない。

グローバルオブジェクト

JavaScriptのコードはオブジェクトに格納されていなければならない。

ので、
何かコードを書けば、実はそれはグローバルオブジェクトに格納された扱いになる。

ブラウザならそれは「window」だし、
node.jsの場合は「global」になる。

strictモード

いくつかの機能を制限することで、厳密なコードが書ける。
どんどん使った方がいい。

スクリプト単位、関数単位で書けるが、
スクリプト単位だと連結等で弊害があるかもしれないので、「関数単位」が良い。

function hoge() {
  'use strict';  // 必ず最初に
  ...
}

strictモードは

・エラーではないが、落とし穴になるようなコードはエラーに
・最適化が困難なものを修正
・将来的なキーワードなどは禁止

といったことを保証してくれる模様。

NaN、undefined、null

説明 判別方法 備考
NaN 非数
(結果の存在しない演算結果)
isNaN(NaN)
undefined 何もない状態 ES5以降:
(x === undefined)

ES5以前:
(typeof x === 'undefined')
returnしない関数はundefinedを返す
null 返すものがない (null === null)

条件文等の判定について

参考:[JavaScript] null とか undefined とか 0 とか 空文字('') とか false とかの判定について

nullやundefinedを同時に処理したいなら

if (hoge) {

のような書き方もできる。
しかし上記の場合、空文字、0、falseも条件に入らなくなるので注意。

eval

文字列をJavaScriptの式として評価する。

eval("2+2");

thisが参照するもの

thisを書いた場所 参照するもの
グローバル グローバルオブジェクト
単純な関数内(非strict) グローバルオブジェクト
単純な関数内(strict) undefined
アロー関数内 関数の外のthis
オブジェクトのメソッド内 そのオブジェクト
コンストラクタ そのオブジェクト

bind

オブジェクト内に単純な関数が記載されていた場合、
その呼び出し方によってthisの内容が異なる。

そんな場合にはbindを使ってthisを拘束できる。

困った例
var hoge = {
  fuga: function () {
    return this;
  }
};

hoge.fuga();  // オブジェクトのthisなので、thisはオブジェクト自身となりhogeになる

var myFuga1 = hoge.fuga;
myFuga1();  // myFugaはただの関数になるので、thisがグローバルオブジェクト

var myFuga2 = myFuga1.bind(hoge);// hogeをthisとして拘束
myFuga2();  // thisはhoge

引数の型や数について

JavaScriptの引数は、

・型をチェックしない
→typeof演算子を使う

・引数の数をチェックしない
→引数が足りない場合は未定義、多い場合は無視される

・関数の呼び出しに使う引数は任意の数で良い(定義を気にしなくて良い)

argumentsオブジェクト

関数はargumentsという配列のようなオブジェクトを参照できる。
動的引数などに使える。

let func = function (x) {
  console.log(x);
  console.log(arguments[0]);
  console.log(arguments[1]);
  console.log(arguments[2]);
};

func(2,3,4); // 2234

デフォルトの引数

function hoge(a, b = 1) {
  return a + b;
}

hoge(2); // 3

アロー関数

単純な関数を省略した記載方法。
thisやargumentsを拘束しないという効果もある。

() => {...}
// ↑
// 同じ
// ↓
function () {...}

もっと短縮する

・仮引数が存在する場合、引数を囲む括弧は省略できる
・処理がreturnの一文で済む場合、ブロックとreturnは省略できる
・短縮構文でオブジェクトリテラルを返す場合は、括弧で囲む必要がある

(x) => { return x; }
// ↑
// 同じ
// ↓
x => x;
var func1 = x => { key: x };
func1(1);  // undefined

var func2 = x => ({ key: x });  // これが正しい

レスト引数

アロー関数内でargumentsは使えない模様。

ので、レスト引数で対応すれば良い。

(...args) => {
  console.log(args);
}

class

クラスを定義する方法は、class文(宣言)とclass式の二つがある。
どちらもstrictモードで実行される。

class文

構文

class MyClass [extends] {
}
class MyClass extends BaseClass {
  constructor () {
        // super()は親クラスのコンストラクタ
    // コンストラクタ内でのみ使える(thisの使用前に呼ぶ必要がある)
    super();

        this.name = 'Takashi';
  }
}

静的メソッド

静的メソッドはインスタンス化しなくても呼ぶことが可能だが、インスタンス化していると呼べない。

class MyClass {
  static hoge () {
    ...
  }
}

MyClass.hoge();

クラス変数

ES6だとできないらしい。
以下のような感じでやるしかない。

class Hoge {
  constructor() {
    this.hoge = 1;
  }
}

class式

class式は
・クラス名を省略できる
・再定義、再宣言ができる
・型エラーをスローしない
・typeofはfunctionを返す

構文

var myClass = class [className] [extends] {...};
var Hoge = class {
  constructor () {}
  one () { return 1; }
};

var hoge = new Hoge();
hoge.one();
内部でクラスを参照したい場合は、クラス名をつける
var Hoge = class NamedHoge () {
  constructor () {}
  one () { return NamedHoge.name; }
}

Function

call、apply

参考:Javascriptのcall/apply関数のプロっぽい使い方 〜 JSおくのほそ道 #014

例えば、二つの配列をマージしたいけど、
Array.prototype.pushの引数に配列は渡せない。
いくつかやり方はあるけど、普通の脳内だとループは免れない。

ダメな私の脳内
let hoge = [1, 2, 3];
let fuga = [4, 5, 6];

fuga.forEach(value => { hoge.push(value); });

けどそんなの美しくない。
そんな時に↓

例:二つの配列をマージ
let hoge = [1, 2, 3];
let fuga = [4, 5, 6];

// hogeに対して、fuga配列を引数としてpushを実行するよー
Array.prototype.push.apply(hoge, fuga);

上記例は以下を実行しているイメージ。

let hoge = [1, 2, 3];

hoge.push(4, 5, 6);

配列で渡せないなら、applyの引数に配列を渡すという仕様を利用しようジャマイカ。
ということだ。

Object

もの。
プロパティを持つことで、様々な性質を持つオブジェクトとして表現できる。
連想配列として使える。

生成

var obj = new Object();

var obj = {[key1: value1, [key2: value2]...]};

関数も定義できる。

プロパティへのアクセス

var obj = new Object();

obj.hoge = 0;
obj['hoge'] = 1;

Getter、Setter

カプセル化や、追加処理を書いたりできる。

var obj = {
  hoge: '',
  get hoge() { 
    return this.hoge;
  },
  set hoge(val) {
    this.hoge = val;
  }
};

実装されていないgetter、ないしsetterにはアクセスできない(エラーが発生)

プロパティの削除

delete obj.hoge;

ループで順番にアクセス

for (val in obj) {
・・・
}
Object.keys(obj).forEach(key => {
  console.log(obj[key]);
});

コンストラクタメソッド

使いそうなものを抜粋。

メソッド 説明
Object.assign(target, ...sources) targetにsourcesをコピーした結果を返す
Object.keys(obj) プロパティのkeyを、文字列の配列で返す key配列を取得してそれでループとかよくする
Object.values(obj) プロパティの値を、配列で返す

instanceof

オブジェクトが自身のプロトタイプに、コンストラクタのprototypeオブジェクトを持っているか。

var obj = {...};

if (obj instanceof Obj) {
...
}

Array

配列のこと。

生成

var arr = [];
var num = [1, 2];

要素の取得

var num = [1, 2];

var zero = num[0]; // 1

要素数を知りたい

var len = arr.length;

ループで順番にアクセス

for

let arr = [1, 2];

for (let i= 0; i < arr.length; i++) {
...
}

for in

配列のkeyを抽出。

let arr = [1, 2];

for (let index in arr) {
  console.log(arr[index]);
}

for of

配列の値を抽出。

let arr = [1, 2];

for (let val of arr) {
  console.log(val);
}

Array.forEach

let arr = [1, 2];

arr.forEach((element, index, thisArr) => {
  // elementは処理中の要素
  // indexは処理中の要素番号(省略可)
  // thisArrは処理対象の配列自身(省略可)
});

forEachでbreakとかcontinueしたい

https://www.deep-rain.com/programming/javascript/778

〜したい 方法 備考
breakしたい arr.some使え someは、引数に指定したcallbackでtrueを返せば即座に処理終了する
continueしたい returnを書く
returnしたい 無理

メソッド

メソッド 説明 備考
arr.filter(() => {...}) callbackがtrueを返した要素のみで構成された配列を生成し、返す。
arr.find((element, index, thisArr) => {...}) callbackが真を返した要素をすぐに返す
見つからなければundefind。
arr.findIndex((element, index, thisArr) => {...}) callbackが真を返した要素のインデックスをすぐに返す
見つからなければ-1。
arr.includes(search) 特定の要素が含まれているか調べ、booleanで返す。
arr.indexOf(search) 特定の要素が含まれているか調べ、最初の要素のインデックスを返す。
見つからなければ-1。
arr.reduce((pre, element, index, thisArr) => {...}) callbackが返した結果をpreに累積する
arr.map((element, index, thisArr) => {...}) callbackで返した値を配列に詰めて、結果に返す
arr.slice(begin[, end]) インデックスbeginから、インデックスendの手前まで返す
srr.some((element, index, thisArr) => {...}) callbackで返した値がtrueなら即座にtrueを返してくれる

JSON

メソッド

メソッド 説明
JSON.parse(str) strを解析して、JSONに相当するObjectを返す
JSON.stringfy(js_value) JavaScriptの値を、JSON文字列に変換して返す

prototype

継承元のオブジェクトみたいなもの。
継承先のオブジェクトは、暗黙の参照が可能となる。

メソッドの共通化などに用いられる。

var Man = function () { this.name = ''; };

var Takashi = new Man();
Man.prototype.help = function () { alert('help!!'); };

Takashi.help(); // help!!

正規表現

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

try...catch

try {
  // throw '好きな文字列';
} catch(e) {
  // eは例外オブジェクト
} finally {
  ...
}

exportとimport

外部モジュール等から、関数、オブジェクト、プリミティブをエクスポート、インポートするために使用。

名前付きエクスポートとインポート

my-module.js
function hoge() {...};
const fuga = 1;

export {hoge, fuga};
import {hoge, fuga} from 'my-module';

console.log(hoge());
console.log(fuga);

デフォルトエクスポートとインポート

インポート時に特に指定がなければ、デフォルトエクスポートの値が呼ばれる。

my-module.js
export default function() {...};
import hoge from 'my-module';

console.log(hoge());