www.webdeveloper.com
Results 1 to 9 of 9

Thread: null & this : issues

  1. #1
    Join Date
    Feb 2010
    Location
    London
    Posts
    17

    null & this : issues

    Hi - I came across two sets of code which I was finding problem understanding and was wondering if someone
    could help me out, I have marked the first set with my own comments.

    As I understand 'null' in the Object context yields an error, so is this an errata or I am missing something.



    f.apply(o, [1,2]); // this I understand

    For example, to find the largest number in an array of numbers, you
    could use the apply() method to pass the elements of the array to the
    Math.max() function:


    var biggest = Math.max.apply(null, array_of_numbers); // can someone explain 'null' in this context

    ----------------------------------------------------------

    Also in the following set of code, the 'this' keyword I am not entirely sure how it is used.
    As I understand the points below are relevant to the code that follows :
    1. Methods have one very important property: the object through which a method is invoked becomes the value of the this keyword within the body of the method.
    2. When a function is invoked as a function rather that as a method, the this keyword refers to the global object.
    3. Confusingly, this is true even when a nested function is invoked (as a function) within a containing method that was invoked as a method: the this keyword has one value in the containing function but (counterintuitively) refers to the global object within the body of the nested function.


    So if I am right in my thinking, the 'this' keyword below is referring to the 'global' Object and hence binding the 'Window' Object with the function 'f'.


    // Return a function that invokes the function f with the
    // specified arguments and also any additional arguments that are
    // passed to the returned function. (This is sometimes called "currying".)

    function bindArguments(/* function */ f /*, initial arguments... */) {
    var boundArgs = arguments;
    return function() {
    // Build up an array of arguments. It starts with the previously
    // bound arguments and is extended with the arguments passed now
    var args = [];
    for(var i = 1; i < boundArgs.length; i++)
    args.push(boundArgs[i]);
    for(var i = 0; i < arguments.length; i++)
    args.push(arguments[i]);

    // Now invoke the function with these arguments
    return f.apply(this, args);
    }
    }

    [COLOR="rgb(65, 105, 225)"]thanking in advance,
    Naz[/COLOR]

  2. #2
    Join Date
    Feb 2006
    Posts
    2,927
    Apply and call require an object for the first parameter-
    you would get an error with method.apply(true,[]),
    for instance, because a boolean is not of type 'object'-
    but null is, and satisfies the function definition.

    You can use any object, if you do not use it (as this) in the applied method.
    I usually pass an object that relates to the method- in your example, I'd call
    Math.max.apply(Math,[1,2,3,4,5,6]), but that is just personal style.

    You can use window, document, any object- unless the method needs the object:
    Code:
        Date.fromUTCArray=function(arr){
            var D= new Date;
            while(arr.length < 7) arr.push(0);
            var T= arr.splice(3, arr.length);
            D.setUTCFullYear.apply(D, arr);
            D.setUTCHours.apply(D, T);
            return D;
        }

  3. #3
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    Quote Originally Posted by mrhoo View Post
    Apply and call require an object for the first parameter-
    you would get an error with method.apply(true,[]),
    for instance, because a boolean is not of type 'object'-
    but null is, and satisfies the function definition.
    i get no errors on any of these:
    Code:
    Math.max.apply(false,[1,2,3,4,5,6]) //==6
    Math.max.apply(/reg/,[1,2,3,4,5,6]) //==6
    Math.max.apply(undefined ,[1,2,3,4,5,6]) //==6
    Math.max.apply("",[1,2,3,4,5,6]) //==6
    the first argument just sets the value of "this" within the function being called or applied. Math.max doesn't use "this", so it doesn't care what you set it.

    methods that use "this" internally DO care.
    the argument shifter (methodizer pattern) is a typical example of when the first argument matters:
    Code:
     [].slice.call(arguments,1)
    a utc time parser is not:
    Code:
    Date.fromUTCArray=function(arr){
       return  new Date(Date.UTC.apply(0,arr));
    }
    Last edited by rnd me; 02-05-2010 at 11:19 AM.

  4. #4
    Join Date
    Feb 2006
    Posts
    2,927
    You are right, rnd_me- if the argument is a primitive value, it is converted to its wrapper object.
    Thanks for pointing it out.

  5. #5
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    Quote Originally Posted by mrhoo View Post
    if the argument is a primitive value, it is converted to its wrapper object.
    it's the bane of a functional programmer's existence:

    Code:
    alert([0].map(function(){
      return [this, typeof this, this==4, this===4];
    }, 4));
    which shows "4,object,true,false"

  6. #6
    Join Date
    Feb 2010
    Location
    London
    Posts
    17
    thanks for your responses, at first I did not understand but after studying carefully I understood the first part :
    Math.max.apply(null, array_of_numbers);

    But as for the second case :
    return f.apply(this, args);

    Am I correct in assuming that this' here refers to the global object, which on client side would be the window.

    - thanking in advance,
    Naz.

  7. #7
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    Quote Originally Posted by mnaseersj View Post
    But as for the second case :
    return f.apply(this, args);

    Am I correct in assuming that this' here refers to the global object, which on client side would be the window.
    assume nothing, "this" cannot be determined based on what you posted.

    It would depend on where you executed that line of code. Given the use of the word "return", i assume it's in a function. Inside a function, "this" can be about anything; you can specify it by using .call or .apply to execute the function. If that function were a method, "this" would refer to the bound object. In an event, "this" would be the element bound to the event.


    Given, no objects, no use of "new", and no .call or .apply, "this" will refer to the global object, available as "window" like you mentioned.

  8. #8
    Join Date
    Feb 2010
    Location
    London
    Posts
    17
    I was referring to my first post in which

    // Return a function that invokes the function f with the
    // specified arguments and also any additional arguments that are
    // passed to the returned function. (This is sometimes called "currying".)

    function bindArguments(/* function */ f /*, initial arguments... */) {
    var boundArgs = arguments;
    return function() {
    // Build up an array of arguments. It starts with the previously
    // bound arguments and is extended with the arguments passed now
    var args = [];
    for(var i = 1; i < boundArgs.length; i++)
    args.push(boundArgs[i]);
    for(var i = 0; i < arguments.length; i++)
    args.push(arguments[i]);

    // Now invoke the function with these arguments
    return f.apply(this, args);
    }
    }

    But I am learning more through reading everyones replies since their elaborating things which are not covered in so much depth or coming from a different angle and compliment my first JS text book that I am reading (Javascript : The Definitive Guide, 5th Ed. @ p145 ).

    But you know sometimes I feel like but then when I come back to it at a different time I usually crack it, though at times I find I have no option but to post it here, and I find people are quite friendly here and it's a superb site and a great resource for all manner of technologies in one place. I have to give credit to everyone involved here.

    - Naz.

  9. #9
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    Quote Originally Posted by mnaseersj View Post
    I was referring to my first post in which

    // Return a function that invokes the function f with the
    // specified arguments and also any additional arguments that are
    // passed to the returned function. (This is sometimes called "currying".)
    still, "this" is unbound in the example you posted. It is passed along, without being set. This lets you use call and apply on the wrapper function later, and if the original wrapped function made use of "this", it would get the expected value through the wrapper.

    by the way, you can code a curry simpler:
    Code:
    function bindArguments(/* function */ f /*, initial arguments... */) {
        var boundArgs=[].slice.call(arguments,1);
       return function bound() {
            return f.apply(this, boundArgs.concat([].slice.call(arguments)));
        };
    }
    i prefer the Function prototype version, which itself currys the first argument of bindArguments():


    Code:
    Function.prototype.bindArguments=function bindArguments(/* initial arguments... */) {
        var f=this, boundArgs=[].slice.call(arguments);
       return function bound() {
            return f.apply(this, boundArgs.concat([].slice.call(arguments)));
        };
    }

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles