Understand Call and apply

  • Similarities: Call and apply are methods that change the direction of the function this and pass in arguments to execute.
  • Differences: Call is used to pass parameters one by one, while apply is used to pass parameters in array.

Here’s an example:

let obj = {
	value: 1
}
function foo(name, age){
	console.log(this.value)
	console.log(name, age)
}
// Change this to obj and pass in the argument
foo.call(obj, 'Xie Bigfoot'.40)	// 1 'Xisha' 40
foo.apply(obj, ['strong forever'.28])	// 1 'yongqiang' 28
Copy the code

call

Analysis:

Imagine if we changed foo to a property of obj and executed obj.foo

let obj = {
    value: 1.foo(){
        console.log(this.value)
    }
}
obj.foo()
Copy the code

When calling, you can place the function on one of the properties of this, execute the function, and delete the property.

The first edition

Call exists in function. prototype based on how call is used, so we started writing the first version and named it Call2.

Function.prototype.call2 = function(ctx) {
    // function this refers to whomever the function is called, so this is the function foo to which we want to change this
    // CTX is the first argument passed when call2 is called.
    ctx.fn = this
    ctx.fn()
    delete ctx.fn
}
// Test it
let obj = {
    value: 1
}
function foo(){
    console.log(this.value)
}
foo.call2(obj)
Copy the code

Print result normal, happy Yia (E ´◡ ‘E)

The second edition

But passing parameters has not been implemented, so what if you need to pass parameters, and the number of parameters is not fixed? You can take values from the Arguments object.

  • To quote an introduction to MDN: Arguments objects are local variables available in all (non-arrow) functions. You can use arguments objects to refer to function arguments in functions. This object contains each argument passed to the function.

Because the arguments [0] to CTX, we need to delete it, the arguments for the class Array, say to delete the first item, I instantly thought of the Array. The prototype. The shift. The call (the arguments), but we implement the call in manual feed, You must no longer call call🤣. Only array. from can be converted to an Array first.

Function.prototype.call2 = function(ctx) {
    let args = Array.from(arguments)
    args.shift()
    ctx.fn = thisctx.fn(... args)delete ctx.fn
}
/ / have a try
let obj = {
    value: 1
}
function foo(name, age){
    console.log(this.value)
    console.log(name, age)
}
foo.call2(obj, 'liu ying'.27)
Copy the code

OK, everything is fine

The third edition

Call also has another property that is bound to the global this by default when the called this is null, adding code to the first line of the function body

ctx = ctx || globalThis	// When CTX is null, CTX points to globalThis
Copy the code
The final version

Finally, if the function has a return value, we write the above is not a bug, must return undefined, so change the code to

Function.prototype.call2 = function(ctx) {
    ctx = ctx || globalThis
    let args = Array.from(arguments)
    args.shift()
    ctx.fn = this
    letres = ctx.fn(... args)delete ctx.fn
    return res
}
Copy the code

Handwriting call is completed at this point, my friend <( ̄ c ̄)y ξ

apply

In fact, the transfer mode of parameters for apply is different from that for call. If takeout is to arrive, the code will be directly pasted at 😁.

The final version
Function.prototype.apply2 = function(ctx, arr = []) {
    ctx = ctx || globalThis
    ctx.fn = this
    letres = ctx.fn(... arr)delete ctx.fn
    return res
}
/ / have a try
let obj = {
    value: 1
}
function foo(name, age){
    console.log(this.value)
    console.log(name, age)
    return 'success'
}
console.log(foo.apply2(obj, ['liu ying'.27]))
// Print the result as 1 'liu Ying' 27 'success'
Copy the code

Well, this content is over here, if there is a mistake or not rigorous place, please be sure to correct, thank 😛.