usage
1.apply
apply
Accepts two parameters, the first parameter is this
the pointer, and the second parameter is the parameter accepted by the function, passed in in the form of an array
The original function will be executed immediately after changing this
the pointer, and this method only temporarily changes this
the pointer once.
grammar:
func.apply(thisArg, [argsArray])
thisArg: the object pointed to by this when the function is running, required
argsArray: the parameters passed when the function is running, in array form, optional
example:
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
Like apply
the same, this
the original function will be executed immediately after changing the pointer, and this method only temporarily changes this
the pointer once.
The difference is that the parameters passed in apply must be in array form, while call does not have this restriction.
grammar:
func.call(thisArg[, args1, args2, args3,....])
thisArg: the object pointed to by this when the function is running, required
args1, etc.: parameters passed when the function is running, optional
example:
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
The bind method is very similar to call. The first parameter also this
points to , and what is passed in later is also a parameter list (but this parameter list can be passed in multiple times)
After changing this
the pointer, it will not be executed immediately, but will return a this
function that permanently changes the pointer.
grammar:
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'
It can be seen from the example that a new function is returned, pointed to bind
when executing the new function , and then the parameters passed in are merged with the parameters passed in when the new function is called, and passed together to the new functionthis
obj
bind
Handwritten implementation:
You can know from the above apply, call, bind usage:
Apply, call, and bind all point to apply, which can change this
. Call will execute the called function, and bind returns a new function.
The second parameter of apply requires an array, while call and bind do not limit the data type. It will pass the remaining parameters to the function together. Bind will also merge the parameters passed in when the new function is called and pass them to the new function.
They are all bound to the Function prototype.
Let’s see how to implement it by handwriting. Because they are all bound to the Function prototype.
1.apply
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
call is the same as apply. The main reason is that the parameters are different from apply. Just make small changes;
code show as below:
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
}
It is mainly used when call
obtaining the second parameter of the function , so that all remaining parameters can be obtained into args, and everything else is the same.args
spread操作符
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
Bind is different. It returns a new function. This new function can be called or used as a constructor using new
operators, so a distinction needs to be made here.
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
}
}
verify
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