www.webdeveloper.com
+ Reply to Thread
Page 1 of 2 1 2 LastLast
Results 1 to 15 of 22
  1. #1
    Join Date
    Jul 2007
    Posts
    245

    Exclamation Function property versus this

    Hello everyone. I'm testing a way I've seen to cache the results of a function within the function itself. But there's a thing I don't understand. First, this is the function:

    PHP Code:
    function isPrimenum ) {
      if (
    isPrime.cache[num] != null) return isPrime.cache[num];
      var 
    prime num != 1// Everything but 1 can be prime
      
    for ( var 2numi++ ) {
        if ( 
    num == ) {
          
    prime false;
          break;
        }
      }
      
    isPrime.cache[num] = prime;
      return 
    prime;
    }

    isPrime.cache = {}; // defining the function property

    isPrime(5); // returns the calculated value (true)
    isPrime(5); // returns the value (true) from cache
    isPrime.cache[5]; // A way to directly access the cached value 
    Well, the question is:
    why this won't work if I replace isPrime with this within the function? It gives an error like "Cannot set property '5' of undefined". I can't still grasp the difference. this is the function itself, and isPrime is the function too!

  2. #2
    Join Date
    Jul 2011
    Posts
    24
    Code:
    function isPrime( num ) { 
      	alert(this===window)//alerts true
       } 
    isPrime( 3 )
    this equals window Not isPrime
    Code:
    function isPrime( num ) { 
      	this.obj = this;
       } 
    
    a = new isPrime;
    alert(a == a.obj)//alerts true
    in this case this is equal to a Not isPrime
    Last edited by DaveyErwin; 09-20-2012 at 07:46 PM.

  3. #3
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,773
    Quote Originally Posted by Jazztronik View Post
    this is the function itself, and isPrime is the function too!
    isPrime and arguments.callee refer to the function itself. i don't think i've ever seen "this" refer to the actual surrounding function...

    "this" always refers to the object holding the function, in your case window.
    you can specify "this" using .call(), .bind(), and .apply(), and [].map() and [].filter() accept a 2nd argument that sets "this" within the mapped function.
    but again, "this" never really refers to the function itself.

    you can say something like this.isPrime.cache[7], but if you want "this" set to an object, you need an object.
    not to make it more confusing, but a function is an object, so it can have methods as properties, and within whose methods, "this" will refer to the function being used as an object: String.fromCharCode(), Date.parse() Array.isArray(), etc. these are not the same as prototype methods, those used w/ "new ", which have "this" bound to a blank object.
    Last edited by rnd me; 09-20-2012 at 10:55 PM.

  4. #4
    Join Date
    Jul 2007
    Posts
    245
    Hello, thanks for your replies! This is where I got the code by the way: http://ejohn.org/apps/learn/#21 (you may edit it on the fly for testing)

    I think one of the things that confused me about what this refers to is the constructors, like this:

    PHP Code:
    function Foo() {
        
    this.name 'foo';

    Quote Originally Posted by rnd me View Post
    you can say something like this.isPrime.cache[7]
    Using this.isPrime.cache[7] generates an error "Cannot set property 'cache' of undefined".

    ok, now I think I see it anyway. But still there are tests I've made that confuse me. I've added a log(this) within the function, and in the previous case the output was [object Window]. Window is the containing object of the function (the context of the function). No problem at this point, it's just as you said.

    If I do this instead of the previous calls:

    PHP Code:
    var checkPrime = new isPrime(5); 
    the output is [object Object], which as I understand after your last paragraph, is the function object, that is isPrime, isn't it? However I can't do this.cache within the function either.

  5. #5
    Join Date
    Jul 2011
    Posts
    24
    Quote Originally Posted by Jazztronik View Post

    If I do this instead of the previous calls:

    PHP Code:
    var checkPrime = new isPrime(5); 
    the output is [object Object], which as I understand after your last paragraph, is the function object, that is isPrime, isn't it? However I can't do this.cache within the function either.
    No it is not isPrime,
    it is checkPrime

  6. #6
    Join Date
    Jul 2007
    Posts
    245
    Quote Originally Posted by DaveyErwin View Post
    No it is not isPrime,
    it is checkPrime
    This really confuses me more. I thought checkPrime would be just a reference to the object isPrime... but you say that, so I must be totally wrong. I'm afraid of becoming even more confused.

  7. #7
    Join Date
    Jul 2007
    Posts
    245
    A simple question to rule out one of the things I was confused about, and I think I have clear thanks to your examples:

    PHP Code:
    function foo() {
       
    console.log(this);
    }

    /* 
    calling foo as a regular function
    this === window (the function is being executed within the context in which has been put into)
    */
    foo(); 

    /*
    calling foo as a constructor (creating a new object obj) 
    this === obj (the function is being executed within the obj context)
    */
    var obj = new foo(); 
    Is this correct?
    Last edited by Jazztronik; 09-21-2012 at 11:25 AM.

  8. #8
    Join Date
    Jul 2011
    Posts
    24
    var checkPrime = new isPrime(5);

    Quote Originally Posted by Jazztronik View Post
    This really confuses me more. I thought checkPrime would be just a reference to the object isPrime... but you say that, so I must be totally wrong. I'm afraid of becoming even more confused.
    checkPrime is not a reference to isPrime
    checkPrime is a newly created object

  9. #9
    Join Date
    Jul 2011
    Posts
    24
    Quote Originally Posted by Jazztronik View Post
    A simple question to rule out one of the things I was confused about, and I think I have clear thanks to your examples:

    PHP Code:
    function foo() {
       
    console.log(this);
    }

    /* 
    calling foo as a regular function
    this === window (the function is being executed within the context in which has been put into)
    */
    foo(); 

    /*
    calling foo as a constructor (creating a new object obj) 
    this === obj (the function is being executed within the obj context)
    */
    var obj = new foo(); 
    Is this correct?
    when calling foo as a constructor
    this will refer to the newly
    created object so yes
    i beleive
    calling foo as a constructor (creating a new object obj)
    this === obj (the function is being executed within the obj context)
    is a correct statement

  10. #10
    Join Date
    Jul 2007
    Posts
    245
    Thanks for your help!

    So, having that part of context clear, there is something still clouding my comprehension.

    Going back to the first example, why if I do

    PHP Code:
    var checkPrime = new isPrime(5); 
    this within isPrime() refers to an object called checkPrime instead of isPrime? I thought checkPrime would be a variable referencing an object. So if I do this:

    PHP Code:
    var testPrime checkPrime
    am I copying the object instead of referencing the same?

  11. #11
    Join Date
    Jul 2011
    Posts
    24
    Quote Originally Posted by Jazztronik View Post
    Thanks for your help!

    So, having that part of context clear, there is something still clouding my comprehension.

    Going back to the first example, why if I do

    PHP Code:
    var checkPrime = new isPrime(5); 
    this within isPrime() refers to an object called checkPrime instead of isPrime? I thought checkPrime would be a variable referencing an object. So if I do this:

    PHP Code:
    var testPrime checkPrime
    am I copying the object instead of referencing the same?
    Code:
     
    function isPrime(){var greet="hiyas";}
     checkPrime = isPrime;
     alert(checkPrime)//alerts function isPrime(){var greet="hiyas";}
    so it seems
    checkPrime and isPrime
    refference the same object
    here is proof that is true
    (get ready for some real confusion)
    Code:
    function isPrime(){var greet="hiyas";}
     checkPrime = isPrime;
     alert(checkPrime)//alerts function isPrime(){var fareWell="seeya";}
    
    
    
     function isPrime(){var fareWell="seeya";}
    Last edited by DaveyErwin; 09-21-2012 at 05:29 PM.

  12. #12
    Join Date
    Mar 2011
    Posts
    52
    Since function declarations are executed before other statements, the conclusion from above example doesn't seem right to me.
    The javascript interpreter runs it like:
    Code:
    function isPrime(){var greet="hiyas";}
    function isPrime(){var fareWell="seeya";}
     checkPrime = isPrime;
    alert(checkPrime) //alerts function isPrime(){var fareWell="seeya";}
    this within isPrime() refers to an object called checkPrime instead of isPrime? I thought checkPrime would be a variable referencing an object.
    >>> this within isPrime() refers to an 'anonymous' (can't really call it anonymous, since we have a reference to it) object, which is refered to by the variable checkPrime.
    When call isPrime as a constructor, using the 'new' keyword it creates an instance of an object.

    Code:
    var testPrime = checkPrime;
    am I copying the object instead of referencing the same?
    >>> It doesn't create a copy, but a reference.
    Code:
    function Base(val){
     this.val = val;
    };
    var a = new Base('AAA');
    var b = a;
    b.val = 'BBB';
    alert(a.val); // BBB
    Another way to create a function with cache is to wrap it into a closure:
    Code:
    var isPrime = (function(){
     var cache = [];
     function isPrime(num){
      if(cache[num] != null){
       return cache[num];
      }
      var prime = num != 1; // Everything but 1 can be prime
      for(var i=2; i<num; i++){
       if(num % i == 0){
        prime = false;
        break;
       }
      }
      cache[num] = prime;
      return prime;
     }
     return isPrime;
    }());

  13. #13
    Join Date
    Jul 2011
    Posts
    24
    Thank you for the very clear
    explanation it has removed
    all confusion.

  14. #14
    Join Date
    Jul 2007
    Posts
    245
    Thanks Kever!

    So, summarizing, and please correct me if I'm wrong:

    1 - Variables are references actually. The exception is when using primitive types (integer, float, boolean, string). I'm still not sure of the last statement (language mess in my head).

    2 - "this" references:

    a - the container object when a function is called as usually, the Window object in this case.

    b - using the "new" keyword: an object which is referenced by the instance name (checkPrime). I still haven't clear the object. I've just made this test:

    PHP Code:
    function isPrimenum ) {
      
    console.log(this);
      ......
    }

    var 
    checkPrime = new isPrime(5); // console: isPrime 
    So the referenced object would be isPrime, but again: why can't I use "this" to access its properties, such as isPrime.cache? I already have it clear if I use isPrime as a normal function, since this would refer to Window, but not when used as a constructor
    Last edited by Jazztronik; 09-22-2012 at 05:00 AM.

  15. #15
    Join Date
    Mar 2011
    Posts
    52
    That console is a little confusing. The referenced object is an instance of the isPrime constructor. A contructor could be seen as a template to create objects.

    PHP Code:
    function Person(name){
     
    this.name name;
     
    console.log(this.name// when john is created, this refers to the john object/instance, when lucy is created it points to the lucy object
    };

    var 
    john = new Person('John'); // john = {name: 'John'}
    var lucy = new Person('Lucy'); // lucy = {name: 'Lucy'}

    // a constructor also has a prototype chain, in which properties shared by all instances are stored.
    // Person.prototype, and also the inherited Function.prototype and Object.prototype.
    // Only if a property is not on the constructor, it will be looked for down the prototype chain

    Person.prototype.sayHello = function(){console.log('Hello, I\'m ' this.name)}; // this points to object/instance which is calling sayHello

    // john = {name: 'John', sayHello: Person.prototype.sayHello}
    // lucy = {name: 'Lucy', sayHello: Person.prototype.sayHello}

    john.sayHello() // Hello, I'm John
    lucy.sayHello() // Hello, I'm lucy

    john.sayHello = function(){console.log('Howdy, I\'m ' this.name)};
    Person.prototype.sayHello = function(){console.log('Hello, I\'m ' this.name '!!!!!')}; // this won't overwrite john.sayHello, it does overwrite lucy.prototype.sayHello

    // john = {name: 'John', sayHello: function(){console.log('Howdy, I\'m ' + this.name)}}
    // lucy = {name: 'Lucy', sayHello: Person.prototype.sayHello}

    john.sayHello() // Howdy, I'm John
    lucy.sayHello() // Hello, I'm lucy!!!!! 

Thread Information

Users Browsing this Thread

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

     

Bookmarks

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