# JavaScript 再入門 #3 ###### tags: `JavaScript` - 参考: [【JS】初級者から中級者になるためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/) ## 関数 - 同じ名称の関数宣言がなされていた場合、呼び出し時にはあとから定義されたものが呼び出される - 引数のデフォルト値 ```javascript function fn(a,b=1) { console.log(a,b) }; fn(1,2); //=> 1,2 fn(1); //=> 1,1 fn(1,null) //=> 1,null fn(1,undefined) //=> 1,1 ``` - `arguments` は実引数(関数呼び出し時に当て込む値)が格納されるオブジェクト - 関数内では `return` で呼び出し/実行元に内部の値を返すことができる ## 関数とオブジェクトの関係 - そもそも関数とは、実行可能な**オブジェクト**のことである - 関数へのプロパティやメソッドの追加 ```javascript function fn() { console.log("hello") }; a.prop = 0; a.method = function() { console.log("method") }; a(); //=> hello a.method(); //=> method console.log(a.prop); //=> 0 ``` ## コールバック関数 - 他の関数に引数として渡される関数のこと - 実例 ```javascript function hello() { console.log("hello"); }; function bye() { console.log("bye"); }; function fn(cb) { cb(); } fn(hello); //=> hello fn(bye); //=> bye ``` ## `this` - 呼び出し元のオブジェクトへの参照を保持するキーワードで、 **実行コンテキストによって参照先が変わる** - 実例 ```javascript const person ={ name: "Tom", hello: function() { console.log("Hello " + this.name); } }; person.hello(); //=> 上記の場合だとこの this は person となる ``` ## 参照のコピーと `this` - 別の変数に関数を代入し、もともとの関数に定義されていたメソッドを実行すると `this` が参照するのはグローバルオブジェクトになる。これは `this` がメソッドとして実行されるか関数で実行されるかよって参照するオブジェクトが変わるため - メソッドとして実行した場合 ```javascript const person ={ name: "Tom", hello: function() { console.log("Hello " + this.name); } }; person.hello(); //=> Hello ``` - 関数として実行した場合 ```javascript window.name = "John"; const person ={ name: "Tom", hello: function() { console.log("Hello " + this.name); } }; const ref = person.hello(); ref(); //=> Hello John ``` - 参照イメージ ![](https://i.imgur.com/Lv1z7UL.png) ## コールバック関数と `this` - コールバック関数として渡した場合も関数内での実行となるため `this` の参照はグローバルオブジェクトとなる ```javascript window.name = "John"; const person ={ name: "Tom", hello: function() { console.log("Hello " + this.name); } }; person.hello(); //=> Hello Tom function fn(ref) { ref(); } fn(person.hello); //=> Hello John ``` ## `bind` と `this` - `bind` を利用すると `this` の参照先を指定することができる - 実行例 ```javascript window.name = "John"; const person ={ name: "Tom", hello: function() { console.log("Hello " + this.name); } }; person.hello(); //=> Hello Tom const helloTom = person.hello.bind(person); function fn(ref) { ref(); } fn(helloTom); //=> Hello Tom ``` - 下記の例では引数の束縛を行っている。対象の関数内に `this` がないので `bind` の第1引数は `null` とし、第2引数に束縛したい値を設定する ```javascript function a(name) { console.log("Hello " + name); } const b = a.bind(null, "Tim"); b(); //=> Hello Tim b("Tom"); //=> Hello Tim ``` - 参照イメージ ![](https://i.imgur.com/dnm6SwM.png) ## `call` , `apply` と `this` - `bind` は `this` や引数を束縛するがそれ単体では実行はしない ただし `call` , `apply` は呼び込んだ時点で実行まで行う - 実行例 ```javascript function a(name, name1) { console.log("Hello " + name + " " + name1); } const tim = {name: "Tim"} const b = a.bind(tim); a.apply(tim, ["Tim", "Bob"]); //=> Hello Tim Bob a.call(tim, "Tim", "Bob"); //=> Hello Tim Bob ``` ## アロー関数 - ES6から導入された無名関数を記述しやすくした省略記法 - 記述例 ```javascript function a(name) { return "Hello " + name; } const b = function(name) { return "Hello " + name; } const c = name => "Hello " + name; const d = (name, name1) => "Hello " + name + " " + name1; console.log(c("Tom")); //=> Hello Tom console.log(d("Tom", "Bob")); //=> Hello Tom Bob ``` ## アロー関数と `this` - アロー関数と無名関数の違い ![](https://i.imgur.com/868H9x4.png) - メソッドや関数をアロー関数で記述した場合 ```javascript window.name = "John"; const person = { name: "Tom", hello: () => { console.log("Hello " + this.name) } } person.hello(); //=> Hello John ``` ```javascript window.name = "John"; const a = () => console.log("Bye " + this.name); const person = { name: "Tom", hello() { // メソッドはこのようにも記述できる console.log("Hello " + this.name); a(); } } person.hello(); //=> Hello Tom Bye John ``` ![](https://i.imgur.com/pocxKqT.png)