概要
今までNode.jsやReactNativeに触れて、自分のJSの知識がいかに乏しいかというのを、しっかり理解することが出来ました。
今年度の目標として、フロントエンドの知識を身につけるというのがあるので、これを機会にしっかり基本から勉強し直して、自分のJSの知識の底上げをしていきたいと思います。
参考にした本
色々とJS関連の本を漁ったところまさに良さそうな内容の本が何冊かありましたので、それらを見ながら、復習をしていきたいと思います。
今回は以下の本を見ながら、脱初心者を目指そうと思います。
脱初心者のJavaScript力を底上げするための本
参考になったところ
argumentsオブジェクト
関数に渡された引数全てを管理しているオブジェクト
配列に似た構造を持ってるけど別物。
function test(aaa, bbb, ccc) { for (var p of arguments) { console.log(p); } } test('ドラえもん', 'のび太くん', 'しずかちゃん', 'ジャイアン', 'スネ夫'); // ドラえもん のび太くん しずかちゃん ジャイアン スネ夫と表示される test('ドラえもん', 'のび太くん'); // ドラえもん のび太くんと表示される test(); // 何も表示されない
定義している引数の数に見合わない呼び出しをしても問題ないということは知っていましたが、このオブジェクトの存在は知りませんでした。 でもそんな使わなそうな気がします。 引数ちゃんと合わせろよって話ですし。。。
変数の巻き上げ
関数内のどの位置にでもvar文を使用して変数を宣言できるが、関数内のどの位置に変数の宣言をしても、 その関数の先頭で宣言された
と見なされる。
以下は本から引用させていただいたコードです。
var a = 'hoge'; var f = function() { console.log(a); // undefined var a = 'fuga'; console.log(a); // fuga }
実際にはf ファンクション内の、2行目で a変数に fugaという文字を入れたが、結果的にはファンクション内の1行目(先頭)で a変数を定義したことになってしまうということです。
しかも、宣言だけで、初期化は行われません。
なので、 undefined になっているということになります。
つまり fファンクション内は以下みたいなります。
var f = function() { var a; console.log(a); a = 'fuga'; console.log(a); }
これはまじで知りませんでした。 まぁ引数で渡しちゃったり、基本的に宣言・初期化は先にしちゃうので気づいてなかったというのもありますが。。 勉強になりました。
即時関数
無名関数を定義し、そのまま ()
をつけて実行することが出来る。無名関数は、function定義から全体を()
で囲む必要がある。
自分が慣れていないだけなのですが、使ったことがありませんでした。
結構使う技術なんでしょうか??
(function(test) { console.log(test); })('パリピ'); // パリピ
apply, call, bind
関数内で参照するthisを束縛するためのメソッド。 thisは呼び出される場面によって自身の参照先が変化するが、これらのメソッドを使うと常に指定した通りのthisで動作させることが出来る。
なお、bindに関しては、関数に渡す引数も束縛することが出来る。
これらは、jsのthisの勉強をしていたときに、なんとなく理解したのですが、実際にきちんと理解するために、今回もう一度勉強しようと思いました。
apply
applyの特徴は、引数をまとめて配列で渡すことのようです。
function profile(age) { console.log(this.name + "です。" + age + "才です。"); } var user1 = { name: "ドラえもん" }; var user2 = { name: "のび太" }; profile.apply(user1, [20]); // ドラえもんです。20才です。 profile.apply(user2, [10]); // のび太です。10才です。
call
callの特徴は、引数をそのままで渡すことが出来るようです。
function profile(age) { console.log(this.name + "です。" + age + "才です。"); } var user1 = { name: "ドラえもん" }; var user2 = { name: "のび太" }; profile.call(user1, 20); // ドラえもんです。20才です。 profile.call(user2, 10); // のび太です。10才です。
bind
bindはほか2つと少し違っていて、引数も同時に束縛できることが出来ます。
userProfile3のように、引数を束縛しないことももちろん可能です。
function profile(age) { console.log(this.name + "です。" + age + "才です。"); } var userProfile1 = profile.bind({ name: "ドラえもん"}, 20); var userProfile2 = profile.bind({ name: "のび太"}, 10); var userProfile3 = profile.bind({ name: "ジャイアン"}); userProfile1(); // ドラえもんです。20才です。 userProfile2(); // のび太です。10才です。 userProfile3(15); // ジャイアンです。15才です。
一度まとめるとスッキリわかりました。勉強になりました。
Map
ES2015からサポートされた map
は従来のオブジェクトで書くよりいろいろメリットがあるとのことでした。特に以下です。
- キーを任意の型で指定できる
- 専用のメソッドが用意されている
専用のメソッドに関しては、名前でだいたい想像できますが、一応書いてみます。
メソッド名 | 詳細 |
---|---|
set(key, val) | mapにデータをセットする |
delete(key) | 指定のkeyのデータをmapから削除する |
size | mapの要素数を返す(こちらはメソッドではない) |
has(key) | 指定のkeyのデータがmap内にあるかどうかを確認する |
get(key) | 指定のkeyのデータをmapから取得する |
keys() | map内に存在するすべてのkeyを返す |
values() | map内に存在するすべてのvalueを返す |
entries() | mapの全てのkey, valueのペアを返す |
それぞれ、サンプル書いてみました。
var testMap = new Map([ ['name', 'ドラえもん'], ['age', 20], [12345, 'ppppp'] ]); console.log(testMap.set('isError', true)); // => Map(4) {"name" => "ドラえもん", "age" => 20, 12345 => "ppppp", "isError" => true} console.log(testMap.delete('isError')); // => true console.log(testMap.size); // => 3 console.log(testMap.has(12345)); // => true console.log(testMap.get(12345)); // => ppppp console.log(testMap.keys()); // => MapIterator {"name", "age", 12345} console.log(testMap.values()); // => MapIterator {"ドラえもん", 20, "ppppp"} console.log(testMap.entries()); // => MapIterator {"name" => "ドラえもん", "age" => 20, 12345 => "ppppp"}
ES2015に関しては、また別途勉強するつもりなので、簡単に書きましたが、こういうのもあるのですね。勉強になりました。
クラス
こちらもES2015でサポートされたもののようです。
class Animal { constructor(name) { this.name = name; } getName() { return this.name; } } var animal = new Animal('ねこ'); console.log(animal.getName()); // => ねこ class Cats extends Animal { constructor(name, nickname) { super(name); this.nickname = nickname; } getNickName() { return this.nickname; } // オーバーライド getName() { return super.getName() + "(名前: " + this. getNickName() + ")"; } } var cats = new Cats('ねこ', 'こじろう'); console.log(cats.getName()); // => ねこ(名前: こじろう)
classはphpで触り慣れているので、比較的すんなり入れました。
アクセス修飾子がないというところが少し気になりますが、無理やり作ることは出来るみたいなので、クラスは積極的に使っていきたいと思います。
勉強になりました!!
Promise
これもES2015でサポートされた機能のようです。
以下のようなコールバック地獄を回避するための デザインパターン
ということです。
request1(function(response1) { request2(function(response2) { request3(function(response3) { request4(function(response4) { request5(function(response5) { // まだまだ続く可能性あり・・・ }); }); }); }); });
↑のようなコードをPromiseを使って書くと以下のようにきれいに書けるようです。
request1() .then(function(response1) { return request2(); }).then(function(response2) { return request3(); }).then(function(response3) { return request4(); }).then(function(response4) { return request5(); }).then(function(response5) { // 処理はつづく・・・ });
シンプルでわかりやすいです!勉強になりました。
Promiseはもう少し色々できそうなので、別でもう少し勉強してみようと思います。
ES2015
ES6とも呼ばれる事があるようなのですが、次バージョンのES2016はES7とは言わないようなので、ES2015で覚えておこうと思います。
classやPromise以外にも色々とわかっておいたほうが良い機能があり、こちらも勉強しようと思います。
ES2015に関してはコチラの記事がとてもわかりやすくまとめて頂いているので、コチラを見ながら特に使いそうだなと感じたものを幾つか記載していきます。
let, const
let: 再宣言が出来ない
const: 再宣言・再代入が出来ない
アロー関数式
無名関数に対して、functionという記述を省略できるようです。
let sum_func = (a, b) => { return a + b; }; console.log(sum_func(1, 2)); // => 3
分割代入
一度に複数の変数に、それぞれの値を代入できるようです。
var [name, age] = ['ドラえもん', 20]; console.log(name); // => ドラえもん console.log(age); // => 20
デフォルト引数
これもPHPなど他の言語でも使われているので、分かりやすかったです。
function test(a = 1) { console.log(a); } test(); // => 1 test(2); // => 2
テンプレート文字列
PHPのヒアドキュメント的な感じでかけるようです。
var name = 'ドラえもん'; var message = `こんにちは! ぼく${name}です。` console.log(message); // => こんにちは! // ぼくドラえもんです。
終わり
今週一発目の記事は今週に入って1時間後にpostしました。
いろいろと勉強できて良かったです。
これだけ学べることがあったことで、自分が今まで理解できていなかったということがよくわかりました。
JSは流行り廃りが早いとかいいますが、そもそもそれを気にするレベルに達してないので、とりあえず貪欲に勉強し続けていこうと思います。
多分次の記事もJS関連だと思います。
ではでは。