apply, call and bind on javascript functions - codeproject

Upload: gfgomes

Post on 11-Feb-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/23/2019 Apply, Call and Bind on JavaScript Functions - CodeProject

    1/5

    Articles Web Development Client side scripting JavaScript

    Sander Rossel, 27 Oct 2015 CPOL

    Apply, Call and Bind on JavaScript functions

    Did you know about Apply and Call in JavaScript? Or Bind? They might come in handy!

    Im a bit short on time this week so Ill keep it short. Last week I talked about Prototype in JavaScript, a fundamental JavaScript

    feature that too few programmers know about. Today Id like to talk about a few more features that people either dont know

    about or are confused about, apply(), call() and bind().

    As usual I have the examples on GitHubin the apply-call-bind repository.

    Also, in case you missed it, I have a free Udemy course on ReactJS and Fluxfor you. Only 50, so you best be quick to get it!

    Function invocation

    So lets talk a bit about functions and how they can be invoked. Lets look at a simple function with a simple invocation.

    varsum = function(a, b) {

    returna + b;

    };

    varx = sum(1, 2);

    console.log(x);

    It doesnt get simpler than this and x will have the expected value of 3. Lets make that slightly less simple. We want to be able

    to add an undefined number of numbers! So how would we handle that? How about this?

    varsum = function(numbers) {

    varresult = 0; numbers.forEach(function(n) {

    result += n;

    });

    returnresult;

    };

    varx = sum([1, 2, 3, 4]);

    console.log(x);

    That looks good, right? Unfortunately, invoking the function is now more difficult as we always need an array. What if I told you

    there is another way?

    Remember that this is JavaScript and JavaScript is, well, weird. We can call a function with any number of input parameters we

    want. Too few and our function might fail, too much and the extra parameters will be ignored.There is sense in all this though. Within each function you can inspect the input parameters through an array-like object,

    arguments.

    Lets rewrite the first version of sum, but using the arguments list this time.

    0.00 (No votes)

    ly, Call and Bind on JavaScript functions - CodeProject http://www.codeproject.com/Articles/1043300/Apply-Call-and-Bind-o...

    5 27/10/2015 22:34

  • 7/23/2019 Apply, Call and Bind on JavaScript Functions - CodeProject

    2/5

    varsum = function() {

    returnarguments[0] + arguments[1];

    };

    varx = sum(1, 2);

    console.log(x);

    But if we can do that we can use ANY number of parameters! Arguments is array-like, which mean we can loop through the

    values (it doesnt have a forEach method though).

    varsum = function() {

    varresult = 0;

    vari = 0;

    for(i; i < arguments.length; i++) {

    result += arguments[i];

    }

    returnresult;

    };

    varx = sum(1, 2, 3, 4);

    console.log(x);

    Thats pretty nice! We can now use the same simple syntax for any number, or a variable number, of input parameters. So now

    Im going to be a real pain in the ass We got this nice function that takes any number of parameters in the plain and simplesyntax were used to, but I want to pass in an array!

    Apply

    If I were your manager youd be annoyed at best. I asked for plain and simple syntax, you deliver, and now I want an array after

    all!? Worry not! Your function is awesome and it can stay. What were going to use is a function on the function prototype

    (meaning all function objects have this function defined), apply.

    So that sounded weird Functions have functions? Yes they do! Remember that a function in JavaScript is just an object. To give

    you an idea, this is how it looks.

    myFunc();// Invocation of a function.

    myFunc.someFunc();// Invocation of a function on a function.

    So lets look at this function, apply, which allows you to pass input parameters to any function as an array. Apply has two input

    parameters, the object on which you want to invoke the function (or the object thispoints to in the function) and the array with

    input parameters to the function.

    So lets invoke our function, sum, using apply. Notice that the first parameter can be null as were not invoking sum on an object.

    varx = sum.apply(null, [1, 2, 3, 4]);

    console.log(x);

    So thats awesome, right? Lets look at an example that doesnt use the arguments variable.

    varsteve = {

    firstName: 'Steve',

    lastName: 'Ballmer',

    doThatThing: function(what) {

    console.log(this.firstName + ' '+ this.lastName

    + ': '+ what + '! '+ what + '! '+ what + '!');

    }

    };

    steve.doThatThing.apply(null, ['Developers']);

    steve.doThatThing.apply(steve, ['Developers']);

    So in this example the function doThatThing is just a regular function with a regular named input parameter and we can still

    invoke it using apply. In this case we also need to pass in the first parameter to set this. If we dont specify the first parameter

    firstName and lastName in the function will be undefined.

    ly, Call and Bind on JavaScript functions - CodeProject http://www.codeproject.com/Articles/1043300/Apply-Call-and-Bind-o...

    5 27/10/2015 22:34

  • 7/23/2019 Apply, Call and Bind on JavaScript Functions - CodeProject

    3/5

    We can also put in another variable as first input parameter.

    varsander = {

    firstName: 'Sander',

    lastName: 'Rossel'

    };

    steve.doThatThing.apply(sander, ['Blogs']);

    Thats a bit weird, isnt it? Even though Sander does not have the doThatThing function we can invoke it as if Sander did. This

    can be very useful behavior as well see in the next section!

    Call

    Another function, which looks like apply, is call. Call allows you to simply invoke a function, but makes you specify the object

    which serves as thiswithin the function, much like apply. The only difference between apply and call is the manner in which

    input parameters are supplied. Apply needs an array with values, call needs the values separated by a comma (like regular

    function invocations).

    steve.doThatThing.call(null, 'Developers');

    steve.doThatThing.call(steve, 'Developers');steve.doThatThing.call(sander, 'Blogs');

    So why would you want to do this? It seems it only obfuscates the code Consider the following scenario, you have some

    function that takes a callback as input and invokes it.

    varsomeFunc = function(callback) {

    console.log('this is '+ this);

    callback('This');

    };

    someFunc(steve.doThatThing);

    What will it print? Undefined undefined Sure, when doThatThing is invoked as callback()this

    will be the global Window object.We have three options now Ill discuss two now and Ill give the third in a minute.

    So first we could make it so that thisis not used in the callback. For this wed need to create a closure, or a new function that

    invokes doThatThing on steve as if it were a normal function.

    someFunc(function(what) {

    steve.doThatThing(what);

    });

    It works, but its a lot of bloated code, so we dont really want that. So theres a second option, we allow the thisobject to be

    passed to the someFunc as an input parameter. And then we can invoke the function on that object using call (or apply)!

    varsomeFuncThis = function(callback, thisArg) { callback.call(thisArg, 'This');

    };

    someFuncThis(steve.doThatThing, steve);

    A lot of JavaScript libraries and frameworks, like jQuery and Knockout.js, use this pattern, passing in thisas an optional input

    parameter.

    Bind

    If youve been paying attention youll remember I just said there was a third method to solve our little problem with thisin the

    callback function. Next to apply and call functions also have a bindfunction. Bind is a function that takes an object as input

    parameter and returns another function. The function that is returned invokes the original function with the input object as this

    context. Lets just look at an example.

    someFunc(steve.doThatThing.bind(steve));

    ly, Call and Bind on JavaScript functions - CodeProject http://www.codeproject.com/Articles/1043300/Apply-Call-and-Bind-o...

    5 27/10/2015 22:34

  • 7/23/2019 Apply, Call and Bind on JavaScript Functions - CodeProject

    4/5

    someFunc(steve.doThatThing.bind(sander));

    And it even works if your original thisisnt the function itself.

    varf = steve.doThatThing;

    f = f.bind(steve);

    someFunc(f);

    Youll need this when passing JavaScript native functions as callbacks to third party libraries.

    someFunc(console.log);

    someFunc(console.log.bind(console));

    The first call fails with an Illegal invocation because thisinside the log function has to be console, but it isnt if its invoked as

    callback. The second line works as weve bound thisto console.

    So here are three functions that all invoke a function slightly differently than what youre used to. All three are indispensable

    when youre doing serious JavaScript development though.

    This blog is a bit shorter than usual, but, as they say, its quality over quantity. Hope to see you back again next week!

    Happy coding!

    The post Apply, Call and Bind on JavaScript functionsappeared first on Sander's bits.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    Share

    About the Author

    Sander Rossel is a professional developer with a working experience in .NET (VB and C#, WinForms, MVC, Entity Framework),

    JavaScript and SQL Server.

    He has an interest in various technologies inlcuding, but not limited to, Functional Programming, NoSQL and Software

    Design.

    He seeks to educate others on his blog, Sander's bits - Writing the code you need, and on his CodeProject profile.

    Sander RosselSoftware Developer

    Netherlands

    ly, Call and Bind on JavaScript functions - CodeProject http://www.codeproject.com/Articles/1043300/Apply-Call-and-Bind-o...

    5 27/10/2015 22:34

  • 7/23/2019 Apply, Call and Bind on JavaScript Functions - CodeProject

    5/5

    Permalink| Advertise | Privacy| Terms of Use| Mobile

    Web02 | 2.8.151024.1 | Last Updated 27 Oct 2015Selecione o idioma

    Article Copyright 2015 by Sander Rossel

    Everything else Copyright CodeProject, 1999-2015

    You may also be interested in...

    Bind Object With Functions in

    JavaScript

    Choosing the Right Charting

    Component for Your Enterprise

    Product

    JavaScript Virtual Keyboard Add HTML5 Document Viewer

    to ASP.NET MVC 5 Project

    User Settings Applied SAPrefs - Netscape-like

    Preferences Dialog

    Comments and Discussions

    0 messageshave been posted for this article Visit http://www.codeproject.com/Articles/1043300/Apply-Call-and-

    Bind-on-JavaScript-functions to post and view comments on this article, or click hereto get a print view with messages.

    ly, Call and Bind on JavaScript functions - CodeProject http://www.codeproject.com/Articles/1043300/Apply-Call-and-Bind-o...