Use of 'Prototype' Vs. 'This' in JavaScript

JavaScript: When to use a Class vs. a prototype?

So, what is the difference between using a class vs. a prototype like below and when do you use either approach?

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.

Defining methods via prototype vs using this in the constructor - really a performance difference?

See http://jsperf.com/prototype-vs-this

Declaring your methods via the prototype is faster, but whether or not this is relevant is debatable.

If you have a performance bottleneck in your app it is unlikely to be this, unless you happen to be instantiating 10000+ objects on every step of some arbitrary animation, for example.

If performance is a serious concern, and you'd like to micro-optimise, then I would suggest declaring via prototype. Otherwise, just use the pattern that makes most sense to you.

I'll add that, in JavaScript, there is a convention of prefixing properties that are intended to be seen as private with an underscore (e.g. _process()). Most developers will understand and avoid these properties, unless they're willing to forgo the social contract, but in that case you might as well not cater to them. What I mean to say is that: you probably don't really need true private variables...

Advantages of using prototype, vs defining methods straight in the constructor?

Methods that inherit via the prototype chain can be changed universally for all instances, for example:

function Class () {}
Class.prototype.calc = function (a, b) {
return a + b;
}

// Create 2 instances:
var ins1 = new Class(),
ins2 = new Class();

// Test the calc method:
console.log(ins1.calc(1,1), ins2.calc(1,1));
// -> 2, 2

// Change the prototype method
Class.prototype.calc = function () {
var args = Array.prototype.slice.apply(arguments),
res = 0, c;

while (c = args.shift())
res += c;

return res;
}

// Test the calc method:
console.log(ins1.calc(1,1,1), ins2.calc(1,1,1));
// -> 3, 3

Notice how changing the method applied to both instances? This is because ins1 and ins2 share the same calc() function. In order to do this with public methods created during construction, you'd have to assign the new method to each instance that has been created, which is an awkward task. This is because ins1 and ins2 would have their own, individually created calc() functions.

Another side effect of creating methods inside the constructor is poorer performance. Each method has to be created every time the constructor function runs. Methods on the prototype chain are created once and then "inherited" by each instance. On the flip side of the coin, public methods have access to "private" variables, which isn't possible with inherited methods.

As for your function Class() {} vs var Class = function () {} question, the former is "hoisted" to the top of the current scope before execution. For the latter, the variable declaration is hoisted, but not the assignment. For example:

// Error, fn is called before the function is assigned!
fn();
var fn = function () { alert("test!"); }

// Works as expected: the fn2 declaration is hoisted above the call
fn2();
function fn2() { alert("test!"); }

__proto__ VS. prototype in JavaScript

__proto__ is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build __proto__ when you create an object with new:

( new Foo ).__proto__ === Foo.prototype
( new Foo ).prototype === undefined

What's the difference between this.function and prototype.function?

Functions on the prototype are only created once and shared between each instance. Functions created in the constructor are created as new objects for each new object created with the constructor.

As a general rule functions should be on the prototype since they will generally not be modified for different objects of the same type, and this has a slight memory/performance benefit. Other properties like objects and arrays should be defined in the constructor, unless you want to create a shared, static property, in which case you should use the prototype.

Its easier to see the distinctions with normal objects or arrays rather than functions

function Foo(){
this.bar = [];
}
var fooObj1 = new Foo();
var fooObj2 = new Foo();

fooObj1.bar.push("x");
alert(fooObj2.bar) //[]

as opposed to:

function Foo(){
}

Foo.prototype.bar = []
var fooObj1 = new Foo();
var fooObj2 = new Foo();

fooObj1.bar.push("x");
alert(fooObj2.bar) //["x"]

this Vs. prototype

Defining a function with whatever = function() { ... } tends to create what's called a "closure", where the function can access local variables of the function that defines it. When you say this.fn = function() { ... }, each object gets an instance of the function (and a new closure). This is often used to create "private" variables in Javascript, but comes with a cost: each function (in each object) is distinct, and takes up more memory.

When you say Rectangle.prototype.fn = function() { ... }, one instance of the function is shared by all Rectangles. This saves memory, and can minimize some memory leaks in browsers that handle closures badly. If you don't need "private" members, or other such access to the defining function's local variables, it's usually a better idea.

JavaScript - The Good Parts: Function prototypes vs Object prototypes

You add a method to the Number prototype, so every Number instance has access to it. In other words, because there's a property called "integer" on the Number prototype, any attempt to access that property from any Number instance will succeed. That's kind-of the whole point of putting properties on a constructor prototype.

When a JavaScript primitive number appears on the left side of a . operator, the language automatically boxes it in a Number instance so that the method call makes sense.

edit — let's look at how that "method" function works. In the call

Number.method( "integer", function() { ... } )

what's going on? Well, inside the "method" function, the "name" parameter is "integer". The function parameter is then assigned as a property of this.prototype. What is this in that invocation of the "method" function? It's the Number constructor function. Thus, the "method" function — which is on the Function prototype, and therefore is available to all function instances, like the Number constructor function for example — adds the given function as a property of the prototype of the constructor function involved.

Why is the "method" property visible as a property of the Number constructor? Because the Number constructor is itself a function. The "method" function was created as a property of the Function prototype, so that means it is visible to every function instance — including the Number constructor.



Related Topics



Leave a reply



Submit