├── Readme.md └── 関連用語.md /Readme.md: -------------------------------------------------------------------------------- 1 | # JavaScript(以下JS) 2 | - ES6 = ES2015 とする(呼び方多すぎ) 3 | 4 | ## 変数と定数の定義 5 | - 基本的に `const` で定義するようにし、どうしても必要な時だけ `let` を使うと事故を減らせる 6 | - `var` はES6で書けるのであればもう使わなくて良い 7 | - `let` 8 | - 変数を宣言する。宣言できるのは一度だけ 9 | - 宣言時に初期化を行わなくてもエラーにはならない(中身はundefinedとなる) 10 | - 値の再代入は可能だが、再宣言はエラーになる 11 | - `const` 12 | - 定数を宣言する。宣言と同時に必ず初期化する必要がある 13 | - 値の再代入も再宣言も不可能 14 | - 定数名は大文字とアンダースコアを組み合わせた名前を使うことが多い模様 15 | 16 | ## 識別子 17 | - 変数名、定数名として使われる文字列に関して以下の規則がある 18 | - 一文字目はUnicode文字、$、アンダースコアでなければならない 19 | - 二文字目以降には↑に加えて数字も使える 20 | - JSでは `testUser` などのようなキャメルケースで定義することが多い模様 21 | - ちなみにES6からは日本語も変数として使えるようになっている 22 | 23 | ```js 24 | const たかし = "やまだ" 25 | たかし // => やまだ 26 | ``` 27 | 28 | ## テンプレートリテラル 29 | - ES6から追加された、文字列の中に変数を埋め込むことができるリテラル(これマジで欲しかった) 30 | 31 | ```js 32 | const NAME = "メアリー" 33 | console.log(`私の名前は${NAME}です`) // => 私の名前はメアリーです 34 | ``` 35 | 36 | ## シンボル 37 | - ES6から使えるようになった 38 | - `Symbol()` コンストラクタから作成し、作成されたシンボルは必ずユニークとなる 39 | - 必ずユニークとなるので、オブジェクトプロパティの名前として使うと、バッティングを回避できる 40 | - 必要に応じて説明のための文字列を渡すことも可能 41 | 42 | ```js 43 | const obj = {} 44 | const HOGE = Symbol() 45 | 46 | obj[HOGE] = 123 47 | obj.HOGE = 999 48 | obj // => {HOGE: 999, Symbol(): 123} 49 | // ぱっと見HOGEは同じに見えるが、 50 | // obj[HOGE] はシンボルをキーとした値を返し(ここでは123) 51 | // obj.HOGE (または obj["HOGE"]) は文字列の "HOGE" をキーとした値を返す(ここでは999) 52 | // 分かりやすい変数名にしろという話ですが... 53 | ``` 54 | 55 | ## MapとSet、WeakMapとWeakSet 56 | - ES6から使えるようになったデータ型 57 | - Map 58 | - オブジェクトと同じくキーと値が対応しているもの 59 | - 状況によってはオブジェクトよりも便利な場合もある 60 | - Set 61 | - 配列に似ているが重複が不可能 62 | - WeakMap, WeakSet 63 | - ほぼ同じような働きをする 64 | - 一部の機能が使えない代わりに特定の状況では優れたパフォーマンスを発揮する 65 | 66 | ## オブジェクト 67 | - プロバティ(メンバーとも呼ばれる)とメソッドで構成される 68 | - オブジェクトの状態や特性を表すのがプロパティで、名前(キーとも呼ばれる)と値で構成される 69 | - オブジェクトのプロパティとして格納されているのがメソッド 70 | 71 | ```js 72 | const user = {} 73 | 74 | user.name = "ユーザー" //=> 「name」を名前、「ユーザー」を値に持つプロパティ 75 | user.age = 30 //=> 「age」を名前、「30」を値に持つプロパティ 76 | 77 | user.getInfo = function() { //=> メソッド 78 | return user.name + "" + user.age 79 | } 80 | ``` 81 | 82 | ## new 演算子 83 | - new 演算子は「受け取った引数で初期化したオブジェクトのインスタンスを返しなさい、とコンストラクタに命令する」演算子 84 | - new 演算子を使ってインスタンス化した場合、関数内の this はそのインスタンス自身を指す 85 | - この仕様のおかげでクラスがなくてもオブジェクト指向っぽい記述が可能になっている 86 | 87 | ## 関数 88 | - JSの関数は通常のオブジェクトと同じ振る舞いが可能(第1級オブジェクト、ファーストクラス関数などと呼ばれるらしい) 89 | - 変数や配列に代入ができ、パラメータ(引数)として利用することも可能 90 | - `function hoge() {` から `}` までが関数の「宣言」で、 `hoge()` で関数を「呼び出す」 91 | - 関数から何か戻り値を返す場合は `return` で指定する。 指定しなかった場合は `undefined` が戻り値となる 92 | - 関数名に `()` をつけて呼ぶと関数の呼び出しとなり、 `()` をつけないで呼び出すと関数を参照するだけで実行はされない 93 | 94 | ```js 95 | // 関数宣言 96 | function func1(a, b) { 97 | console.log(a, b) 98 | } 99 | 100 | // 呼び出し 101 | func1(1, 9) //=> 1 9 102 | 103 | // 関数の変数への代入 104 | const f1 = function() { 105 | console.log("あああ") 106 | } 107 | 108 | f1() //=> あああ 109 | 110 | // パラメータ(引数)として使用 111 | function func2(func) { 112 | func() 113 | } 114 | 115 | func2(f1) //=> あああ 116 | ``` 117 | 118 | - 通常のオブジェクトと同じ振る舞いが可能なので、メンバを動的に操作可能(非推奨) 119 | 120 | ```js 121 | const f3 = function() { 122 | // 特になし 123 | } 124 | 125 | f3.tes //=> undefined 126 | 127 | f3.tes = 12345 128 | 129 | f3.tes //=> 12345 130 | ``` 131 | 132 | - 関数は () で処理を呼び出すことができ、 () をつけずに呼び出すと定義の内容を参照することができる 133 | 134 | ```js 135 | const f4 = function() { 136 | console.log("かんすう") 137 | } 138 | 139 | f4() //=> かんすう 140 | f4 141 | //=> 142 | // ƒ () { 143 | // console.log("かんすう") 144 | // } 145 | ``` 146 | 147 | - JSの関数は return 文で明示的に指定されていない場合、自動的に呼び出し元には undefined を返却する 148 | - しかし、 new 演算子を用いて呼び出された場合はオブジェクトのインスタンスを返却する 149 | - new 演算子を使って呼び出さなかった場合は、ただの関数呼び出しになる 150 | 151 | ```js 152 | function Test(a, b) { 153 | this.a = a 154 | this.b = b 155 | } 156 | 157 | const aaa = new Test(1, 2) 158 | aaa //=> Test {a: 1, b: 2} 159 | aaa.a //=> 1 160 | aaa.b //=> 2 161 | 162 | const bbb = Test() 163 | bbb //=> undefined 164 | ``` 165 | 166 | - オブジェクトのプロパティとして指定される関数をメソッドと呼ぶ 167 | - メソッドはES6から省略記法が追加された 168 | 169 | ```js 170 | const obj = { 171 | name: "hoge", 172 | test() { return "Test func!" } 173 | // old: function() { return "Old ver!" } 以前はこう 174 | } 175 | 176 | obj.test() //=> "Test func!" 177 | ``` 178 | 179 | - さらにES6ではアロー関数という表記の仕方も導入された 180 | - `function`の省略が可能 181 | - 引数が一つならカッコを省略可能 182 | - 関数本体が一つの式からなる場合 `{}` と `return` が省略可能 183 | - などの利点がある 184 | - アロー関数は無名関数で、名前のついた関数を作る場合は今まで通り `function` を使って作成する 185 | - 引数に無名関数を渡したりするときによく使用される 186 | - 通常の関数ともっとも異なる点は `this` の扱われ方で、通常、関数の中で定義された関数の中で `this` を参照すると、 `undefined` かグローバルオブジェクトを参照してしまうが、アロー関数では `this` を一つ上の関数で呼んだときと同じ `this` を参照してくれる(非常にわかりにくい説明なので、下記 `this` も合わせて参照) 187 | - オブジェクトのコンストラクタとして使えなかったり、 `arguments` 変数が使えないなどの違いもある 188 | 189 | ```js 190 | const obj3 = { 191 | name: "hoge", 192 | test() { 193 | const innerFunc = () => { 194 | return this.name 195 | } 196 | return `${innerFunc()}, huga!` 197 | } 198 | } 199 | 200 | obj3.test() //=> "hoge, huga!" 201 | 202 | // もし innerFunc = () => {} が innerFunc = function() {} だった場合 203 | // obj3.test() は ", huga!" となる (this.nameがundefinedなので) 204 | ``` 205 | 206 | ## 引数 207 | - JSは引数チェックを一切行わない 208 | - 多く渡しても、少なく渡してもエラーは発生しない 209 | - 足りない分は undefined となり、余った分は何事もないかのように振る舞う 210 | 211 | ```js 212 | function func5(a, b) { 213 | console.log(a, b) 214 | } 215 | 216 | func5(1) //=> 1 undefined 217 | func5(1, 2, 3) //=> 1 2 218 | ``` 219 | 220 | - 関数に渡された引数は全て arguments というオブジェクトを使い、参照が可能 221 | - arguments は関数内のスコープのみで利用できる 222 | 223 | ```js 224 | function func6(a, b) { 225 | console.log(arguments) 226 | } 227 | 228 | func6(1, 2, 3, 4, 5, 6) //=> (5) [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ] 229 | 230 | function func7(a, b) { 231 | console.log(arguments[0]) 232 | } 233 | 234 | func7(5, 8, 1) //=> 5 235 | ``` 236 | 237 | - arguments は配列っぽい動作をするが配列とは別物なので注意 238 | - ES6からスプレッド演算子(展開演算子)が導入されたのでそちらを使った方が扱いに悩む必要がないのでおすすめ 239 | 240 | ```js 241 | function hoge(...aaa) { 242 | console.log(aaa) 243 | } 244 | 245 | hoge(1,2,3,4,5) //=> (5) [1, 2, 3, 4, 5] 246 | 247 | function hoge(...aaa) { 248 | console.log(...aaa) 249 | } 250 | 251 | hoge(1,2,3,4,5) //=> 1 2 3 4 5 252 | ``` 253 | 254 | ## 無名関数 255 | - JSでは関数名が必要なければ省略が可能 256 | - 複数回呼び出すことのない関数を定義する際に利用することが多い 257 | 258 | ```js 259 | const func = function() { console.log(111) } 260 | ``` 261 | 262 | ## コールバック 263 | - 引数として渡される関数のことをコールバック(コールバック関数)と言う 264 | - 引数として渡すことで関数内の任意のタイミングで発動することが可能 265 | - 代表的な使用例として非同期処理などがある 266 | 267 | ```js 268 | function func8(callback) { 269 | console.log("適当な処理") 270 | callback() 271 | } 272 | 273 | func8(function() { 274 | console.log("引数として渡される関数の処理") 275 | }) 276 | //=> 適当な処理 277 | // 引数として渡される関数の処理 278 | ``` 279 | 280 | ## 巻き上げ(var変数) 281 | - 関数内のどの位置でも `var` を使って変数宣言ができるが、これらの変数宣言は関数内のいかなる場所で宣言されたとしても「関数の先頭で宣言された」とみなされること 282 | - あくまで巻き上げられるのは宣言のみで、値の代入は巻き上げられない 283 | - これに対して `let` は宣言をするまでは存在しない(宣言前にアクセスしようとするとエラーとなる) 284 | 285 | ```js 286 | var aaa = "tes" 287 | 288 | var f9 = function() { 289 | console.log(aaa) 290 | } 291 | 292 | f9() //=> tes 293 | 294 | 295 | var f10 = function() { 296 | console.log(aaa) 297 | var aaa = "tes2" 298 | console.log(aaa) 299 | } 300 | 301 | f10() //=> undefined 302 | // tes2 303 | 304 | // 関数 f10 の内部は下記の記述と同じ 305 | var f10 = function() { 306 | var aaa 307 | console.log(aaa) 308 | aaa = "tes2" 309 | console.log(aaa) 310 | } 311 | ``` 312 | 313 | ## 巻き上げ(関数) 314 | - 関数もスコープの先頭に巻き上げられる 315 | 316 | ```js 317 | f() //=> "hoge" 318 | function f() { return "hoge" } 319 | ``` 320 | 321 | - しかし、変数に代入された関数は巻き上げられない 322 | 323 | ```js 324 | f2() //=> Uncaught ReferenceError: f2 is not defined 325 | let f2 = function() { return "hoge" } 326 | ``` 327 | 328 | ## 即時関数(IIFE) 329 | - 関数を定義すると同時に実行可能な関数のことを即時関数と呼ぶ 330 | 331 | ```js 332 | (function() { 333 | console.log(123) 334 | })(); 335 | //=> 123 336 | ``` 337 | 338 | ## this 339 | - 関数本体ではthisという参照のみが可能(値の代入はできない)な特別な値を利用することができる 340 | - JSの this は使用状況によって参照先が変化する「危険物」 341 | - 使用する際は誰が見ても誤解のないように、何を参照しているのかコメントで明記するのが望ましい 342 | - また、 this は常に特定のものを指すよう「束縛」することが可能なので、可能であれば束縛を上手く利用したいところ 343 | - thisは「関数の呼び出され方」に依存している。「関数の宣言された場所」には依存しない 344 | 345 | ```js 346 | const obj = { 347 | name: "たなか", 348 | speak() { return `私の名前は${this.name}です` } 349 | } 350 | 351 | obj.speak() //=> 私の名前はたなかです 352 | 353 | const func1 = obj.speak 354 | 355 | func1 === obj.speak //=> true (同じ関数を参照している) 356 | 357 | func1() 358 | "私の名前はです" //=> thisはundefined 359 | 360 | // func1内のthisはグローバルオブジェクトを参照している(chromeの場合) 361 | window.name = "グローバル" 362 | func1() //=> 私の名前はグローバルです 363 | 364 | // ちゃんとオブジェクトに束縛させればOK 365 | const obj2 = { 366 | name: "さとう" 367 | } 368 | 369 | obj2.speak = obj.speak 370 | 371 | obj2.speak() //=> "私の名前はさとうです" 372 | ``` 373 | 374 | ## thisの束縛(applyとcall) 375 | - 関数には `apply` と `call` と言うメソッドが用意されている 376 | - それぞれ関数内で参照する `this` を束縛するためのメソッド 377 | - this は呼び出した時の状況によって参照先が変化するが、これらのメソッドを使用することにより、常に指定したものを `this` として動作させることができる 378 | 379 | ```js 380 | const val = 1 381 | 382 | function func11(a, b) { 383 | console.log(this.val + a + b) 384 | } 385 | 386 | func11(3, 6) //=> 10 (this.val はグローバル変数のvalを参照) 387 | 388 | const val2 = { val: 5 } 389 | 390 | func11.apply(val2, [6, 1]) //=> 12 (this.val は val2 の val を参照している) 391 | func11.call(val2, 6, 1) //=> 12 392 | ``` 393 | 394 | - apply と call の違いは、引数を配列で渡すか、カンマ区切りで渡すかだけで結果に違いはない 395 | 396 | ## thisの束縛(bind) 397 | - bind は this を束縛した関数オブジェクトを生成する 398 | 399 | ```js 400 | function func12(a, b) { 401 | console.log(this.val + a + b) 402 | } 403 | 404 | const bind1 = func12.bind({val: 1}) 405 | const bind2 = func12.bind({val: 5}, 5) 406 | const bind3 = func12.bind({val: 2}, 6, 9) 407 | 408 | bind1(1, 2) //=> 4 (1 + 1 + 2) 409 | bind2(3) //=> 13 (5 + 5 + 3) 410 | bind3() //=> 17 (2 + 6 + 9) 411 | ``` 412 | 413 | - 上記の例からもわかる通り、束縛する引数の数は自由に設定が可能 414 | - ただし、bindは永続的な束縛を行うため、見つけるのが困難なバグの原因となりかねないので注意が必要 415 | 416 | ## コンストラクタ 417 | - コンストラクタはオブジェクトのインスタンス化の際に呼び出されるメソッド 418 | - Ruby でいうところの initialize メソッドに近い 419 | - JSでは function で擬似的なクラスを作ることができ、 new 演算子でインスタンスを作ることができる 420 | - 要するに class 内では constructor の部分で、関数であれば関数 = コンストラクタとなる 421 | 422 | ```js 423 | function User(name, age) { //=> コンストラクタ 424 | this.name = name 425 | this.age = age 426 | } 427 | 428 | const u1 = new User("ユーザー1", 24) 429 | u1 //=> User {name: "ユーザー1", age: 24} 430 | ``` 431 | 432 | - 上記例では User というコンストラクタを定義し、その中でnameとageを初期化している 433 | - また、コンストラクタ内ではメソッドも定義可能 434 | 435 | ```js 436 | function User(name, age) { //=> コンストラクタ 437 | this.name = name 438 | this.age = age 439 | this.getName = function() { 440 | return this.name 441 | } 442 | } 443 | 444 | const usr1 = new User(123, 99) //=> User {name: 123, age: 99, getName: ƒ} 445 | usr1.getName() //=> "123" 446 | ``` 447 | 448 | - しかし、これだと User のインスタンスを作成するごとに、インスタンスに .getName() がコピーされるため、メモリを大量に消費する可能性がある 449 | - そこでJSでは prototype というものを使ってメソッドを追加することができる 450 | 451 | ```js 452 | function User(name, age) { //=> コンストラクタ 453 | this.name = name 454 | this.age = age 455 | } 456 | 457 | User.prototype.getName = function() { 458 | return this.name 459 | } 460 | 461 | const usr = new User("ggg", 78) //=> User {name: "ggg", age: 78} 462 | usr.getName() //=> "ggg" 463 | ``` 464 | 465 | - usr 自体は getName() をもっていないが、prototype を通して定義されたメソッドが参照できている 466 | 467 | ## constructor 468 | - コンストラクタから生成されたオブジェクトは constructor に生成に使用したコンストラクタ関数を保持している 469 | - ちなみに、この constructor はオブジェクトが参照しているコンストラクタ関数のプロトタイププロパティの値として存在する 470 | 471 | ```js 472 | function Tes() {} 473 | 474 | const tes = new Tes 475 | 476 | tes.__proto__ //=> {constructor: ƒ} 477 | Tes.prototype //=> {constructor: ƒ} 478 | 479 | tes.__proto__ === Tes.prototype //=> true 480 | 481 | tes.constructor //=> ƒ Tes(){} 482 | Tes.prototype.constructor //=> ƒ Tes(){} 483 | 484 | // 以上から、 tes.constructor は Tes.prototype.constructor を参照していることがわかる 485 | ``` 486 | 487 | - instanceof と異なり、コンストラクタの種類が判定できるため「出所不明」なオブジェクトの詳細を調べる際に使える 488 | 489 | ```js 490 | const a = [] 491 | const b = {} 492 | const c = function() {} 493 | 494 | a.constructor //=> ƒ Array() { [native code] } 495 | b.constructor //=> ƒ Object() { [native code] } 496 | c.constructor //=> ƒ Function() { [native code] } 497 | 498 | // 自作のコンストラクタ 499 | const Myf1 = function() {} 500 | const aaa = new Myf1 501 | aaa.constructor //=> ƒ () {} (無名関数なので名前が表示されない) 502 | 503 | // 名前が欲しければコンストラクタに名前をつけておく 504 | const Myf1 = function myfunc() {} 505 | const aaa = new Myf1 506 | aaa.constructor //=> ƒ myfunc() {} 507 | ``` 508 | 509 | ## データ型 510 | - JSのデータ型は大きく分けて「基本型(プリミティブ型)」と「参照型(オブジェクト型)」に分類される 511 | - 基本型と参照型は「値そのものを扱うのか、値の格納されているアドレスを扱うのか」が異なる 512 | 513 | ## プリミティブ型 514 | - JSには以下の5つのプリミティブ型が存在する 515 | - Boolean 516 | - Number 517 | - String 518 | - null 519 | - undefined 520 | - Symbol <- new! ES6から! 521 | - プリミティブ型とは、 true, 999, "テスト" などの「値そのもの」を扱うためのデータ型 522 | - それぞれコンストラクタから「オブジェクト」として生成することも可能だが、ほぼ無意味に等しいので使う必要はない 523 | 524 | ```js 525 | // 通常はこう使う 526 | const a = 123 527 | const b = "aiu" 528 | const c = true 529 | 530 | // このような使用は通常避けるべき 531 | const a2 = new Number(123) 532 | const b2 = new String("aiu") 533 | const c2 = new Boolean(true) 534 | ``` 535 | 536 | - なぜそれぞれオブジェクトが存在しているのか? 537 | - 上記a, b, cは「ただの値」であるプリミティブ型の変数だが、実は「オブジェクトであるかのようにメソッドを呼び出すこと」が可能 538 | 539 | ```js 540 | a //=> 123 541 | a.toString() //=> "123" 542 | ``` 543 | 544 | - JSではプリミティブ型の変数が「オブジェクトのように扱われる」と、一時的にオブジェクトに変換が行われる 545 | - 上記例では .toString() がオブジェクトのように扱う行為なので、裏で自動的にオブジェクト変換が行われている 546 | - このように裏で自動的に生成されるオブジェクトは「ラッパーオブジェクト」と呼ばれる 547 | - ラッパーオブジェクトは必要に応じて生成され、不要になったら破棄される 548 | - なお、 null と undefined にはラッパーオブジェクトは存在しないため、常にプリミティブな存在 549 | 550 | ## 参照型(オブジェクト型) 551 | - 主に以下の種類がある 552 | - 配列を扱うための array 553 | - オブジェクトを扱うための object 554 | - 関数を扱うための function 555 | 556 | ## リテラル 557 | - データ型に格納できる値そのもの、または値の表現方法のことを「リテラル」と呼ぶ 558 | - 数値リテラル 559 | - 整数リテラルと浮動小数点リテラルに分類される 560 | 561 | ```js 562 | 100 //=> 整数(10進数)リテラル。 563 | 060 //=> 整数(8進数)リテラル。 先頭に0をつける。 564 | 0xCC55BB //=> 整数(16進数)リテラル。先頭に0xをつける。 565 | 1.1 //=> 浮動小点数リテラル。 566 | ``` 567 | 568 | - 文字列リテラル 569 | - シングルクォートまたはダブルクォートで値を囲んだもの 570 | - "aiueo" など 571 | - 配列リテラル 572 | - カンマで区切った値をブラケット([])で囲った形式 573 | - [1, 2, 3] など 574 | - オブジェクトリテラル 575 | - 名前をキーにしてアクセスができるもの(ハッシュや連想配列とも呼ばれる -> 最近は map を使うので呼ばない) 576 | - ドットまたはブラケットでアクセスが可能 577 | 578 | ```js 579 | const obj = { a: 1, b: 2, c: 3 } 580 | 581 | obj.a //=> 1 582 | obj["b"] //=> 2 583 | ``` 584 | 585 | - 関数リテラル 586 | - 関数もデータ型の一種 587 | 588 | ## null と undefined 589 | - 「null」 は 「nullを設定した状態」 590 | - 「undefined」は「未定義、何も設定していない状態」 591 | - 要するに「nullは設定しない限り存在しない」 592 | - 定義した変数に対して何もしなければ undefined で、nullを代入すると null となる 593 | - 変数が null または undefined であるかの確認は、単純な同値比較( === )を使えばよい 594 | 595 | ```js 596 | let r 597 | if (r === undefined) { console.log(123) } 598 | //=> 123 599 | 600 | r = null 601 | if (r === null) { console.log(123) } 602 | //=> 123 603 | ``` 604 | 605 | ## if文で false と判定される条件 606 | - 以下の5つがif文でfalseと判定される 607 | - undefined 608 | - null 609 | - 0 610 | - 空文字("") 611 | - false 612 | - NaN 613 | 614 | ## グローバル変数 615 | - JSでは var を使わずに変数を宣言するとグローバルな変数として宣言されてしまうが、極力グローバル変数などは作らないことが推奨されている 616 | - グローバルが汚染され将来的に変数名が衝突する可能性があるため 617 | - そこで代表的な代替案として「名前空間」を使用する方法と、「クロージャ」を使用する方法がある 618 | 619 | ## 名前空間 620 | - JSには他言語のように仕組みが存在するわけではなく、オブジェクトを利用してそれらと同等の仕組みを実現している 621 | 622 | ```js 623 | const Hakozaru = {} //=> グローバル変数を定義 624 | 625 | Hakozaru.tes = "test!" 626 | Hakozaru.tes //=> "test!" 627 | 628 | Hakozaru.getHako = function() { 629 | console.log("箱") 630 | } 631 | 632 | Hakozaru.getHako() //=> 箱 633 | ``` 634 | 635 | - 上記例でグローバル変数を一つだけ定義しているが、このグローバル変数の名前を会社名やプロジェクト名などにすれば、ほぼ確実に変数の衝突を回避することが可能 636 | 637 | ## グローバルオブジェクトは変更しない 638 | - JSでは既存のグローバルオブジェクトに対して操作が行える 639 | - Rubyのように既存の String などに対しても独自のメソッドが追加できてしまう 640 | - Rubyでも同じだが、余計な混乱を招かないためにもグローバルオブジェクトは触らないようにすることが望ましい 641 | 642 | ## 例外処理(try〜catch) 643 | - JSの例外処理は非常にオーバーヘッドが大きい処理なので、むやみやたらに使用するのは危険 644 | - 使用の際は「本当に例外処理をしないといけない処理なのか」を考えて使用すること 645 | - なお、意図的に例外を発生させる場合は throw を使用する 646 | 647 | ```js 648 | try { 649 | // 例外が発生する可能性がある処理 650 | } catch(例外を受け取る変数) { 651 | // 例外が発生した場合に実行する処理 652 | } finally { 653 | // 最後に実行される処理 654 | } 655 | 656 | throw new Error("message") //=> Uncaught Error: message at :1:7 657 | ``` 658 | 659 | ## typeof 演算子 660 | - 対象のデータ型を調べる演算子 661 | - JSは動的にデータ型が変化するため、型に応じた処理をしたい場合はこの演算子を使う 662 | - 一部不思議な結果が返される 663 | - 結論からいうと「文字列、数値、真偽値のプリミティブ値に対してのみ使用すべき」 664 | 665 | ```js 666 | const a = "abc" 667 | const b = 123 668 | const c = true 669 | const d = new String("abc") 670 | const e = [] 671 | 672 | typeof a //=> "string" 673 | typeof b //=> "number" 674 | typeof c //=> "boolean" 675 | typeof d //=> "object" (NumberやBooleanでも同じ) 676 | typeof e //=> "object" (配列もobjectが返る) 677 | ``` 678 | 679 | - null は object として判定されるので注意が必要 680 | 681 | ```js 682 | const t = null 683 | const z = undefined 684 | 685 | typeof t //=> "object" 686 | typeof z //=> "undefined" 687 | ``` 688 | 689 | - オブジェクトに対して使用した場合は、関数オブジェクトのみ function が返される 690 | 691 | ```js 692 | typeof [] //=> "object" 693 | typeof {} //=> "object" 694 | typeof function() {} //=> "object" 695 | ``` 696 | 697 | ## instanceof 演算子 698 | - オブジェクトが何のコンストラクタから生成されたかを判定する 699 | 700 | ```js 701 | const a = {} 702 | const b = [] 703 | const c = function() {} 704 | 705 | a instanceof Object //=> true 706 | b instanceof Array //=> true 707 | c instanceof Function //=> true 708 | ``` 709 | 710 | - 全てのオブジェクトは Object から派生しているため、 オブジェクト instanceof Object は必ず true となる 711 | - instanceof演算子はオブジェクトのプロトタイプチェーンを辿ってコンストラクタのチェックを行うため 712 | - 自作のコンストラクタも判定可能 713 | 714 | ```js 715 | const hoge = function() {} 716 | const aaa = new hoge() 717 | 718 | aaa instanceof hoge //=> true 719 | ``` 720 | 721 | ## 三項演算子 722 | - if ~ else に相当する式 723 | 724 | ```js 725 | const result = true ? "true!" : "false" 726 | console.log(result) // => "true!" 727 | ``` 728 | 729 | ## map(連想配列) 730 | - 以前は連想配列(ハッシュ)はオブジェクトで表現するのが当たり前だったが、ES6より map がサポートされたことにより map を使用するのが一般的になった 731 | 732 | ```js 733 | const m = new Map() 734 | 735 | m.set("key", "value") //=> Map(1) {"key" => "value"} 736 | m.get("key") //=> "value" 737 | 738 | m.set(1, 2) //=> Map(2) {"key" => "value", 1 => 2} 739 | 740 | m.size //=> 2 741 | 742 | m.keys() //=> MapIterator {"key", 1} 743 | m.values() //=> MapIterator {"value", 2} 744 | m.entries() //=> MapIterator {"key" => "value", 1 => 3} 745 | m.has("key") //=> true 746 | ``` 747 | 748 | ## クラス 749 | - ES6でクラスが正式にサポートされた 750 | - コンストラクタ内で、 this を介して追加した変数はメンバ変数となる(hoge.nameなどで呼び出し可能) 751 | - extends で継承が可能 752 | - クラスメソッドは static で定義する 753 | 754 | ```js 755 | class User { 756 | constructor(name) { 757 | this.name = name 758 | } 759 | 760 | // インスタンスメソッド 761 | getName() { 762 | return this.name 763 | } 764 | 765 | // クラスメソッド 766 | static getClassName() { 767 | return "User" 768 | } 769 | } 770 | 771 | const user = new User("たなかたろう") 772 | user.name //=> "たなかたろう" 773 | user.getName() //=> "たなかたろう" 774 | User.getClassName() //=> "User" 775 | 776 | // 継承は extends で行う 777 | class User2 extends User { 778 | insMethod() { 779 | return "User2のインスタンスメソッド" 780 | } 781 | } 782 | 783 | const user2 = new User2("123") 784 | user2.name //=> "123" 785 | user2.getName() //=> "123" 786 | User2.getClassName() //=> User 787 | user2.insMethod() //=> "User2のインスタンスメソッド" 788 | ``` 789 | 790 | ## 分割代入(デストラクチャリング) 791 | - ES6から分割代入が行えるようになった 792 | 793 | ```js 794 | const obj = { a: 123, b: 456, c: 789, z: 999 } 795 | const { a, b, c, d } = obj 796 | 797 | a //=> 123 798 | b //=> 456 799 | c //=> 789 800 | d //=> undefined 801 | z //=> ReferenceError: z is not defined 802 | ``` 803 | 804 | ## スコープ 805 | - 静的スコープ 806 | - グローバルスコープ 807 | - グローバルスコープで宣言したものは全てのスコープで利用可能になる 808 | - その影響範囲から、グローバルスコープに変数や関数などを定義し使用する場合は注意が必要 809 | - ブロックスコープ 810 | - `let` と `const` は識別子をブロックスコープで定義する 811 | - ブロックスコープで定義された識別子はそれを囲むブロックでしか有効にならない 812 | - 以下はスタンドアロンなブロックを定義した場合の例 813 | 814 | ```js 815 | { 816 | const x = 3 817 | console.log(x) //=> 3 818 | } 819 | console.log(x) //=> Uncaught ReferenceError: x is not defined 820 | ``` 821 | 822 | ```js 823 | let u = 0 824 | 825 | if(true) { // ブロックの始まり 826 | let u = 555 //=> ifの外で定義している u とは別の新しい変数が定義される(変数のマスキング) 827 | console.log(u) //=> 555 828 | } // ブロック終わり 829 | 830 | u //=> 0 831 | ``` 832 | 833 | - 関数スコープ 834 | - `var` によって宣言された変数は関数スコープを持つ(宣言された関数内であればどこでも有効) 835 | - この辺りは「巻き上げ」とも関係があるので、そちらも参照 836 | 837 | ## strictモード 838 | - `var` を使い忘れて宣言された変数などの、暗黙的なグローバルが禁止される厳格なモード 839 | - `"use strict;"` と書くことで厳格モードでコードが実行される 840 | - グローバルスコープに書くとスクリプト全体に適用され、関数内に書けばその関数が `strict` モードとして実行される 841 | - スクリプト全てが厳格モードになると、それはそれで困る場合があるので、自分の書いたコードのみに適用する場合は即時関数などでラップしてしまうのがよさそう 842 | 843 | ```js 844 | (function() { 845 | "use strict"; 846 | 847 | // 以降全てstrictモードで実行される 848 | // この関数の外にあるコードには影響しない 849 | })(); 850 | ``` 851 | -------------------------------------------------------------------------------- /関連用語.md: -------------------------------------------------------------------------------- 1 | ### 軽く用語まとめ 2 | - Node.js 3 | - ブラウザ以外の環境でJSを実行する際に用いる 4 | - npm 5 | - Node.jsをインストールすると一緒にインストールされるパッケージマネージャー 6 | - Babel 7 | - ES2015(ES6)のプログラムをES5のプログラムに変換するトランスパイラー 8 | - 最新のES〇〇のJSのコードはブラウザが対応しておらず動作しないことがあるため、それを現在のブラウザで実行可能なコードに変換する際に用いるNode.js製のツール 9 | --------------------------------------------------------------------------------