Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The examples have very different outcomes.</p> <p>Before looking at the differences, the following should be noted:</p> <ul> <li>A constructor's <em>prototype</em> provides a way to share methods and values among instances via the instance's private <code>[[Prototype]]</code> property.</li> <li>A function's <em>this</em> is set by how the function is called or by the use of <em>bind</em> (not discussed here). Where a function is called on an object (e.g. <code>myObj.method()</code>) then <em>this</em> within the method references the object. Where <em>this</em> is not set by the call or by the use of <em>bind</em>, it defaults to the global object (window in a browser) or in strict mode, remains undefined.</li> <li>JavaScript is a object oriented language, i.e. everything is an Object, including functions.</li> </ul> <p>So here are the snippets in question:</p> <pre><code>var A = function () { this.x = function () { //do something }; }; </code></pre> <p>In this case, variable <code>A</code> is assigned a value that is a reference to a function. When that function is called using <code>A()</code>, the function's <em>this</em> isn't set by the call so it defaults to the global object and the expression <code>this.x</code> is effectively <code>window.x</code>. The result is that a reference to the function expression on the right hand side is assigned to <code>window.x</code>.</p> <p>In the case of:</p> <pre><code>var A = function () { }; A.prototype.x = function () { //do something }; </code></pre> <p>something very different occurs. In the first line, variable <code>A</code> is assigned a reference to a function. In JavaScript, all functions objects have a <em>prototype</em> property by default so there is no separate code to create an <em>A.prototype</em> object.</p> <p>In the second line, <em>A.prototype.x</em> is assigned a reference to a function. This will create an <em>x</em> property if it doesn't exist, or assign a new value if it does. So the difference with the first example is which object's <em>x</em> property is involved in the expression.</p> <p>Another example is below. It's similar to the first one (and may be what you meant to ask about):</p> <pre><code>var A = new function () { this.x = function () { //do something }; }; </code></pre> <p>In this example, the <code>new</code> operator has been added before the function expression so that the function is called as a constructor. When called with <code>new</code>, the function's <em>this</em> is set to reference a new Object whose private <code>[[Prototype]]</code> property is set to reference the constructor's public <em>prototype</em>. So in the assignment statement, the <code>x</code> property will be created on this new object. When called as a constructor, a function returns its <em>this</em> object by default, so there is no need for a separate <code>return this;</code> statement.</p> <p>To check that <em>A</em> has an <em>x</em> property:</p> <pre><code>console.log(A.x) // function () { // //do something // }; </code></pre> <p>This is an uncommon use of <em>new</em>, since the only way to reference the constructor is via <em>A.constructor</em>. It would be much more common to do:</p> <pre><code>var A = function () { this.x = function () { //do something }; }; var a = new A(); </code></pre> <p>Another way of achieving a similar result is to use an immediately invoked function expression:</p> <pre><code>var A = (function () { this.x = function () { //do something }; }()); </code></pre> <p>In this case, <code>A</code> assigned the return value of calling the function on the right hand side. Here again, since <em>this</em> is not set in the call, it will reference the global object and <code>this.x</code> is effectively <code>window.x</code>. Since the function doesn't return anything, <code>A</code> will have a value of <code>undefined</code>.</p> <p>These differences between the two approaches also manifest if you're serializing and de-serializing your Javascript objects to/from JSON. Methods defined on an object's prototype are not serialized when you serialize the object, which can be convenient when for example you want to serialize just the data portions of an object, but not it's methods:</p> <pre><code>var A = function () { this.objectsOwnProperties = "are serialized"; }; A.prototype.prototypeProperties = "are NOT serialized"; var instance = new A(); console.log(instance.prototypeProperties); // "are NOT serialized" console.log(JSON.stringify(instance)); // {"objectsOwnProperties":"are serialized"} </code></pre> <p><strong>Related questions</strong>:</p> <ul> <li><a href="https://stackoverflow.com/questions/186244/what-does-it-mean-that-javascript-is-a-prototype-based-language"><strong>What does it mean that JavaScript is a prototypal language?</strong></a></li> <li><a href="https://stackoverflow.com/questions/235360/what-is-the-scope-of-a-function-in-javascriptecmascript"><strong>What is the scope of a function in JavaScript?</strong></a></li> <li><strong><a href="https://stackoverflow.com/questions/3127429/javascript-this-keyword">How does the &quot;this&quot; keyword work?</a></strong></li> </ul> <p><strong>Sidenote:</strong> There may not be any significant memory savings between the two approaches, however using the prototype to share methods and properties will likely use less memory than each instance having its own copy.</p> <p>JavaScript isn't a low-level language. It may not be very valuable to think of prototyping or other inheritance patterns as a way to explicitly change the way memory is allocated.</p>
 

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