What's the difference between
var A = function () { this.x = function () { //do something }; };
and
var A = function () { }; A.prototype.x = function () { //do something };
Prototypes allow you to easily define methods to all instances of a particular object. The beauty is that the method is applied to the prototype, so it is only stored in the memory once, but every instance of the object has access to it.
To answer your question simply, there is no real difference. Straight from the MDN web docs definition: JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance.
'Prototype' helps remove code redundancy which helps boost your app's performance. If you are seeking to optimize resources or memory on your application, you should use prototype .
Well not exactly. Prototypes are a special type of object and exist as a property on function-objects. When we try to access a key on a function-object, JavaScript will look at its prototype property to see if it's there. If not it will go up the prototype-chain to try to find it.
The examples have very different outcomes.
Before looking at the differences, the following should be noted:
[[Prototype]]
property.myObj.method()
) then this within the method references the object. Where this is not set by the call or by the use of bind, it defaults to the global object (window in a browser) or in strict mode, remains undefined.So here are the snippets in question:
var A = function () { this.x = function () { //do something }; };
In this case, variable A
is assigned a value that is a reference to a function. When that function is called using A()
, the function's this isn't set by the call so it defaults to the global object and the expression this.x
is effective window.x
. The result is that a reference to the function expression on the right-hand side is assigned to window.x
.
In the case of:
var A = function () { }; A.prototype.x = function () { //do something };
something very different occurs. In the first line, variable A
is assigned a reference to a function. In JavaScript, all functions objects have a prototype property by default so there is no separate code to create an A.prototype object.
In the second line, A.prototype.x is assigned a reference to a function. This will create an x property if it doesn't exist, or assign a new value if it does. So the difference with the first example in which object's x property is involved in the expression.
Another example is below. It's similar to the first one (and maybe what you meant to ask about):
var A = new function () { this.x = function () { //do something }; };
In this example, the new
operator has been added before the function expression so that the function is called as a constructor. When called with new
, the function's this is set to reference a new Object whose private [[Prototype]]
property is set to reference the constructor's public prototype. So in the assignment statement, the x
property will be created on this new object. When called as a constructor, a function returns its this object by default, so there is no need for a separate return this;
statement.
To check that A has an x property:
console.log(A.x) // function () { // //do something // };
This is an uncommon use of new since the only way to reference the constructor is via A.constructor. It would be much more common to do:
var A = function () { this.x = function () { //do something }; }; var a = new A();
Another way of achieving a similar result is to use an immediately invoked function expression:
var A = (function () { this.x = function () { //do something }; }());
In this case, A
assigned the return value of calling the function on the right-hand side. Here again, since this is not set in the call, it will reference the global object and this.x
is effective window.x
. Since the function doesn't return anything, A
will have a value of undefined
.
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:
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"}
Related questions:
Sidenote: 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With