Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I realize this is an old thread, but I have a solution that is much more elegant, and has few drawbacks apart from the fact that it is not generally done, as I have noticed. </p> <p>Consider the following: </p> <pre><code>var f=function(){ var context=this; } f.prototype.test=function(){ return context; } var fn=new f(); fn.test(); // should return undefined because the prototype definition // took place outside the scope where 'context' is available </code></pre> <p>In the function above we defined a local variable (context). We then added a prototypical function (test) that returns the local variable. As you have probably predicted, when we create an instance of this function and then execute the test method, it does not return the local variable because when we defined the prototypical function as a member to our main function, it was outside the scope where the local variable is defined. This is a general problem with creating functions and then adding prototypes to it - you cannot access anything that was created in the scope of the main function.</p> <p>To create methods that are within the scope of the local variable, we need to directly define them as members of the function and get rid of the prototypical reference:</p> <pre><code>var f=function(){ var context=this; this.test=function(){ console.log(context); return context; }; } var fn=new(f); fn.test(); //should return an object that correctly references 'this' //in the context of that function; fn.test().test().test(); //proving that 'this' is the correct reference; </code></pre> <p>You may be worried that because the methods are not being created prototypically, different instances may not really be data-separated. To demonstrate that they are, consider this: </p> <pre><code>var f=function(val){ var self=this; this.chain=function(){ return self; }; this.checkval=function(){ return val; }; } var fn1=new f('first value'); var fn2=new f('second value'); fn1.checkval(); fn1.chain().chain().checkval(); // returns 'first value' indicating that not only does the initiated value remain untouched, // one can use the internally stored context reference rigorously without losing sight of local variables. fn2.checkval(); fn2.chain().chain().checkval(); // the fact that this set of tests returns 'second value' // proves that they are really referencing separate instances </code></pre> <p>Another way to use this method is to create singletons. More often than not, our javascript functions are not being instantiated more than once. If you know that you will never need a second instance of the same function, then there is a shorthand way to create them. Be warned, however: lint will complain that it is a weird construction, and question your use of the keyword 'new':</p> <pre><code>fn=new function(val){ var self=this; this.chain=function(){ return self; }; this.checkval=function(){ return val; }; } fn.checkval(); fn.chain().chain().checkval(); </code></pre> <p><strong>Pro's:</strong> The benefits to using this method to create function objects are plentiful. </p> <ul> <li>It makes your code easier to read, since it indents the methods of a function object in a way that makes it visually easier to follow. </li> <li>It allows access to the locally defined variables <strong><em>only in methods originally defined in this manner</em></strong> even if you later add prototypical functions or even member functions to the function-object, it cannot access the local variables and whatever functionality or data you store on that level remains safe and inaccessible from anywhere else.</li> <li>It allows a simple and straight-forward way to define singletons.</li> <li>It allows you to store a reference to 'this' and maintain that reference indefinitely.</li> </ul> <p><strong>Con's:</strong> There are some drawbacks to using this method. I don't pretend to be comprehensive :)</p> <ul> <li><strike>Because the methods are defined as members to the object and not prototypes - inheritance can be achieved using member definition but not prototypical definitions.</strike> This is actually incorrect. The same prototypical inheritance can be achieved by acting on <code>f.constructor.prototype</code>. </li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload