What exactly is different about these 2 objects, a created using a constructor, b using a closure?
Is the property __proto__ useful for anything that cannot be achieved by using a closure? Am I supposed to use these techniques in different situations? Is there a difference in memory usage?
(jsFiddle)
window.MODULE = {};
MODULE.constructor = function(){
this.publicVariable = 10;
};
MODULE.constructor.prototype.publicMethod = function(){
return this.publicVariable;
};
//-------------------------------//
MODULE.closure = (function(){
var publicMethod = function(){
return this.publicVariable;
};
return function(){
var obj = {};
obj.publicVariable = 10;
obj.publicMethod = publicMethod;
return obj;
};
}());
//-------------------------------//
var a = new MODULE.constructor();
console.log("constructor", a.publicMethod(), a)
var b = MODULE.closure();
console.log("closure", b.publicMethod(), b)
Also see a more complicated jsFiddle comparison with some private and static properties - both techniques work the same as far as I can tell...
Roughly, the main advantages of prototypal inheritance (your "constructor" method) are makes it easier to do subclasses and monkeypatching (adding methods to an existing class) while closures are nice if you want private instance variables and methods ("protected methods" are still hard to do with either method) or prefer lexical scoping instead of dynamic scoping with "this" (useful if someone does setTimeout(obj.method, 1000))
As for performance, prototypal inheritance can be a bit more efficient because implementations are tuned to it but it really shouldn't matter unless you instantiate lots of objects from that class.
Private variable example:
var counter = function(){
var count = 0; //private variable
var increment = function(){ // private method
count ++;
};
return { //public interface
next: function(){
increment();
return count;
},
}
}
var c = counter();
console.log(c.next());
console.log(c.next());
If we skip the advantages of OOP approach, difference between a and b is that b has own method publicMethod, when a inherits this method from it's prototype:
a.hasOwnProperty('publicMethod'); // false
b.hasOwnProperty('publicMethod'); // true
Note, that __proto__ property is non-standard and not supported in IE < 11. Alternatively you may use ES5 feature Object.getPrototypeOf(a).
Also note naming conventions it JavaScript1:
UPPER_CASE is used for constants, when globals usually use PascalCase, so your MODULE should be Module;
constructors use PascaleCase too, so your MODULE.constructor should be Module.Constructor.
More on prototype, inheritance, overriding and calling super here: https://stackoverflow.com/a/16063711/1641941
MODULE={};
MODULE.constructor = function(){
this.publicVariable = 10;
};
MODULE.constructor.prototype=(function(){
var privateMethod=function(){
console.log("I'm private");
};
return {
publicMethod : function(){
//going to call "private" method
privateMethod();
return this.publicVariable;
}
};
}());
var c = new MODULE.constructor();
c.publicMethod();
To have instance specific "private" member values you have to give up prototype because you have to define all functions accessing these values in the constructor function body instead of on the prototype. I personally think it's silly to forcefully implement something that is not supported by JavaScript (private instance specific variables) and by doing so giving up something that is supported by JavaScript (prototype).
By supported I mean that JS engines will optimise your code for it.
Related
I've heard that one of the advantages of closures is the ability to create private properties for objects as follows.
function Func2(){
//A is a closure, kept alive after the Func2 has returned,
//After Func2 returns, A is only accessible by getA and setA (it's "private")
var A = 100;
return {
getA: function(){
return A;
},
setA: function(newA){
A = newA;
}
}
}
You can get and set the private property A of an object created with Func2 using the getter and setter functions...
var obj2 = Func2();
obj2.getA();
obj2.setA(200);
But what's the point of that if I can do the same thing using a regular constructor function?
function Func1(){
var A = 100; //A is a private property of any object created with the Func1 constructor
this.getA = function(){
return A;
};
this.setA = function(newA){
A = newA;
};
}
Accessing the private properties is done the same way...
var obj1 = new Func1()
obj1.getA();
obj1.setA(200);
As others have pointed out in the comments, a closure is created in both cases, and both will work.
I think the reason that the return approach is recommended for the module pattern is that the module pattern does not make use of Javascript's prototype chain, so it's unnecessary to use a regular constructor function that would create a new prototype (which isn't needed and would waste memory). In your example, objects created by Func2 would just have the default prototype of Object.prototype, whereas objects created by Func1 would have a prototype of Func1.prototype which in turn would have the prototype Object.prototype. Also, Func2 has the advantage that it will work with or without the new keyword (although it's best to avoid the new keyword if you're using the module pattern for the reasons I mentioned above). (I have seen some programmers complain about the fact that if a programmer forgets the new keyword in traditional OO Javascript, it can cause hard-to-detect bugs; I personally have never found this to be an issue though).
Another approach to private variables, as you're probably aware, is to simply prefix them with _, e.g.:
function Func1() {
this._A = 100;
}
Func1.prototype = {
constructor: Func1,
getA: function(){
return this._A;
},
setA: function(newA){
this._A = newA;
}
};
Personally I prefer this over the module pattern - the main goal of private variables is communication to other programmers, i.e. "this is an internal property; don't access it directly" - and the underscore prefix is a well-known convention. Private properties have never really been about 100% preventing access to those properties, just discouraging it (consider the fact that most programming languages allow you to access private properties using reflection if you really want to). And also, simply prefixing with an underscore allows you to easily have "protected" properties in addition to private ones (useful for sub-types / sub-classes). Making use of the prototype chain is also more memory-efficient, because you don't have multiple copies of the same functions for each instance.
But I do realize that in spite of the simplicity of the underscore naming convention, some programmers still prefer using the module pattern to really make private properties inaccessible from outside the closure. If you want to do that, then I'd recommend using the traditional module pattern, using the return statement as in your first example.
Another pattern you could consider, if you prefer to stick with the module pattern but still want to declare public properties as you go along (rather than in a return statement at the end), would be to create a new object and use that instead of this, e.g.:
function Func3(){
var obj = {};
var A = 100;
obj.getA = function(){
return A;
};
obj.setA = function(newA){
A = newA;
};
return obj;
}
(By the way, for private methods, as opposed to private data properties, the underscore prefix isn't a necessity even if you're using the prototypal approach. The code sample in this answer is an example of this.)
I've seen in some tests that using prototype methods increases the performance of the code execution and reduces the memory consumption, since methods are created per class, not per object.
At the same time I want to use the module pattern for my class, since it looks nicer and allows to use private properties and methods.
The layout of the code is like the following:
var MyClass = function() {
var _classProperty = "value1";
var object = {
classProperty : _classProperty
};
object.prototype = {
prototypeProperty = "value2"
}
return object;
}
But the prototype in this case doesn't work. I've found that the reason is that prototypes are set for the functions, not the object. So I suppose that I should use object.__proto__.prototype instead of just object.prototype. But the __proto__ is not supported by all browsers and doesn't comply to ECMAScript5 rules.
So is there a better way to use prototypes in the module pattern object constructor?
The prototype property is the one you have to set on constructor functions. And the module pattern uses an IEFE (for local variables), which returns the "class" constructor.
var MyClass = (function() {
var _classProperty = "value1";
function MyClass() {
this.instanceProperty = …;
…
}
MyClass.prototype.prototypeProperty = "value2";
…
return MyClass;
})();
Then:
var instance = new MyClass;
console.log(instance.instanceProperty);
console.log(instance.prototypeProperty);
You have to set the prototype of your constructor function:
var MyClass = function() {
var _classProperty = "value1";
this.classProperty = _classProperty;
};
MyClass.prototype = {
prototypeProperty : "value2"
};
var instance = new MyClass();
console.log(instance.classProperty); //value1
console.log(instance.prototypeProperty); //value2
FIDDLE
EDIT
This is not an implementation of the module pattern but the constructor pattern. Neverless, it allows for private properties and methods (as far as JavaScript allows for that). But if your goal really was to implement the module pattern, take a look at Bergi's answer.
What are the basic ways of defining reusable objects in Javascript? I say reusable to exclude singleton techniques, such as declaring a variable with object literal notation directly. I saw somewhere that Crockford defines four such ways in his book(s) but I would rather not have to buy a book for this short bit of information.
Here are the ways I'm familiar with:
Using this, and constructing with new (I think this is called classical?)
function Foo() {
var private = 3;
this.add = function(bar) { return private + bar; }
}
var myFoo = new Foo();
Using prototypes, which is similar
function Foo() {
var private = 3;
}
Foo.prototype.add = function(bar) { /* can't access private, correct? */ }
Returning a literal, not using this or new
function Foo() {
var private = 3;
var add = function(bar) { return private + bar; }
return {
add: add
};
}
var myFoo = Foo();
I can think of relatively minor variations on these that probably don't matter in any significant way. What styles am I missing? More importantly, what are the pros and cons of each? Is there a recommended one to stick to, or is it a matter of preference and a holy war?
Use the prototype. Returning specific objects from constructors makes them non-constructors, and assigning methods to this makes inheritance less convenient.
Returning an object literal
Pros:
If a person forgets new, they still get the object.
You can create truly private variables, since all methods of the object defined inside the constructor share its scope.
Cons:
It’s not a real constructor. Adding something to its prototype won’t change the returned objects, new or no new. new Foo() instanceof Foo would also result in false.
Using prototype
Pros:
You leave the constructor uncluttered.
This is the standard way of doing things in JavaScript, and all built-in constructors put their methods on their prototypes.
Inheritance becomes easier and more correct; you can (and should) use Object.create(ParentConstructor.prototype) instead of new ParentConstructor(), then call ParentConstructor from within Constructor. If you want to override a method, you’re able to do it on the prototype.
You can “modify” objects after they’ve already been created.
You can extend the prototypes of constructors you don’t have access to.
Cons:
It can get to be a bit too verbose, and if you want to change the function’s name, you have to change all of the functions added to the prototype, too. (Either that or define the prototype as one big object literal with a compatible property descriptor for constructor.)
They don’t share an instance-specific scope, so you can’t really have private variables.
Assigning to this.* in the constructor
Pros:
You can use closures and therefore private member variables.
Cons:
No duck typing; you can’t call a method right off of the prototype with any old object. For example, Array.prototype.slice.call(collectionLikeObject).
It's mostly a matter of preference. There's no one way to make Chicken Noodle soup, and uniform objects are the same way.
I don't use any of those 3, although they all work for their own purposes. I use a custom function called Object:deploy, and use it like this..
var a = { hey: 'hello' },
b = {}.deploy(a);
console.log(b.hey); // 'hello'
Using prototype is the best for most people because of automatic trickling.
function A() {};
A.prototype.hello = "Hey";
var a = new A();
console.log(a.hello); // 'Hey'
A.prototype.hello = "Hello";
console.log(a.hello); // 'Hello'
And contrary to popular belief, you can use private variables in prototype.
function Hello() {};
(function () {
var greeting = "Hello";
Hello.prototype.greet = function () { return greeting };
}).apply(this);
But even though that's possible, it's usually better to do..
function Hello() {};
Hello.prototype.greeting = "Hello";
Hello.prototype.greet = function () { return this.greeting };
Well the second approach (prototype) is more similar to standard classes in other languages like Python, in that you have a common "prototype" object which all instances are sharing. To compare the first and second approaches:
In approach 1, every time you call "new Foo()", you are creating a brand new object and inserting all the methods. This isn't very time or space efficient, since each Foo instance will have its own table of all the methods. You can test this by creating two Foo objects, and asking foo1.add == foo2.add (false). Approach 3 is very similar to this; I'm not sure what the semantic difference (if any) there is between approaches 1 and 3.
In approach 2, you have set up a shared prototype object containing all the methods. If you ask foo1.add == foo2.add, you get true. This is more space- and time-efficient. It also lets you add more methods to the prototype after creating instances, and they will see the new methods.
The problem with approach 2, as you say, is that you can't access the private members. But you can still add non-private members to the object itself, and access those using the prototype methods:
function Foo() {
this.private = 3;
}
Foo.prototype.add = function(bar) { return this.private + bar }
A caveat is that foo.private is visible externally.
The prototype one doesn't have a per object instance overhead only a per class overhead for the add function. This alone is the reason why I don't like the other two approaches.
Do not forget about inheritance. Some day you'll need. And for organizing inheritance the best approach is combined technic:
function Foo() {
this.array = [1, 2, 3];
this.add = function(bar) { return private + bar; }
}
Foo.prototype.add = function(bar) { }
var myFoo = new Foo();
Setting fields in constructor is useful to avoid modifying them by children objects.
Setting methods to prototype is faster then doing this every time in constructor.
I've been fiddling around a bit with the prototype and closure patterns in Javascript. As you might know, there's a performance penalty when using the closure pattern because it redefines the same functions for every instance of an object. However, the closure pattern does allow for private variables, which makes encapsulation easier.
Here's a typical example of the prototype pattern:
function Foo(val) {
this.val = val;
}
Foo.prototype.getVal = function() {
return this.val;
}
var f = new Foo(42);
I was thinking, why can't you do something like this?
function Parent() {
}
Parent.prototype.getVal = function() {
return this.val;
}
function foo(val) {
function Obj {
this.val = val;
}
Obj.prototype = new Parent();
return new Obj();
}
var f = foo(42); // Note the missing 'new'
This allows for private variables in the foo() function, and you can even dynamically set the prototype in the foo() function.
I made a jsperf.com test which indeeds shows a big difference in performance, but i don't know why.
The difference in performance is most likely beacuse you are creating two objects instead of one. You are creating one extra object just to use as prototype for the other.
If you want to create a lot of objects like this, you should just create one prototype object and use it as prototype for all objects that you create.
I found the following code somewhere, but I am not understanding the code properly.
ArticleVote.submitVote('no');return false;
Is ArticleVote a class and submitVote() a function of that class?
Or what does the above code mean? And is there any concept of classes and objects in jQuery or in traditional JavaScript? How to create them? Please share some reference links or code.
Everything is an object in JavaScript
As opposed to other purportedly pure OOP languages. Functions are objects too, but they may just as well be constructor of objects.
var ObjectCreator = function () {
};
The above is a function which if called appropriately, creates an object. Called appropriately means that you have to use the new operator:
var obj = new ObjectCreator;
So while JavaScript does not have classes per se, has means to emulate that behavior. For example:
class Foo {
public void bar() {}
}
Foo foo = new Foo();
is equivalent to the following JS code:
var Foo = function () {
// constructor
};
Foo.prototype.bar = function () {}
var foo = new Foo;
Inheritance is different
The real difference comes when you want to use inheritance, which is a different type of inheritance (prototypal). So, given two pseudo-classes Foo and Bar, if we want Bar to extend from Foo, we would have to write:
var Foo = function () {};
var Bar = function () {};
Bar.prototype = new Foo; // this is the inheritance phase
var bar = new Bar;
alert(bar instanceof Foo);
Object literals
While constructor functions are useful, there are times when we only need only one instance of that object. Writing a constructor function and then populate its prototype with properties and methods is somehow tedious. So JavaScript has object literals, which are some kind of hash tables, only that they're self-conscious. By self-conscious I mean that they know about the this keyword. Object literals are a great way to implement the Singleton pattern.
var john = {
age : 24,
isAdult : function () {
return this.age > 17;
}
};
The above, using a constructor function would be equivalent to the following:
var Person = function (age) {
this.age = age;
};
Person.prototype.isAdult = function () {
return this.age > 17;
};
var john = new Person(24);
What about that prototype thingy
As many have said, in JavaScript objects inherit from objects. This thing has useful aspects, one of which may be called, parasitic inheritance (if I remember correctly the context in which Douglas Crockford mentioned this). Anyway, this prototype concept is associated with the concept of prototype chain which is similar to the parent -> child chain in classical OO languages. So, the inheritance stuff. If a bar method is called on a foo object, but that object does not have a bar method, a member lookup phase is started:
var Baz = function () {};
Baz.prototype.bar = function () {
alert(1);
};
var Foo = function () {};
Foo.prototype = new Baz;
var foo = new Foo;
/*
* Does foo.bar exist?
* - yes. Then execute it
* - no
* Does the prototype object of the constructor function have a bar
* property?
* - yes. Then execute it
* - no
* Is there a constructor function for the prototype object of
* the initial construct function? (in our case this is Baz)
* - yes. Then it must have a prototype. Lookup a bar
* member in that prototype object.
* - no. OK, we're giving up. Throw an error.
*/
foo.bar();
Hold on, you said something about parasitic inheritance
There is a key difference between classical OO inheritance and prototype-based inheritance. When objects inherit from objects, they also inherit state. Take this example:
var Person = function (smart) {
this.smart = smart;
};
var Adult = function (age) {
this.age = age;
};
Adult.prototype = new Person(true);
var john = new Adult(24);
alert(john.smart);
We could say that john is a parasite of an anonymous Person, because it merciless sucks the person intelligence. Also, given the above definition, all future adults will be smart, which unfortunately is not always true. But that doesn't mean object inheritance is a bad thing. Is just a tool, like anything else. We must use it as we see fit.
In classical OO inheritance we can't do the above. We could emulate it using static fields though. But that would make all instances of that class having the same value for that field.
Javascript supports objects but not classes - it uses a prototype-based object system.
JavaScript supports object-oriented development
Object-oriented JavaScript
Certainly JS has objects and classes, but it's not exactly a conventional approach.
It's rather a broad question, but there's three main things you want to know about objects and classes in JS:
1). Everything is an object - this famously includes JS's first class functions
2). There are object literals
var myObject = { "foo": 123, "bar": [4,5,6] };
3). Inheritance is prototype based, so creating classes is more a matter of form than function. To get the effect of a class you'd write something like:
function myClass(foo)
{
this.foo = foo;
}
myClass.prototype.myFooMethod = function() {alert(this.foo);}
var myInstance = new myClass(123);
myinstance.myFooMethod(); // alerts 123
For your example it's likely that ArticleVote is an object instance and probably not conceptually a class, and submitVote would be a method of the object. can't tell for sure though, it could be what you'd call a static method in another language.
Yes, JavaScript has impressive support for Object Oriented programming, Objects and functions. In fact, I'm surprised that you have to ask this question! There are a wealth of resources online such as:
http://mckoss.com/jscript/object.htm
http://www.webreference.com/js/column79/
http://www.javascriptkit.com/javatutors/oopjs.shtml
More resources:
http://www.google.com/search?q=object+oriented+programming+javascript
JavaScript frameworks such as jQuery and Prototype could not have been built without this support in JavaScript engines.
You can achieve the above through Javascript, nothing to do with jQuery.
var ArticleVote= {};
ArticleVote.submitVote = function(voteResult) {
console.log(voteResult);
}
function Vote(){
ArticleVote.submitVote('no');
return false;
}
You can use the JavaScript function as class.
ClassUtil = function(param){
privateFunction = function(param){
// Do some thing
return valueParam;
}
this.publicFunction = function(){
var val1 = function1();
if (val1){
return true;
} else{
return false;
}
}
}
function getClass(){
var classUtil = new ClassUtil();
alert(classUtil.publicFunction());
}
There is one public and one private function. You can call public function from out side using object of the class.