LoginSignup
3
3

Javascriptの標準組み込みオブジェクトのFunctionのインスタンスメソッドcall(),apply(),bind()について

Last updated at Posted at 2023-07-30

なんとなくで使っていたので、整理を兼ねて文字に起こします。

はじめに

Javascriptには、標準組み込みオブジェクト(Standard built-in objects)というグローバル領域にあるオブジェクトがあります。
この標準組み込みオブジェクトにオブジェクトの基本となるオブジェクト、Object,
Function,Boolean,Symbolがあります。

今回はこの中のFunctionオブジェクトについて、深掘りしていきます。
Javascriptの全ての関数はこのFunctionオブジェクトであり、 Functionオブジェクトは functionsのメソッドを持ちます。

thisについて

Functionのメソッドで使うためにはthisを理解しておく必要があります。
個人的に、下記が一番わかりやすかったです。

thisはオブジェクト自身を指し、.の前のオブジェクトが指定されます。

関数の呼び出しをした時、オブジェクトで実行している場合、そのオブジェクトをthisとして参照できます。
オブジェクトを指定しない場合は、グローバルオブジェクトまたはundefinedが指定されます。
別のオブジェクトを指定した場合、その別のオブジェクトがthisとして参照されます。

// 1. オブジェクトを指定している
const obj1 = {
    prop1: 1,
    func1: function() { console.log(this) }
};
obj1.func1(); 
// => {prop1: 1, func1: ƒ}

// 2. オブジェクトを指定していない
const func2 = obj1.func1;
func2(); 
// => undefinedまたはグローバルオブジェクト (ブラウザで実行している場合はwindow)

// 3. 別のオブジェクトを指定する
const obj2 = {
    prop2: 2
}
obj2.func2 = obj1.func1;
obj2.func2(); 
// => {prop2: 2, func2: ƒ}

標準組み込みオブジェクトのFunctionのインスタンスメソッド

下記のメソッドが用意されています。

Function.prototype.call()

第一引数にthisの値、第二引数以降は呼び出し先の引数として渡されて、関数を呼び出せます。

const obj1 = {
    prop1: 1,
    func1_1: function(prop1_1) { console.log(prop1_1, this) },
    func1_2: function(prop1_1, prop1_2) { console.log(prop1_1, prop1_2, this) }
};
const obj2 = {
    prop2: 2
};

obj1.func1_1.call(obj2, 3);
// => 3 {prop2: 2}

obj1.func1_1.call(obj2, 3, 4);
// => 3 {prop2: 2}

obj1.func1_2.call(obj2, 3, 4);
// => 3 4 {prop2: 2}

obj1.func1_2.call(obj2, [3, 4, 5, 6], 7);
// =>  [3, 4, 5, 6] 7 {prop2: 2}

obj1.func1_1.call(1, 3); // 数値を指定するとNumberのオブジェクトとして指定される
// => 3 Number {1}

obj1.func1_1.call('1', 3); // 文字列を指定するとStringのオブジェクトとして指定される
// => 3 String {'1'} 

obj1.func1_1.call(null, 3); // nullやundefinedを指定すると、
// => 3 undefinedまたはグローバルオブジェクト

Function.prototype.apply()

第一引数にthisの値、第二引数は呼び出し先の引数を列挙したArrayを指定して、関数を呼び出せます。

const obj1 = {
    prop1: 1,
    func1: function(prop) { console.log(prop, this) }
};
const obj2 = {
    prop2: 2
}

obj1.func1_1.apply(obj2, 3);
// => Arrayでないので、error

obj1.func1_1.apply(obj2, [3]);
// => 3 {prop2: 2}

obj1.func1_1.apply(obj2, [3, 4]);
// => 3 {prop2: 2}

obj1.func1_2.apply(obj2, [3, 4]);
// => 3 4 {prop2: 2}

Function.prototype.bind()

第一引数にthisの値して、新しく関数を作成します。

const obj1 = {
    prop1: 1,
    func1: function(prop) { console.log(prop, this) }
};
const obj2 = {
    prop2: 2
};

const func1_1_bind = obj1.func1_1.bind(obj2);
const func1_2_bind = obj1.func1_2.bind(obj2);

func1_1_bind(3);
// => 3 {prop2: 2}

func1_1_bind(3, 4);
// => 3 {prop2: 2}

func1_2_bind(3, 4);
// => 3 4 {prop2: 2}

使い道を考える

下記のような、classのインスタンスメソッドをそのインスタンス外で使いたい時などで使える

class Animal {
    name = 'animal';
    display_name() {
        console.log(this.name)
    }
}

class Fish {
    name = 'fish';
}

const animal = new Animal();
const display_name1 = animal.display_name;
// 1. 別のオブジェクトのプロパティでメソッドを使う
const fish = new Fish();
display_name1.call(fish);
// => fish

// 2. インスタンスメソッドをそのインスタンス外で使う
const display_name2 = animal.display_name.bind(animal);
display_name2();
// => animal

終わり

調べるついでにQiita書こうと思うと、理解する意欲が変わるので今後続けていきたい

参照

MDN Web Docs Standard built-in objects Function

JavaScript の this を理解する多分一番分かりやすい説明

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3