ENCA 21日目: Function.prototype.bind でターゲットの length が Infinity な場合の挙動明示
length
プロパティ
函数の JavaScript の函数は length
プロパティが設定されるようになっています。これは函数を作った際に受け取る引数(デフォルト引数や残余引数が現れる前の引数)の数が設定されます。
function foo(a, b, c = "c") {}
console.log(foo.length); // 2
なおこのプロパティは configurable であるため、Object.defineProperty
を使って値を書き換えることが出来ます。
function foo(a, b, c = "c") {}
Object.defineProperty(foo, "length", { value: 10 });
console.log(foo.length); // 10
Function.prototype.bind
とは
Function.prototype.bind
を使うことで函数に渡されるレシーバー(this
)といくつかの引数をあらかじめ設定した Bound Function Exotic Objects を作ることが出来ます。この Bound Function は元のターゲット函数への参照を保持しており、実行時や instanceof
演算子で使われる OrdinaryHasInstance でターゲット函数を使うようになっています。
また Bound Function の length
プロパティはターゲット函数の length
から、あらかじめ設定する引数の数を引いた値が設定されます。
function add(a, b) {
return a + b;
}
const boundAdd = add.bind(null, 1);
console.log(boundAdd(2)); // 3
console.log(boundAdd.length); // 1
Function.prototype.bind
でターゲット函数の length
が Infinity
な場合の挙動明示
函数の length
プロパティを Infinity
に設定し、それに Function.prototype.bind
を実行することを考えます。
function foo() {}
Object.defineProperty(foo, "length", { value: Infinity });
console.log(foo.bind(null, 1, 2).length);
このときの仕様が曖昧になっており、V8 と SpiderMonkey では Infinity
となり、JavaScriptCore では 0
となり、IoT 用の JavaScript ランタイムである Moddable XS では Number.MAX_SAFE_INTEGER - 2
の値を持つようになっていました。
2020年9月にどういう挙動にしたらよいか議論され、ターゲット函数が length
として Infinity
を持つ場合は Bound Function も Infinity
を持つべきと結論付けられました。
Discussion