The introduction

Recently, in js learning, I saw the problem of function overload. At the beginning, I only saw the implementation code. After looking at the code and thinking hard for half an hour, I finally clarified the principle of its implementation, and also felt amazed by its clever implementation. This implementation method is jQuery author John Resig’s implementation of function overloading in “JavaScript Ninja Secrets”. The design is very clever, and I write this article to share with you

What is function overloading

Overloading, simply put, is when functions or methods with the same name and different argument lists are called overloaded functions or methods.

Let’s take a look at the effect

 function addMethod (obj, name, fn) {
        var old = obj[name];
        obj[name] = function () {
            if (fn.length === arguments.length) {
                return fn.apply(this, arguments)
            } else if (typeof old === 'function') {
                return old.apply(this, arguments)
            }
        }
    }

    var person = {userName: 'Bear's little bear'}

    addMethod(person, 'show'.function () {
        console.log(this.userName + '- >' + 'show1')
    })
    addMethod(person, 'show'.function (str) {
        console.log(this.userName + '- >' + str)
    })
    addMethod(person, 'show'.function (a, b) {
        console.log(this.userName + '- >' + (a + b))
    })
    person.show()  
    person.show('bkl')
    person.show(10, 20)
Copy the code

Output result

/ / bear bao small bear -- - > show1 / / bear bao small bear -- - > BKL / / bear bao small bear -- - > 30Copy the code

We add a show method to an object. The show method does something different every time we pass in a different argument

In order to understand the following text, here is an explanation of the fn.length property you may not know, first look at the following code

function fn(a,b,c) {}
fn.length // 3
function fn(a,b,c,d) {}
fn.length // 4
Copy the code

Fn. Legnth is the number of parameters of the function fn when it is defined. Well, let’s move on

The addMethod function, in simple terms, adds a method fn to an object that specifies its name. It uses a closure to store the fn passed in by the variable old, and calls s each time How, depending on the argument passed in, our code may find the fn function passed in several times by old

In order to make this more intuitive, we have made a small change to the addMethod function. In fact, we have added a console.log() function to make it easier to understand how the function is executed

    function addMethod (obj, name, fn) {
        var old = obj[name];
        obj[name] = function() {console.log(1) // Prints 1if(fn.length === arguments.length){console.log(2) // Print 2return fn.apply(this,arguments);
            }else if(typeof old === 'function'){console.log(3) // Prints 3return old.apply(this,arguments);
            }
        }
    }
    addMethod(person, 'show'.function () {
        console.log(this.userName + '- >' + 'show1')
    })
    addMethod(person, 'show'.function (str) {
        console.log(this.userName + '- >' + str)
    })
    addMethod(person, 'show'.function (a, b) {
        console.log(this.userName + '- >' + (a + b))
    })

Copy the code

Now, let’s take a look at the person.show method, and see what happens when the function passes one argument with no arguments, versus two,

  • person.show(10, 20)
1 2 bear ---->30Copy the code

As you can see, when two arguments are passed in, only a 1 and a 2 are printed, and the corresponding execution function is executed. The person.show function has fn as its scope

    function (a, b) {
        console.log(this.userName + '- >' + (a + b))
    }
Copy the code
  • person.show(‘bkl’)
1 3 1 2 Bear ----> BKLCopy the code

Person. show (fn. Length === 2); person.show (fn. Length === 2); person.show (fn. Length === 2)

return old.apply(this,arguments);
Copy the code

What is old at this point? Old in this case is the person. Show method before the following function is executed

    addMethod(person, 'show'.function (a, b) {
        console.log(this.userName + '- >' + (a + b))
    })
Copy the code

After execution, the fn function in the scope of the Person. show function is the following method

    function (str) {
        console.log(this.userName + '- >' + str)
    }
Copy the code
  • person.show()
---->show1Copy the code

Given the output, it is not hard to see that when no arguments are passed, we can find the method all the way up through the closure’s old variable.

    function () {
        console.log(this.userName + '- >' + 'show1')}Copy the code

conclusion

In this way, we concatenate the difference between passing one argument and passing two, using the old variable in the closure. The implementation of JS overload. Again, this is really clever. Beautiful and charming code

If you think it’s ok, please give it a thumbs-up. Thank you!