What’s the difference? How does it work?
The call takes multiple arguments. The first argument is the function context (this), followed by arguments to the function itself.
let obj = {
name: "A"
}
functionAllName (firstName, lastName) {console.log(this) console.log(' my full name is"${firstName}${this.name}${lastName}"')} // The allName function has no name attribute.'I am'.'front end') // My full name is "I am the front end" this refers to window allname.call (obj,'I am'.'front end') // My full name is "I am a front-end" this refers to objCopy the code
apply
Apply takes two arguments. The first argument is the function context, this, and the second argument is the function argument that is simply passed in as an array.
allName.apply(obj, ['I am'.'front end'])// My full name is "I am a front-end" this refers to objCopy the code
bind
Bind receives multiple arguments. The first is the bind return value. The return value is a function context called this, which is not immediately executed.
let obj = {
name: "A"
}
functionAllName (firstName, lastName, flag) {console.log(this) console.log(' my full name is"${firstName}${this.name}${lastName}"My motto is"${flag}"')} allname.bind (obj) // Not executedlet fn = allName.bind(obj)
fn('I am'.'front end'.'Study hard and make progress every day') // This can also be used. Parameters can be passed separately.bindFn = allname.bind (obj);"Are you")
fn('front end'.'Study hard and make progress every day')
Copy the code
Then rub your hands together to implement call, apply, and bind
To realize the call
let Person = {
name: 'Tom'.say() {console.log(this) console.log(' my name is${this.name}Person.say() Person1 = {name:'Tom1'} // We try to implement this to Person1 using the native call method person.say.call (Person1)Copy the code
Through the first print execution and the second print execution I found that if Person1 has a say method then Person1 directly executes person1.say () and the result is that I am Tom1. Yes, that’s how call is implemented. Look at the code
Function.prototype.MyCall = function(context) {//context is Person1 in the demo // the function that must call MyCall at this point is the say method, So all we need to do is extend the say method on the context to point to the say method that calls MyCall so this console.log(this) context.say = this // MyCall and this inside of MyCall is our virtual say method Context.say ()} // Test person.say.myCall (Person1)// My name is Tom1Copy the code
let Person = {
name: 'Tom'.say() {console.log(this) console.log(' my name is${this.name}`)
}
}
Person1 = {
name: 'Tom1'} // If there is no argument person.say.call ()Copy the code
This is not specified. This points to window
We need to do the same
Function.prototype.MyCall = function(context) {/ / if no parameters we refer to the call handling context = context | | the window / / Person1 / / must call at this time of the context is the demo MyCall function method is to say, So we just need to extend a say method on the context pointing to the say method that called MyCall so this context.say = this // this inside MyCall is our virtual say method context.say()} Person.say.MyCall()Copy the code
// Find fault 2: By default we define context.say = this fn if it is already occupied. Say should be a unique value. Symbol fn = Symbol() for es6functionMySymbol (obj) {mySymbol(obj) {mySymbol(obj)letUnique = (math.random () + new Date().getTime()).toString(32).slice(0, 8if (obj.hasOwnProperty(unique)) {
returnMySymbol (obj)}else {
returnUnique}} / / now we the multi-parameter and execution of the deleted along with all the custom method removed a fix Function. The prototype. MyCall1 =function(context) {/ / if not preach or has a value of null object context window context = context | | windowletFn = mySymbol(context) context[fn] = thisletArg = [...arguments].slice(1) arg = [...arguments].slice(1) //[... Arg) // fn delete context[fn]let Person = {
name: 'Tom', say(age) {console.log(this) console.log(' my name is${this.name}I this year${age}`)
}
}
Person1 = {
name: 'Tom1'} person.say.call (Person1,18)// My name is Tom1Copy the code
The results were perfect!
To realize the apply
And then apply is a little bit easier, because when you have multiple arguments the second argument is an array, so I’m not going to go through the details.
Function.prototype.myApply = function(context) {// The object context points to window if there is no passed or the passed value is emptyif (typeof context === "undefined" || context === null) {
context = window
}
letFn = mySymbol(context) context[fn] = thisletArg = [...arguments].slice(1) //[... XXX] Slice returns a new array context[fn](arg) // execute fn delete context[fn] // delete method}Copy the code
To realize the bind
Call (1); bind (2); bind (3); bind (3); bind (4);
Function.prototype.bind = function(context) {// Return a function bound to this, where we need to save thisletSelf = this // can support currie pass parameters, save parametersletArg = [...arguments].slice(1) // Return a functionreturn function() {// We need to get the storage parameters again because we support the currie formatletNewArg = [...arguments] console.log(newArg) // Return function bound to this, pass two saved arguments // consider the return function to have the return value donereturn
returnSelf.apply (context, arg.concat(newArg))}} // Fix the testlet fn = Person.say.bind(Person1)
fn()
fn(18)
Copy the code
Yes, perfect, implement this binding, return function, do not execute immediately, can be currie form passed parameters. Corey related to explain in detail please click: segmentfault.com/a/119000001…
The simplified version of the implementation is complete
Welcome to ridicule or like!