JavaScript - bind

公開日:2018-11-29 更新日:2019-05-13

1. 概要

bind は、既存の関数に対して、引数を固定で設定した新しい関数を生成します。
bind の第1引数は call、apply と同様に、関数内の this に割り当てるオブジェクトです。

関数1(引数a, 引数b, 引数c);

//引数 a に 10、引数 b に 20 を割り当てる
関数2 = 関数1.bind(null, 10, 20); 

//bindで生成される関数
関数2(引数c) {
	関数1(10, 20, 引数c);
}

関数2(300); //関数1(10, 20, 300); が実行される

2.1 bind

var add = function(value1, value2, value3) {
	console.log("value1 = " + value1);
	console.log("value2 = " + value2);
	console.log("value3 = " + value3);
	return value1 + value2 + value3;
}

//第1引数が 10 固定の新しい関数が func に入る
var func = add.bind(null, 10);

console.log( func(100, 1000) );

value1 = 10
value2 = 100
value3 = 1000
1110

2.2 bind の用途

以下の例では、0、1、2、3、4 を返す関数を配列に入れているように見えますが、
実行すると、全て結果が 5 になります。

var func_list = [];
for (var i = 0; i < 5; i++) {
	var func = function () {
		return i;
	};
	
	func_list.push(func);
}

console.log( func_list[0]() ); //5
console.log( func_list[1]() ); //5
console.log( func_list[2]() ); //5
console.log( func_list[3]() ); //5
console.log( func_list[4]() ); //5

これは、return で指定している i が、関数を実行する時まで、変数として扱われるためです。
上記関数の配列は、以下のようになっています。
func_list[0] = function () { return i; };
func_list[1] = function () { return i; };
func_list[2] = function () { return i; };
func_list[3] = function () { return i; };
func_list[4] = function () { return i; };

これは、bind を使うと解決できます。

function func(i) {
	return i;
}

var func_list = [];
for (var i = 0; i < 5; i++) {
var newFunc = func.bind(null, i);
	func_list.push(newFunc);
}
console.log( func_list[0]() ); //0
console.log( func_list[1]() ); //1
console.log( func_list[2]() ); //2
console.log( func_list[3]() ); //3
console.log( func_list[4]() ); //4

また、bind を使わずに、以下のようにしても解決できます。

var func_list = [];
for (var i = 0; i < 5; i++) {
	var func = function(j) {    // j はループ毎に異なる変数として扱われる
		return function() {
			return j;
		}
	}(i);
	
	func_list.push(func);
}

console.log( func_list[0]() ); //0
console.log( func_list[1]() ); //1
console.log( func_list[2]() ); //2
console.log( func_list[3]() ); //3
console.log( func_list[4]() ); //4

無名関数 function(j) は、ループで5回実行されますが、
引数の j は、全て異なる変数として扱われます。
無名関数を抜けても、無名関数内で j を参照しているため、各 j の値は破棄されません。
そのため、「return j;」を実行すると、異なる値を返します。

「return 0;」 と言う関数が実行されているのではなく、
あくまでも、「return j;」が実行されています。