BLOG

thisについて

thisについてメモ

thisとは

呼び出し元のオブジェクトへの参照を保持するキーワード
実行コンテキストによって’this’の参照先は変わる


const person = {
    name: 'ken',
    yo: function(){
        console.log('yo ' + this.name);//このthisがオブジェクトのpersonを参照するので、person.nameの'ken'が入ってくる
    }
}
person.yo();


yo ken

thisと参照のコピー

オブジェクトのメソッドとして実行される場合

‘this’=>呼び出し元オブジェクト

関数として実行される場合

‘this’=>グローバルオブジェクト


window.name = 'John'
const person = {
    name: 'Tom',
    hello: function() {
        console.log('Hello ' + this.name);
        a();
    }
}

person.hello();
function a(){
    console.log('hello ' + this.name);
}


Hello Tom
hello John

thisと コールバック関数


window.name = 'John';

const person = {
    name: 'Tom',
    hello: function() {
        console.log('Hello ' + this.name);
    }
}

const person2 = {
    name: 'jerry',
    hello2: function() {
        console.log('Hellooooo ' + this.name);
    }
}

function fn(ref){
    ref();
}

person.hello();
person2.hello2();
fn(person2.hello2);


Hello Tom
Hellooooo jerry
Hellooooo John

この
fn(person2.hello2);
関数として実行されているため、出力されるthis.nameの値はグローバルオブジェクトの’John’になる。
ではこれを’Tom’や’Jerry’を出力できるようにするにはどうすればいいのか。

bindを使う



const person = {
    name: 'Tom',
    hello: function() {
        console.log('Hello ' + this.name);
    }
}

const person2 = {
    name: 'jerry',
    hello2: function() {
        console.log('Hellooooo ' + this.name);
    }
}
const helloTom = person.hello.bind(person);//追加
const helloJerry = person2.hello2.bind(person2);//追加

function fn(ref){
    ref();
}

person.hello();
person2.hello2();
fn(person2.hello2);
fn(helloTom);//追加
fn(helloJerry);//追加



Hello Tom
Hellooooo jerry
Hellooooo John
Hello Tom //更新
Hellooooo jerry //更新

bindが何を行っているのか

  1. bindの第一引数で渡したオブジェクト(person)をhelloの中で実行されるthisの参照先として設定
  2. その設定した関数を新しい関数としてhelloTomに返却する
  3. よってhelloTomという関数を実行した際には、bindで指定したオブジェクト(person) がthisの参照先となる
  4. fn(helloTom)のようにコールバック関数で渡したとしてもHello Tomが出力される

function a(){
    console.log('hello ' + this.name);
}

const b = a.bind({name: 'michael'}); 
b();


hello michael

上記のような場合
下記のように省略できる



function a(name){
    console.log('hello ' + name);
}
const b = a.bind(null, 'michael');

b();


hello michael

  1. this.nameを削除し、a()にnameという引数が渡ってくるようにする。
  2. 関数内でthisが使われなくなった場合は、bindの第一引数を設定する必要がないのでnullにする。
  3. bind第2引数以下に関数の引数(name)を渡すことによって、引数の値’michael’を束縛することができる。
  4. そうすると’Tim’という値が引数で固定されて、a(name)に渡ってくる
  5. b()を実行すると、hello michaelが出力される

※b()に引数を渡して実行しても、bindのほうが優先されるので、
b(‘jacson’);
を渡しても
hello michael
と出力される。

bindではthisのオブジェクトを固定もしくは引数を固定することができる。

bindまとめ

bindによるthisの束縛

bindによってthisや引数を固定して新しい関数を作成すること。

実行コンテキストによっては、自分の使いたいthisが渡ってこない場合があるがそのような場合に、bindを使ってthisの値を束縛することによってthisが渡ってこない問題を解決する。

thisとcall,apply

bind

thisや引数の参照先を変更。使用時点で実行はしない。bindによってthisや引数を固定した新しい関数を作るところまでをbindを読んだ時点では行う。

call, apply

thisや引数の参照先を変更するのはbindと同じだが、これらはメソッドを呼んだ時点で同時に関数を実行する。

bindの場合


function a(name) {
    console.log('hello ' + name);
}

const b = a.bind(null, 'Tim');

b();


hello Tim



function a() {
    console.log('hello ' + this.name);
}
const tim = { name: 'Tim'};

const b = a.bind(tim);

a.apply(tim)
a.call(tim)


hello Tim
hello Tim

applyとcallの違い

callを呼んだら、第2引数以下は関数の引数を定義することができる。

第一引数はthisの参照先のオブジェクト


function a(name) {//nameいれる
    console.log('hello ' + name);//thisをとる
}
const tim = { name: 'Tim'};

const b = a.bind(tim);

b();
a.apply(tim);
a.call(tim, 'Tim');//第2引数に'Tim'いれる


hello undefined
hello undefined
hello Tim

applyを呼んだら、第2引数にはいるのは文字列ではなく配列になる

第一引数はthisの参照先のオブジェクト
第2引数には配列を渡して、配列は引数に一つずつ渡る



function a(name, name1) {//name1加える
    console.log('hello ' + name + ' ' + name1);
}
const tim = { name: 'Tim'};

const b = a.bind(tim);

a.apply(tim, ['Tim','Boby']);//'Boby'加える



hello Tim Boby

applyの実践的な使い方


const arry = [1,2,3,4,5];
const result = Math.max.apply(null, arry);
console.log(result);


5

applyの第一引数はthisだが、この場合設定する必要がないのでnullをいれる。第2引数にarry。

ES6ではスプレッド演算子を使って上記を表現することが可能


const arry = [1,2,3,4,5];
const result = Math.max(...arry);
console.log(result);


5