これを知って、バインド、呼び出し、適用するものを具体的に参照してください
それらはすべて機能的な方法です
call: Array.prototype.call(this, args1, args2])
apply: Array.prototype.apply(this, [args1, args2])
:ES6の前は、配列呼び出しを展開するために使用されfoo.appy(null, [])
、ES6の後は、...演算子を使用します
- 新しいバインディング>明示的なバインディング>暗黙的なバインディング>デフォルトのバインディング
- bindのカリー化とapplyの配列破壊を使用する必要がある場合は、nullにバインドし、可能な限りObject.create(null)を使用してDMZオブジェクトを作成します。
4つのルール:
- デフォルトのバインディング、他の装飾(バインド、適用、呼び出し)なし、グローバルオブジェクトを指すように非厳密モードで定義、未定義を指すように厳密モードで定義
function foo() {
console.log(this.a);
}
var a = 2;
foo();
- 暗黙的なバインディング:呼び出し場所にコンテキストオブジェクトがあるかどうか、またはオブジェクトによって所有または含まれているかどうかにかかわらず、暗黙的なバインディングルールは、関数呼び出しでこれをこのコンテキストオブジェクトにバインドします。さらに、オブジェクト属性チェーンの前のレイヤーまたは最後のレイヤーのみが呼び出し位置で役割を果たします。
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo,
}
obj.foo(); // 2
- バインディングの表示:呼び出しを実行してバインディングを表示し、関数に適用します
function foo() {
console.log(this.a);
}
var obj = {
a: 2
};
foo.call(obj);
ディスプレイ製本のハード製本
function foo(something) {
console.log(this.a, something);
return this.a + something;
}
function bind(fn, obj) {
return function() {
return fn.apply(obj, arguments);
};
}
var obj = {
a: 2
}
var bar = bind(foo, obj);
新しいバインディング、新しい関数の呼び出しは、まったく新しいオブジェクトを作成し、このオブジェクトを関数呼び出しのthisにバインドします。
- Newがバインドされている場合、それがnewのハードカバーされた関数である場合、ハードカバーされたこれはnewによって作成されたオブジェクトに置き換えられます。
function foo(a) {
this.a = a;
}
var bar = new foo(2);
console.log(bar.a)
(4)質問:手書きのバインド、適用、呼び出し
// call
Function.prototype.call = function (context, ...args) {
context = context || window;
const fnSymbol = Symbol("fn");
context[fnSymbol] = this;
context[fnSymbol](...args);
delete context[fnSymbol];
}
// apply
Function.prototype.apply = function (context, argsArr) {
context = context || window;
const fnSymbol = Symbol("fn");
context[fnSymbol] = this;
context[fnSymbol](...argsArr);
delete context[fnSymbol];
}
// bind
Function.prototype.bind = function (context, ...args) {
context = context || window;
const fnSymbol = Symbol("fn");
context[fnSymbol] = this;
return function (..._args) {
args = args.concat(_args);
context[fnSymbol](...args);
delete context[fnSymbol];
}
}
// MDN的标准源码
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis || window,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
テストテスト:
Function.prototype.myCall = function (context) {console.log('this',this)}
var obj = {a:1}
aaa.myCall(obj)
// 输出
// this ƒ aaa(obj){alert(obj)}