Prototype vs function definition [duplicate] - javascript

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 8 years ago.
Say I have the following Function
function FooController (){
this.foo = function () {
alert('foo');
}
}
FooController.prototype.bar = function () {
alert('bar');
}
Is there a difference between these two syntaxes? Why would I use one over the other? Is there a performance hit?

If it's defined on the prototype, any instance of FooController will "inherit" the bar method because it's in the instance's prototype chain. Only 1 function is defined and in memory using this technique.
If you define using this.foo = function, you're adding the function directly to the instance as a property of that instance. This means that you will have 1 function in memory per instance of the controller.
function FooController {}
FooController.prototype.hello = function() {
console.log("world");
};
Create an instance and check the prototype's value
var c = new FooController();
c.hello(); // "world"
This is as expected, but let's define a hello method directly on the c instance
c.hello = function() { console.log("cats"); };
c.hello(); // "cats"
We can still call the prototype method directly
c.prototype.hello.call(c); // "world"
Or we can delete the hello property on the c instance
delete c.hello;
Now let's call our function again
c.hello; // "world"
It's back to using the prototype's method !

All instances of FooController will share bar, each foo will be created individually per object.
In general you want properties to be created with the this. syntax, so they're not shared, and functions to be created using the prototype syntax (there's no point in many identical functions)
You can run into trouble if you put functions on the prototypes. With primitives you won't notice the difference, since writing to them will write to the local object and ignore the protoype, but you can cause problems with arrays like this.
function FooController (){
this.foo = function () {
alert('foo');
}
}
FooController.prototype.bar = [];
var a = new FooController();
var b = new FooController();
a.bar.push['hi'];
alert(b.bar.length); //1

Related

Property of object not returning the expected value in Javascript [duplicate]

In C++, the language I'm most comfortable with, usually one declares an object like this:
class foo
{
public:
int bar;
int getBar() { return bar; }
}
Calling getBar() works fine (ignoring the fact that bar might be uninitialized). The variable bar within getBar() is in the scope of class foo, so I don't need to say this->bar unless I really need to make it clear that I'm referring to the class' bar instead of, say, a parameter.
Now, I'm trying to get started with OOP in Javascript. So, I look up how to define classes and try the same sort of thing:
function foo()
{
this.bar = 0;
this.getBar = function() { return bar; }
}
And it gives me bar is undefined. Changing the bar to this.bar fixes the issue, but doing that for every variable clutters up my code quite a bit. Is this necessary for every variable? Since I can't find any questions relating to this, it makes me feel like I'm doing something fundamentally wrong.
EDIT: Right, so, from the comments what I'm getting is that this.bar, a property of an object, references something different than bar, a local variable. Can someone say why exactly this is, in terms of scoping and objects, and if there's another way to define an object where this isn't necessary?
JavaScript has no classes class-based object model. It uses the mightier prototypical inheritance, which can mimic classes, but is not suited well for it. Everything is an object, and objects [can] inherit from other objects.
A constructor is just a function that assigns properties to newly created objects. The object (created by a call with the new keyword) can be referenced trough the this keyword (which is local to the function).
A method also is just a function which is called on an object - again with this pointing to the object. At least when that function is invoked as a property of the object, using a member operator (dot, brackets). This causes lots of confusion to newbies, because if you pass around that function (e.g. to an event listener) it is "detached" from the object it was accessed on.
Now where is the inheritance? Instances of a "class" inherit from the same prototype object. Methods are defined as function properties on that object (instead of one function for each instance), the instance on which you call them just inherits that property.
Example:
function Foo() {
this.bar = "foo"; // creating a property on the instance
}
Foo.prototype.foo = 0; // of course you also can define other values to inherit
Foo.prototype.getBar = function() {
// quite useless
return this.bar;
}
var foo = new Foo; // creates an object which inherits from Foo.prototype,
// applies the Foo constructor on it and assigns it to the var
foo.getBar(); // "foo" - the inherited function is applied on the object and
// returns its "bar" property
foo.bar; // "foo" - we could have done this easier.
foo[foo.bar]; // 0 - access the "foo" property, which is inherited
foo.foo = 1; // and now overwrite it by creating an own property of foo
foo[foo.getBar()]; // 1 - gets the overwritten property value. Notice that
(new Foo).foo; // is still 0
So, we did only use properties of that object and are happy with it. But all of them are "public", and can be overwritten/changed/deleted! If that doesn't matter you, you're lucky. You can indicate "privateness" of properties by prefixing their names with underscores, but that's only a hint to other developers and may not be obeyed (especially in error).
So, clever minds have found a solution that uses the constructor function as a closure, allowing the creating of private "attributes". Every execution of a javascript function creates a new variable environment for local variables, which may get garbage collected once the execution has finished. Every function that is declared inside that scope also has access to these variables, and as long as those functions could be called (e.g. by an event listener) the environment must persist. So, by exporting locally defined functions from your constructor you preserve that variable environment with local variables that can only be accessed by these functions.
Let's see it in action:
function Foo() {
var bar = "foo"; // a local variable
this.getBar = function getter() {
return bar; // accesses the local variable
}; // the assignment to a property makes it available to outside
}
var foo = new Foo; // an object with one method, inheriting from a [currently] empty prototype
foo.getBar(); // "foo" - receives us the value of the "bar" variable in the constructor
This getter function, which is defined inside the constructor, is now called a "privileged method" as it has access to the "private" (local) "attributes" (variables). The value of bar will never change. You also could declare a setter function for it, of course, and with that you might add some validation etc.
Notice that the methods on the prototype object do not have access to the local variables of the constructor, yet they might use the privileged methods. Let's add one:
Foo.prototype.getFooBar = function() {
return this.getBar() + "bar"; // access the "getBar" function on "this" instance
}
// the inheritance is dynamic, so we can use it on our existing foo object
foo.getFooBar(); // "foobar" - concatenated the "bar" value with a custom suffix
So, you can combine both approaches. Notice that the privileged methods need more memory, as you create distinct function objects with different scope chains (yet the same code). If you are going to create incredibly huge amounts of instances, you should define methods only on the prototype.
It gets even a little more complicated when you are setting up inheritance from one "class" to another - basically you have to make the child prototype object inherit from the parent one, and apply the parent constructor on child instances to create the "private attributes". Have a look at Correct javascript inheritance, Private variables in inherited prototypes, Define Private field Members and Inheritance in JAVASCRIPT module pattern and How to implement inheritance in JS Revealing prototype pattern?
Explicitly saying this.foo means (as you've understood well) that you're interested about the property foo of the current object referenced by this. So if you use: this.foo = 'bar'; you're going to set the property foo of the current object referenced by this equals to bar.
The this keyword in JavaScript doesn't always mean the same thing like in C++. Here I can give you an example:
function Person(name) {
this.name = name;
console.log(this); //Developer {language: "js", name: "foo"} if called by Developer
}
function Developer(name, language) {
this.language = language;
Person.call(this, name);
}
var dev = new Developer('foo', 'js');
In the example above we're calling the function Person with the context of the function Developer so this is referencing to the object which will be created by Developer. As you might see from the console.log result this is comes from Developer. With the first argument of the method call we specify the context with which the function will be called.
If you don't use this simply the property you've created will be a local variable. As you might know JavaScript have functional scope so that's why the variable will be local, visible only for the function where it's declared (and of course all it's child functions which are declared inside the parent). Here is an example:
function foo() {
var bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(f.getBar()); //'foobar'
This is true when you use the var keyword. This means that you're defining bar as local variable if you forget var unfortunately bar will became global.
function foo() {
bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(window.bar); //'foobar'
Exactly the local scope can help you to achieve privacy and encapsulation which are one of the greatest benefits of OOP.
Real world example:
function ShoppingCart() {
var items = [];
this.getPrice = function () {
var total = 0;
for (var i = 0; i < items.length; i += 1) {
total += items[i].price;
}
return total;
}
this.addItem = function (item) {
items.push(item);
}
this.checkOut = function () {
var serializedItems = JSON.strigify(items);
//send request to the server...
}
}
var cart = new ShoppingCart();
cart.addItem({ price: 10, type: 'T-shirt' });
cart.addItem({ price: 20, type: 'Pants' });
console.log(cart.getPrice()); //30
One more example of the benefits of the JavaScript scope is the Module Pattern.
In Module Pattern you can simulate privacy using the local functional scope of JavaScript. With this approach you can have both private properties and methods. Here is an example:
var module = (function {
var privateProperty = 42;
function privateMethod() {
console.log('I\'m private');
}
return {
publicMethod: function () {
console.log('I\'m public!');
console.log('I\'ll call a private method!');
privateMethod();
},
publicProperty: 1.68,
getPrivateProperty: function () {
return privateProperty;
},
usePublicProperty: function () {
console.log('I\'ll get a public property...' + this.publicProperty);
}
}
}());
module.privateMethod(); //TypeError
module.publicProperty(); //1.68
module.usePublicProperty(); //I'll get a public property...1.68
module.getPrivateProperty(); //42
module.publicMethod();
/*
* I'm public!
* I'll call a private method!
* I'm private
*/
There's a little strange syntax with the parentless wrapping the anonymous functions but forget it for the moment (it's just executing the function after it's being initialized). The functionality can be saw from the example of usage but the benefits are connected mainly of providing a simple public interface which does not engages you with all implementation details. For more detailed explanation of the pattern you can see the link I've put above.
I hope that with this :-) information I helped you to understand few basic topics of JavaScript.
function Foo() {
this.bar = 0;
this.getBar = function () { return this.bar };
}
When you call the function above with the new keyword - like this...
var foo = new Foo();
... - a few things happen:
1) an object is created
2) the function is executed with the this keyword referencing that object.
3) that object is returned.
foo, then, becomes this object:
{
bar: 0,
getBar: function () { return this.bar; }
};
Why not, then, just do this:
var foo = {
bar: 0,
getBar: function () { return this.bar; }
};
You would, if it's just that one simple object.
But creating an object with a constructor (that's how it's called) gives us a big advantage in creating multiple of the "same" objects.
See, in javascript, all functions are created with a prototype property [an object], and all objects created with that function (by calling it with the new keyword) are linked to that prototype object. This is why it's so cool - you can store all common methods (and properties, if you wanted to) in the prototype object, and save a lot of memory. This is how it works:
function Foo( bar, bob ) {
this.bar = bar;
this.bob = bob;
}
Foo.prototype.calculate = function () {
// 'this' points not to the 'prototype' object
// as you could've expect, but to the objects
// created by calling Foo with the new keyword.
// This is what makes it work.
return this.bar - this.bob;
};
var foo1 = new Foo(9, 5);
var foo2 = new Foo(13, 3);
var result1 = foo1.calculate();
var result2 = foo2.calculate();
console.log(result1); //logs 4
console.log(result2); //logs 10
That's it!
To get closer to OOP in JavaScript, you might want to take a look into a Module design pattern (for instance, described here).
Based on the closure effect, this pattern allows emulating private properties in your objects.
With 'private' properties you can reference them directly by its identifier (i.e., no this keyword as in constructors).
But anyway, closures and design patterns in JS - an advanced topic. So, get familiar with basics (also explained in the book mentioned before).
In javascript this always refers to the owner object of the function. For example, if you define your function foo() in a page, then owner is the javascript object windows; or if you define the foo() on html element <body>, then the owner is the html element body; and likewise if you define the function onclick of element <a>, then the owner is the anchor.
In your case, you are assigning a property bar to the 'owner' object at the begining and trying to return the local variable bar.
Since you never defined any local varialbe bar, it is giving you as bar is undefined.
Ideally your code should have defined the variable as var bar; if you want to return the value zero.
this is like a public access modifier of objects(variables or functions), while var is the private access modifier
Example
var x = {};
x.hello = function(){
var k = 'Hello World';
this.m = 'Hello JavaScript';
}
var t = new x.hello();
console.log(t.k); //undefined
console.log(t.m); //Hello JavaScript

Why are methods always added to the prototype and not defined in the constructor function? [duplicate]

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 6 years ago.
Most guides on JavaScript explain object creation using constructor functions as follows:
let Person = function (fn, ln) {
this.fn = fn;
this.ln = ln;
};
Person.prototype.greet = function () {
console.log("hello "+ this.fn+ " "+ this.ln)
};
That is: fields are defined in the constructor function while methods are added to the prototype.
Now I understand that the properties defined inside the constructor function will form N copies for N instances, while those on the prototype will have 1 copy shared among all N instances. So it makes sense that properties are defined inside the constructor, as we obviously don't want the copies to be sharing mutable properties like arrays etc.
What I don't get is why the methods aren't defined in the constructor function too. Like this:
let Person = function (fn, ln) {
this.fn = fn;
this.ln = ln;
this.greet = function () {
console.log("hello "+ this.fn+ " "+ this.ln)
};
};
I understand that it will result in there being a copy for each instance and the methods belonging to the object itself rather than its parent/prototype, but is there any particular downside to it?
It just seems a lot more coherent and similar to Ruby etc. style-wise.
because if we defined methods in the constructor , a new Function object would be created for every object even though the method has the same code .
data members of the object are a different thing because they are supposed to carry data unique to every object.

Constructor vs Factory functions [duplicate]

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 7 years ago.
Could you explain the difference between setting methods in the constructor and through prototype object? The following code shows these two ways of setting the methods - say_hello and say_bye both work fine:
function MessageClass() {
this.say_bye = function() { alert('see ya'); };
}
MessageClass.prototype.say_hello = function() { alert('hello'); };
x = new MessageClass();
x.say_hello();
x.say_bye();
foxxtrot and annakata are both correct, but I'll throw in my 2 cents.
If you use the prototype then each instance of the "MessageClass" is really referencing the same functions. The functions exist in memory only once and are used for all instances. If you declare the methods in the constructor (or otherwise add it to a specific instance) rather than the prototype then a new function is created for each instance of MessageClass.
That being said, there is probably not any noticeable performance difference for most cases and it is unlikely that you will see a memory usage difference either. I would go with the prototype method unless you have a compelling reason to do otherwise. The only reason I can thing that you might want to declare a method in the constructor is if you need a closure. For example, if you have event handlers or you wanted to simulate private properties with getters/setters you might do:
function MessageClass() {
var self = this;
this.clickHander = function(e) { self.someoneClickedMe = true; };
var _private = 0;
this.getPrivate = function() { return _private; };
this.setPrivate = function(val) { _private = val; };
}
EDIT: Because there has been discussion about how this effects objects extended by another object with functions assigned in the constructor I'm adding a bit more detail. I might use the term "class" to simplify the discussion, but it is important to note that js does not support classes (that doesn't mean we can't do good OO development) or we would not be discussing this issue.
Most javascript libraries call the constructor on the base class and the sub class. (e.g. Prototype.js's Object.extend) This means that methods assigned in the constructor of each will be available on the resulting objects. However, if you are extending objects yourself there can be unexpected consequences.
If I take the MessageClass above and extend it:
function ErrorMessageClass() {}
ErrorMessageClass.prototype = new MessageClass();
errorMsg = new ErrorMessageClass();
Then errorMsg will have a getPrivate and setPrivate method on it, but they may not behave as you would expect. Because those functions were scoped when they were assigned (i.e. at "ErrorMessageClass.prototype = new MessageClass()" not only are the get/setPrivate methods shared, the _private variable gets shared across all instances of ErrorMessageClass as well. This essentially makes _private a static property for ErrorMessageClass. For example:
var errorA = new ErrorMessageClass();
var errorB = new ErrorMessageClass();
errorA.setPrivate('A');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'A'
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'B'
Likewise with the clickHandler function and someoneClickedMe property:
errorA.clickHandler();
console.log(errorA.someoneClickedMe); // prints 'true'
console.log(errorB.someoneClickedMe); // prints 'true'
However, change those function definitions to use this._private:
this.getPrivate = function() { return this._private; };
this.setPrivate = function(val) { this._private = val; };
and behavior of instances of ErrorMessageClass becomes more of what you would expect:
errorA.setPrivate('A');
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'B'
If you bind methods by prototype JS only has to do it once and binds to an object class (which makes it elligible for OO JS extensions).
If you do the binding within the "class" function, JS has to do the work of creating and assigning for each and every instance.
The difference is when you derive a class from Message Class. Only the methods declared on the prototype will be available on child classes of Message.

Idiomatic Javascript Coding Style - when to declare functions on the prototype vs inside the function constructor [duplicate]

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 9 years ago.
In Javascript, when I want to declare a 'publicly' accessible function what is the idiomatic approach?
MyObj.prototype.foo = function() {
...
}
or
function MyObj() {
this.foo = function() {
...
}
}
What situations would determine one style over the other?
What are the advantages of one over the other?
Thanks a bunch for the help!
The core difference
When a method declared on the prototype it's shared among all instances created by invoking the function as a constructor.
//assuming the first kind
var a = new MyObj();
var b = new MyObj();
//a and b both have the _same_ foo method
On the other hand, when it's created inside the class, each gets its own instance of the function.
//assuming the second kind
var a = new MyObj();
var b = new MyObj();
//a and b both have the _different_ foo methods
When it matters
Creating things on the prototype is useful for sharing functionality. It's faster than giving each instance its own copy of the method. However, if the construction creates closure the function will have access to it.
You can only access the closure of the creation in the second version
function MyObj(x) {
var y = x;
this.foo = function() {
console.log(y);
}
}
This is not possible in the first version. While this seems silly in this example sometimes closures are very useful. However, since the function now has access to the closure, even if it doesn't use it - it'll be slower. This is insignificant in 99% of cases but in performance intensive situations it might matter.

What is the best way of defining a class in javascript [duplicate]

This question already has answers here:
How can I emulate "classes" in JavaScript? (with or without a third-party library) [closed]
(7 answers)
Closed 10 years ago.
I have searched for a way of defining a class in javascript like in java or php but I found none!
I want something like
class javascriptClass {
function someFunction(){}
}
You can use a prototype class, like so:
function MyClass() {
}
MyClass.prototype.method1 = function() {
// do stuff
};
MyClass.prototype.method2 = function(p) {
// do stuff
};
var myClass = new MyClass();
Now, after instantiating an object myClass from the prototype MyClass, you can access the methods of the object myClass:
myClass.method1();
The above method is great if you need to instantiate more than one object/instance of the class.
If you only expect to have one object, then another method you can use simply acts as a namespace to protect your functions from collisions with others:
var myObject = {
method1: function() {
// do stuff
},
method2: function(p) {
// do stuff
}
};
myObject.method1();
In JavaScript, you don't have classes as such. You define functions that are used to create objects with new, and you can give them methods by either creating them in the body of the constructor, or adding them through the object's prototype. For example:
function JavaScriptClass() {
// I am a JavaScript constructor! Any initialization can be done here.
}
// This is the prototype! You can put instance methods and variables (to an extent) here.
JavaScriptClass.prototype.someFunction = function() {
alert('someFunction was called!');
};
// Now, let's create an instance!
var obj = new JavaScriptClass();
obj.someFunction(); // someFunction was called!
And you can access the current object using this, in both the constructor and any methods bound to the object. Note that this can also be bound to just about anything in JavaScript. It's a different type of OOP.
Unlike class-based languages, JavaScript is functional languages or prototypal language, you can't use class keyword or the kind of signature you have posted in JavaScript. In JavaScript, normally you would do:
function Person(){
// public members
this.foo = 'foo';
this.walk = function(){ ......... }
// private members
var bar = 'bar';
var baz = function(){.........}
}
var person = new Person();

Categories