Normally I use standard OOP approach based on prototype and my class looks like this
var std = function(){
this.log = function(msg){ console.log("want to be private. " + msg) };
};
std.prototype = {
logInfo: function(msg){
this.log(msg);
}
};
but in that case log is public method and anyone could use it. But I want to make it private, but still available in methods declared in prototype. For that we will need closures. Code will change to this
var closureStd = (function(){
var std = function(){};
var log = function(msg){ console.log("I'm really private, youhooo!" + msg) };
std.prototype = {
logInfo: function(msg){
log(msg);
}
};
return std;
})();
So my question: what is the difference between std and closureStd and what is the price I need to pay to be able to call private methods from prototype?
what is the difference between std and closureStd?
The std constructor creates a new method on every invocation while closureStd does not. You should've made it
function std(){}
std.prototype = {
log: function(msg){ console.log("want to be private. " + msg) },
logInfo: function(msg){ this.log(msg); }
};
And, of course (you already know) the log function in the closureStd is stored in a (private) variable while on the std instance it's accessible (and overwritable) from outside on each instance (or on their prototype). In the closure it's a variable lookup in the scope chain (which can assumed static), while for the method it's a property lookup on an object (and its prototype chain), which might be dynamic but is equally optimized in modern engines.
what is the price I need to pay to be able to call private methods from prototype?
None. The module pattern is common and cheap, variable lookups in a static chain are very fast. I'd rather worry about memory since you're creating so many method instances in the constructor approach.
I also made some tests to measure performance (result's will be in console) and I find that putting class in closure demonstrate better performance compare to put methods in constructor. You also have inheritance options. So for now I don't see disadvantages and will always use class inside closure when I'll need private methods.
Note that the module pattern provided by the link Bondye provided does not hold private instance properties. It works great for function properties since the function would not change for each instance but works a little unpredictable for value properties as the following code demonstrates:
var module = (function () {
// private variables and functions
var foo = 'bar';
// constructor
var module = function (name) {
// instance variables
this.name=name;
};
// prototype
module.prototype = {
constructor: module,
something: function () {
// notice we're not using this.foo
console.log("foo in "+this.name+" is:",foo);
foo="new value";
}
};
// return module
return module;
})();
var m1 = new module("m1");
var m2 = new module("m2");
m1.something();// foo in m1 is: bar
m1.something();// foo in m1 is: new value
m2.something();// foo in m2 is: new value
As you can see in the last line of code both the m1 and m2 instance share a private variable called foo (all instances will point to the same value).
What I could make out from the other link that Bondye posted is that it's hard to simulate privateness in JavaScript and you could consider using a naming convention to indicate properties are private. You can use something like google closure compiler and annotate your JS code to indicate privates; but using closure compiler has it's own disadvantages (used libraries cannot be compiled unless Closure Compiler compatible and code has to be in certain format to be compiled in advanced mode).
Another option is to throw out prototype altogether (at least for everything using the private properties) and put everything in the constructor function's body (or use a function that returns an object).
// function returning an object
function makeObj(name){
// private vars:
var foo = "bar";
return {
name:name,
something:function(){
console.log("foo in "+this.name+" is:",foo);
foo="new value";
}
}
}
var m1=makeObj("m1");
var m2=makeObj("m2");
m1.something();// foo in m1 is: bar
m1.something();// foo in m1 is: new value
m2.something();// foo in m2 is: bar
// constructor with everything in the constructor's body:
function Obj(name){
// private vars:
var foo = "bar";
this.name=name;
this.something=function(){
console.log("foo in "+this.name+" is:",foo);
foo="new value";
}
}
Obj.prototype.someOtherFunction=function(){
// anything here can't access the "private" variables
}
var m1=new Obj("m1");
var m2=new Obj("m2");
m1.something();// foo in m1 is: bar
m1.something();// foo in m1 is: new value
m2.something();// foo in m2 is: bar
One more problem you can run into with using private instance values is that they are only accessible in the instance. When you want to clone an object and define a clone function in your object to create a new instance you have to write public accessor functions to set the private values because you can't set them directly as in Java private fields.
More info on using constructor functions here: Prototypical inheritance - writing up
Related
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
I am trying to understand how "classes" work in ES5 and how I can apply my knowledge of traditional, typed object oriented languages like Java to javascript.
In the following code sample I have commented with my questions.
var MyClass = (function () {
// [What am I?] A private variable?
var myVariable1
// Constructor.
function MyClass() {
// Essentially a public variable.
this.myVariable2 = 0;
}
// Public method returning myVariable1.
MyClass.prototype.myMethod1 = function () {
return myVariable1;
};
// Public method returning public variable.
MyClass.prototype.myMethod2 = function () {
return this.myVariable2;
};
// [What am I?] A private method?
function myMethod3 () {
return 0;
}
return MyClass;
}());
I am mostly wondering about the "private" stuff. Like, what happens if I have multiple instances of this class? Can they interfere with each others private variables and functions?
First I'll address this bit:
...and how I can apply my knowledge of traditional, typed object oriented languages like Java to javascript.
You can frequently get away with thinking of JavaScript as being a bit like Java/C#/etc., but if you do:
It'll bite you at some point, because JavaScript is not like Java/C#/etc., it is fundamentally different even though it has some trappings that make it look similar;
and
You'll miss out on the true power of JavaScript by not knowing how to use its fundamentally-different nature.
How do I know? I did exactly that, came from a Java (and even C++) background and assumed JavaScript was similar, and got bitten, and missed out (initially). :-)
That's not remotely meant as any form of criticism, it's just a word to the wise. Try to learn in depth how JavaScript prototypical inheritance and closures work, and you'll find that the way you solve problems will be slightly different than the way you would in Java/C#/etc.
In Old Environments
Answers to your direct queries inline in this code block, but in 2022 I added a bit below ("In Modern Environments") to address the new modern features recently added to JavaScript to directly address these use cases in different ways.
var MyClass = (function () {
// [What am I?] A private variable?
// ==> A private *class* variable (static variable). Not instance-specific.
var myVariable1
// Constructor.
function MyClass() {
// Essentially a public variable.
// ==> A public field/property/variable, choose your terminology. :-)
// ==> The Java spec calls them both fields and variables (oddly).
// ==> In JavaScript, they're called properties.
this.myVariable2 = 0;
}
// Public method returning myVariable1.
// ==> Correct, but note that myVariable1 is shared across all instances
MyClass.prototype.myMethod1 = function () {
return myVariable1;
};
// Public method returning public variable.
// ==> Yes, note that this one is returning an instance-specific field/property/variable
MyClass.prototype.myMethod2 = function () {
return this.myVariable2;
};
// [What am I?] A private method?
// ==> A private *class* method (static method), yes.
function myMethod3 () {
return 0;
}
return MyClass;
}());
I am mostly wondering about the "private" stuff. Like, what happens if I have multiple instances of this class? Can they interfere with each others private variables and functions?
Yes, as I mentioned in the comments, they're class-wide. If you wanted to have a private "instance field", you'd have to declare it within your constructor, and create any functions that needed to have access to it within the constructor so that they closed over it:
function MyClass(arg) {
var privateInstanceInfo = arg; // We could also just use arg directly
this.accessThePrivateInstanceInfo = function() {
return privateInstanceInfo * 42;
};
}
MyClass.prototype.useOnlyPublicInfo = function() {
// This cannot access `privateInstanceInfo` directly.
// It *can* access the function `accessThePrivateInstanceInfo`
// because that's public:
return accessThePrivateInstanceInfo();
};
var c = new MyClass(2);
console.log(c.useOnlyPublicInfo()); // 84
This is all down to a concept called closures, which is outlined in detail in this question and its answers: How do JavaScript closures work? I'll also reference my article from several years ago Closures are not complicated, which while it uses some older terms for things compared to the latest specification, still describes the concepts just fine.
The inline-invoked function (IIFE) you've used as a wrapper creates a single execution context that all of the functions within it close over. That means they have live access to the variables and functions defined within that context, even after the function returns. Since you only call it once, there's only one context, and so only one myVariable1 and myMethod3.
In my example creating private instance information, we use the fact that a new context is created for each call to the constructor. That context isn't shared with anything else, and so becomes instance-specific.
There's a way to get near-private instance properties without having to define functions in the constructor, which is to use a randomly-selected name:
function makeRandomName() {
var str = "";
while (str.length < 10) {
str += String.fromCharCode(32 + Math.floor(95 * Math.random()));
}
return "__" + str;
}
var MyClass = (function() {
var pseudoPrivatePropName = makeRandomName();
function MyClass() {
this[pseudoPrivatePropName] = 42;
}
// ....
return MyClass;
})();
The code inside the IIFE knows the name of the property, the code outside of it doesn't. Now, malicious code could still find the property, but it's become much more challenging, particularly if you have more than one. (And if you have more than one, you need a better name allocator than the one above.) (Details in this very-outdated article in my blog.)
In ES2015 (ES6) you could use
var pseudoPrivatePropName = Symbol();
...instead of having a name allocator, but it doesn't make the property any more private.
In Modern Environments
In modern environments though, you can use new features that have been added to JavaScript for the ES2022 specification:
Class Public Instance Fields & Private Instance Fields
Private instance methods and accessors
Static class fields and private static methods
Here's how you might right MyClass using those features and ES2015's class syntax:
class MyClass {
// Static class field (class-wide, not instance-specific)
static myVariable1;
// Instance class field (property) (instance-specific)
myVariable2 = 0;
// Private class field (instance-specific)
#privateInstanceInfo;
// Private static class field (class-wide, not instance-specific)
static #privateStaticInfo;
// Constructor for the class
constructor(arg) {
this.#privateInstanceInfo = arg;
}
// Public instance method returning static member
myMethod1() {
// Note that `MyClass.myVariable1` is shared across all instances
return MyClass.myVariable1;
}
// Public instance method return instance field (property) value
myMethod2() {
return this.myVariable2;
}
// Public instance method accessing the private field; all methods declared
// for the class can access it, not just this one
accessThePrivateInstanceInfo() {
return this.#privateInstanceInfo * 42;
}
// Private instance method
#myMethod3() {
return 0;
}
// Static method
static myStaticMethod() {
return this.#getPrivateStaticInfo(); // Or `MyClass.#getPrivateStaticInfo();`
}
// Private static method
static #getPrivateStaticInfo() {
return this.#privateStaticInfo; // Or `MyClass.#privateStaticInfo`
}
}
On those last two, the static method and the private static method, note that usually this during the call will refer to the class constructor itself (MyClass), because usually you're calling static members by doing MyClass.myStaticMethod(). But as usual with this, that's not necessarily true; if you did const f = MyClass.myStaticMethod; f();, this during the call wouldn't refer to MyClass. Using this in static methods to refer to the constructor is friendly to subclasses (because a subclass constructor's prototype is its superclass constructor; details here), but does mean you have to deal with the usual caveats around this.
Use # for private, and _ for protected.
I was wondering - what's the difference between JavaScript objects, classes and functions?
Am I right in thinking that classes and functions are types of objects?
And what distinguishes a class from a function? Or are they really the same thing, just the term for them changes according to how they are used?
function func() { alert('foo'); } // a function
func(); // call the function - alerts 'foo'
var func2 = function () { alert('hello'); } // acts the same way as 'func' surely?
func2(); // alerts 'hello'
var Class = function() { alert('bar'); }; // a class
var c = new Class(); // an istance of a class - alerts 'bar'
Sure, classes have methods and properties and can be instantiated - but then, I could do the same with any old function - or not?
As you must already be aware by now there are no classes in JavaScript. Instead functions in JavaScript may be made to behave like constructors by preceding a function call with the new keyword. This is known as the constructor pattern.
In JavaScript, everything is an object except for the primitive data types (boolean, number, and string), and undefined. On the other hand null is actually an object reference even though you may at first believe otherwise. This is the reason typeof null returns "object".
Functions in JavaScript are similar to functables in Lua (i.e. they are callable objects). Hence a function can be used in place of an object. Similarly, arrays are also objects in JavaScript. On the other hand, objects can be thought of as associative arrays.
The most important point however is that there are no classes in JavaScript because JavaScript is a prototypal object-oriented language. This means that objects in JavaScript directly inherit from other objects. Hence we don't need classes. All we need is a way to create and extend objects.
Read the following thread to learn more about prototypal inheritance in JavaScript: Benefits of prototypal inheritance over classical?
Update 2015
There are classes in JavaScript they just aren't used on older browsers:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
It has constructors, extensions, and the like.
class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(this.name + ' roars.');
}
}
A Class in JS:
function Animal(){
// Private property
var alive=true;
// Private method
function fight(){ //... }
// Public method which can access private variables
this.isAlive = function() { return alive; }
// Public property
this.name = "Joe";
}
// Public method
Animal.prototype.play = function() { alert("Bow wow!"); }
// .. and so on
Now when you create it's object
var obj = new Animal();
You can expect anything of this object as you would from objects in other language. Just the efforts to achieve it, was a bit different. You should also be looking at inheritance in JS.
Getting back too your question, I'll reword it as:
//Class : A representation of a set with common properties.
//object : One from the set with the same properties.
var Class = function() {alert('bar');}; // A set of function which alert 'bar'
var object = new Class(); // One of the functions who alert's 'bar'.
JavaScript does not have classes, and functions are actually objects in JavaScript (first-class citizens).
The only difference that function objects have is that they are callable.
function func() { alert('foo'); } // a function - Correct
func(); // call the function - alerts 'foo' - Correct
var func2 = function () { alert('foo'); } // same as 'func' surely? - Nope, func2 is a different object, that apparently does the same thing when called.
var Class = function() { alert('bar'); }; - It's a function with no name stored in variable Class.
var c = new Class(); - Calls function stored in Class supplying new empty object as this and returning that object. Functions called as new functionA() are expected to work as constructors and prepare a newly created object (this). In your case - constructor does nothing with the object and just alerts bar.
You also get classes in ES6 that look like this:
//class
class Cat {
//constructor
constructor() {
this.name = 'Snowball';
}
//method
meow() {
console.log('Hello, nyah! My name is ' + this.name + ' nyah!~');
}
};
There are no classes in javascript. But, there are ways to make a function to behave like a class in other languages.
A very good explanation is given here 3 way to define a class in js
Also, found a very good reference for OOP in Javascript
Object is the base type in JavaScript i.e. all the user defined data types inherits from Object in one way or another. So if you define a function or a class [note as of now JS doesn't support class construct, but its proposed in ECMAScript version 6], it will implicitly inherit from Object type.
Classes are really used for encapsulating logical functions and properties into one type / entity and you can 'new' it up using constructor syntax. So if you define a 'Customer' class, you can instantiate it multiple times and each instance / object can have different values. They can even share the values if you define class level value using prototype.
Since JS doesn't support class construct at the moment, functions can really act as individual method as well as container for other functions or types.
I hope with ECMAScript 6 we will have clear separation between these constructs similar to what we have in other languages like C#, Java etc.
I am trying to duplicate private prototype methods in javascript and found this bit of code, but I do not fully understand how it implements itself.
The code is...
var Foo = function () {};
Foo.prototype = (function () {
// Private attributes
var somePrivateAttribute = 'Hello world';
// Private methods
function somePrivateMethod(val) {
alert(val);
}
// Public attributes and methods
return {
somePublicMethod: function () {
somePrivateMethod(somePrivateAttribute);
}
};
})();
What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function? Could anyone please explain the benefits and disadvantages of using this for a project of mine.
How would this type of pattern work for objects that could have 500 instances or just 1. I am trying to understand and would greatly appreciate if anyone could enlighten me?
Is there any performance benefits to using this method?
What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function?
No. That's the point of prototypes, they are not duplicated - every of your Foo instances will inherit from the same Foo.prototype object.
Could anyone please explain the benefits and disadvantages of using this for a project of mine.
It looks like you're having a little misunderstanding, regarding the naming: Those "private" things are no "attributes" or "methods", as they have absolutely nothing to do with instance objects. They are just local variables which are only accessible from the functions you assign to the prototype object.
You might want to read How do JavaScript closures work? and their use in IIFEs.
How would this type of pattern work for objects that could have 500 instances or just 1.
It's perfectly fine. However, using the constructor pattern for just 1 instance might be a little odd - singletons can be defined in a simpler way.
If you want to read more on that pattern, search for revealing prototype pattern - it's the revealing module pattern applied to create prototype objects.
I haven't seen that pattern before, using a module (that's what it's called) for the prototype... but here's what I'd recommend; it's similar but the module encloses everything:
var Foo = (function FooClass() {
var privateVar = 'Hello world';
function privateFunc() {
...
}
function Foo() {}
Foo.prototype = {
publicMethod: function() {
...
}
};
return Foo;
}());
var foo = new Foo();
What I do not understand is when this object is initiated new Foo()
does that create a new object for the prototype every time as it is in
a self executing function?
The self executing function runs once, returns the object, and it won't run again; it keeps a reference to the variables via closure.
What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function?
No, the assignment to Foo's prototype only happens once. Nothing wrong with it at all, just a little unconventional.
You could also write it like this (also unconventional, but accomplishes the same thing):
var Foo = function () {};
Foo.prototype = new function() {
// Private attributes
var somePrivateAttribute = 'Hello world';
// Private methods
function somePrivateMethod(val) {
alert(val);
}
// Public attributes and methods
this.constructor = Foo;
this.somePublicMethod = function () {
somePrivateMethod(somePrivateAttribute);
}
};
As Bergi pointed out, this adds an extra object to the prototype chain; if you want to avoid that, you can write it like this instead:
var Foo = function () {};
(function() {
// Private attributes
var somePrivateAttribute = 'Hello world';
// Private methods
function somePrivateMethod(val) {
alert(val);
}
// Public attributes and methods
this.somePublicMethod = function () {
somePrivateMethod(somePrivateAttribute);
}
}).call(Foo.prototype)
By modifying the prototype instead of replacing it, the constructor property also stays intact.
Suppose I have a Foo object
How can I extend this object by adding a bar() method and also ensure that future instances of Foo have this method?
you need to add it to Foo's prototype:
function Foo(){}
Foo.prototype.bar = function(){}
var x = new Foo()
x.bar()
This all depends on how you're creating Foo, and how you intend to use .bar().
First, are you using a constructor-function for your object?
var myFoo = new Foo();
If so, then you can extend the Foo function's prototype property with .bar, like so:
function Foo () { /*...*/ }
Foo.prototype.bar = function () { /*...*/ };
var myFoo = new Foo();
myFoo.bar();
In this fashion, each instance of Foo now has access to the SAME instance of .bar.
To wit: .bar will have FULL access to this, but will have absolutely no access to variables within the constructor function:
function Foo () { var secret = 38; this.name = "Bob"; }
Foo.prototype.bar = function () { console.log(secret); };
Foo.prototype.otherFunc = function () { console.log(this.name); };
var myFoo = new Foo();
myFoo.otherFunc(); // "Bob";
myFoo.bar(); // error -- `secret` is undefined...
// ...or a value of `secret` in a higher/global scope
In another way, you could define a function to return any object (not this), with .bar created as a property of that object:
function giveMeObj () {
var private = 42,
privateBar = function () { console.log(private); },
public_interface = {
bar : privateBar
};
return public_interface;
}
var myObj = giveMeObj();
myObj.bar(); // 42
In this fashion, you have a function which creates new objects.
Each of those objects has a .bar function created for them.
Each .bar function has access, through what is called closure, to the "private" variables within the function that returned their particular object.
Each .bar still has access to this as well, as this, when you call the function like myObj.bar(); will always refer to myObj (public_interface, in my example Foo).
The downside to this format is that if you are going to create millions of these objects, that's also millions of copies of .bar, which will eat into memory.
You could also do this inside of a constructor function, setting this.bar = function () {}; inside of the constructor -- again, upside would be closure-access to private variables in the constructor and downside would be increased memory requirements.
So the first question is:
Do you expect your methods to have access to read/modify "private" data, which can't be accessed through the object itself (through this or myObj.X)?
and the second question is:
Are you making enough of these objects so that memory is going to be a big concern, if you give them each their own personal function, instead of giving them one to share?
For example, if you gave every triangle and every texture their own .draw function in a high-end 3D game, that might be overkill, and it would likely affect framerate in such a delicate system...
If, however, you're looking to create 5 scrollbars per page, and you want each one to be able to set its position and keep track of if it's being dragged, without letting every other application have access to read/set those same things, then there's really no reason to be scared that 5 extra functions are going to kill your app, assuming that it might already be 10,000 lines long (or more).
There are many ways to create re-usable objects like this in JavaScript. Mozilla have a nice introduction here:
https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript
The following will work in your example:
function Foo(){
this.bar = function (){
alert("Hello World!");
}
}
myFoo = new Foo();
myFoo.bar(); // Hello World
You can make bar a function making it a method.
Foo.bar = function(passvariable){ };
As a property it would just be assigned a string, data type or boolean
Foo.bar = "a place";