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!