Edited at

JavaScript再入門

More than 1 year has passed since last update.


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

違いはないよう。

シングルを採用することの方が多い。


関数?メソッド?

オブジェクトのプロパティはメソッド。

そうでないものは関数。

のよう。

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());