使用法
1.申し込む
apply
2 つのパラメータを受け入れます。最初のパラメータはthis
ポインタで、2 番目のパラメータは関数によって受け入れられ、配列の形式で渡されるパラメータです。
this
元の関数はポインタを変更した直後に実行されますが、このメソッドではthis
ポインタを一時的に 1 回だけ変更します。
文法:
func.apply(thisArg, [argsArray])
thisArg: 関数の実行時に this が指すオブジェクト、必須
argsArray: 関数の実行時に渡されるパラメーター、配列形式、オプション
例:
function fn (a,b,c) {
console.log(this.name)
console.log(a, b, c)
}
let obj = {name: '科比'}
fn.apply(obj, [1,2,3])
// 输出 科比 1 2 3
2.電話
apply
同様に、ポインタthis
を変更すると元の関数がすぐに実行されますが、このメソッドは一時的にthis
ポインタを 1 回変更するだけです。
違いは、apply で渡されるパラメータは配列形式である必要があるのに対し、call にはこの制限がないことです。
文法:
func.call(thisArg[, args1, args2, args3,....])
thisArg: 関数の実行時に this が指すオブジェクト、必須
args1 など: 関数の実行時に渡されるパラメーター、オプション
例:
function fn (a,b,c) {
console.log(this.name)
console.log(a, b, c)
}
let obj = {name: '科比'}
fn.call(obj, 1, 2, 3)
// 输出 科比 1 2 3
3.バインド
バインド メソッドは call に非常によく似ています。最初のパラメータもthis
を指し、後で渡されるものはパラメータ リストです (ただし、このパラメータ リストは複数回渡すことができます)。
ポインタを変更した後this
、すぐには実行されませんが、this
ポインタを永続的に変更する関数が返されます。
文法:
func.bind(thisArg[, args1, args2, args3,....])
function fn (a, b, c, d) {
console.log(this.name)
console.log(a, b, c, d)
}
let obj = {name: '科比'}
let bindFn = fn.bind(obj, 1, 2, 3)
bindFn('bind') // 输出 科比 1 2 3 'bind'
bind
この例から、新しい関数が返され、新しい関数の実行時にthis
ポイントされobj
、bind
渡されたパラメータが新しい関数の呼び出し時に渡されたパラメータとマージされ、一緒に新しい関数に渡されることがわかります。
手書きの実装:
上記の apply、call、bind の使用法から知ることができます。
apply、call、bind はすべて apply を指します。これにより this が変更される可能性があります
。Call は呼び出された関数を実行し、bind は新しい関数を返します。
apply の 2 番目のパラメータには配列が必要ですが、call と binding はデータ型を制限しません。残りのパラメータも一緒に関数に渡します。Bind は、新しい関数の呼び出し時に渡されたパラメータもマージして、それらを関数に渡します。新しい機能。
これらはすべて Function プロトタイプにバインドされています。
手書きで実装する方法を見てみましょう。なぜなら、それらはすべて Function プロトタイプにバインドされているからです。
1.申し込む
Function.prototype.apply = function (context, args) {
// 不传默认是全局,window
context = context || window
// args不传时默认是空数组,防止下面用spread操作符时报错
args = args ? args : []
// 把this存到context.fn,这里的this是调用的函数
context.fn = this
// 执行调用的函数,this指向context,参数用spread操作符扩展
const res = context.fn(...args)
// 删除,不污染context
delete context.fn
// 返回res
return res
}
function fn (a,b,c) {
console.log(this.name)
console.log(a, b, c)
}
let obj = {name: '码上游'}
fn.apply(obj, [1,2,3])
// 输出 码上游 1 2 3
2.電話
call は apply と同じです。主な理由は、パラメーターが apply とは異なるためです。少し変更するだけです。
コードは以下のように表示されます。
Function.prototype.call = function (context, ...args) {
// 不传默认是全局,window
context = context || window
// args不传时默认是空数组,防止下面用spread操作符时报错
args = args ? args : []
// 把this存到context.fn,这里的this是调用的函数
context.fn = this
// 执行调用的函数,this指向context,参数用spread操作符扩展
const res = context.fn(...args)
// 删除,不污染context
delete context.fn
// 返回res
return res
}
これは主にcall
関数の 2 番目のパラメータを取得するargs
ときに使用されspread操作符
、残りのすべてのパラメータを args に取得でき、その他はすべて同じです。
function fn (a,b,c) {
console.log(this.name)
console.log(a, b, c)
}
let obj = {name: '科比'}
fn.call(obj, 1, 2, 3)
// 输出 科比 1 2 3
3.バインド
Bind は異なります。新しい関数を返します。この新しい関数は、演算子を使用して呼び出したり、コンストラクターとして使用したりできるnew
ため、ここで区別する必要があります。
Function.prototype.bind = function (context, ...args) {
// 不传默认是全局,window
context = context || window
// 把this存到fn,这里的this是调用的函数
let fn = this
return function newFn (...fnArgs) {
let res
// 要考虑新函数是不是会当作构造函数
if (this instanceof newFn) {
// 如果是构造函数则调用new 并且合并参数args,fnArgs
res = new fn(...args, ...fnArgs)
} else {
// 当作普通函数调用 也可以用上面定义的_call
res = fn.call(context, ...args, ...fnArgs)
}
return res
}
}
確認する
function fn (a, b, c, d) {
console.log(this.name)
console.log(a, b, c, d)
}
let obj = {name: '科比'}
let bindFn = fn.bind(obj, 1, 2, 3)
bindFn('bind') // 输出 科比 1 2 3 'bind'
let bindFn = fn.bind(obj, 1, 2, 3)
let instance = new bindFn()
instance.constructor === fn // true