JavaScript Classes and Variable Scope - javascript

I'm relatively new to JS and I'm having issues properly emulating OOP principles.
I guess I have two questions. Question the first is regarding the many ways to declare variables.
Say I have a class:
function clazz(a)
{
this.b = 2;
var c = 3;
this.prototype.d = 4; // or clazz.prototype.d = 4?
}
var myClazz = new clazz(1);
Am I correct in the following assessments:
a is a private variable that is instance specific (i.e. different instances of clazz will have unique and independent variables 'a'). It can be accessed from within clazz as: 'a'.
b is a public variable that is instance specific. It can be accessed from within clazz as 'this.b' and from outside clazz as 'myClazz.b'.
c is a private variable that is static, or class specific (i.e. different instances of clazz will share the same 'c' variable). It can be accessed from within any instance of clazz as 'c' and changes in instance of clazz are reflected in all instances of clazz.
d is a public variable that is static/class specific. It can be accessed from anywhere via 'clazz.prototype.d' or 'myClazz.prototype.d'.
The overall issue I have with my understanding of the variable scheme is that there's no way to declare a private variable that is NOT static (i.e. a unique version for every instance of the class).
The second question is with respect to different types of class declarations.
I've been using:
var MySingleton = new function() {...};
to create singletons. Is this correct? I'm also unsure as to the effect of the "new" keyword in this situation as well as appending () function braces to the end of the declaration as so:
var MySingleton = new function() {...}();
I've been using this pattern to declare a class and then instantiate instances of that class:
function myClass() {...};
var classA = new myClass();
var classB = new myClass();
Is this the proper method?

You are right for a and b:
a is an argument, available only within the scope of the constructor function.
bis a public instance variable, available on all instances created with that constructor function.
c is a private variable, accessible only within the constructor function.
The d declaration is invalid, because the prototype object is meant to be used only on constructor functions, like Clazz.prototype.d = 3;, if you do it like this, the variable will be shared, but you can assign a value on an specific instance, and the default value will be shadowed (through the prototype chain).
For "private variables" you can use the way you declare c, for example:
function Clazz(){
var c = 3; // private variable
this.privilegedMethod = function () {
alert(c);
};
}
Privileged methods, are public, but they can access "private" variables declared inside the constructor function.
For creating singletons, the easiest way is maybe to use an object literal, like:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
And if you want private members on your singleton instance, you can:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accesible here
},
publicMethod2: function () {
}
};
})();
This is has been called the module pattern, it basically allows you to encapsulate private members on an object, by taking advantage of the use of closures.
More info:
Private Members in JavaScript
Introduction to Object Oriented JavaScript
Edit: About the syntax you post:
var mySingleton = new (function() {
// ...
})();
By using the new operator, you are declaring and using in one step an "anonymous constructor function", which will generate a new object instance, it is valid but I personally would prefer the "module" pattern approach, to create my own object instance (and avoid new).
Also, reading new function () {}, I think that is not really intuitive and may create confusion, if you don't understand well how the new operator works.
About the parentheses, they are optional, the new operator will call the function constructor without parameters if you don't add them (see ECMA-262, 11.2.2).

OK, lets go over this:
'a' is an argument passed to the constructor of your class. It will only exist for the duration of the constructor's invocation. This means you should probably store its value somewhere.
'b' is a public instance member. It is instance specific (altho, since you're assigning the value in the constructor, all instances will initially have the same value for 'b').
'c' is a private instance member. It will, however, only be accessible inside your constructor since it is only defined in that scope. Unless you refer to it from a closure inside your constructor function, its fate will be similar to that of 'a' above.
'd' is a public instance member. Each instance of your class will have a member 'd' with the value 4 initially. Note however that assigning a reference type object to a prototype member of your class (such as 'd') will make every instance member 'd' refer to the same object. Example:
MyClass.prototype.d = { prop1: 'val1', prop2: 'val2' };
var a = new MyClass();
var b = new MyClass();
a.d.prop1 = 'foo'; // is the same as: b.d.prop1 = 'foo';
Static members of the class are defined using:
function MyClass()
{
// ...
}
MyClass.staticMemeber = 'I am a static member';
You should probably not treat MyClass.prototype as a place to hold your static members/methods.Everything assigned to a classes' prototype is in turn a member of each of its instances.
When ()'s are attached to a function definition (right after the block), the function is executed. That means:
var myFunc = function() { alert('blah'); }();
would result in nothing more than a method invocation. The following code:
var MySingleton = new function() {...}();
would mean 'use the return value from function() as the constructor for MySingleton'.

Related

How can I pass 'this' object to lower function 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

Difference between using a module pattern and instantiating new objects

I'm trying to restructure some javascript and I'm confused about the module pattern.
One way I have now is to simply declare a class containing all the functionality for a component like so
var Foo = function(){
this.Bar = {};
...
}
and create a new instance for use in the component. But I've also read about the module pattern and I can't see what the benefit would be compared to what I have since it appears to do about the same, just in a more complicated way. Maybe I just haven't encountered the case that makes it a better choice.
For example, a pattern like this:
var module = (function () {
// private variables and functions
var foo = 'bar';
// constructor
var module = function () {
};
// prototype
module.prototype = {
constructor: module,
something: function () {
}
};
// return module
return module;
})();
var my_module = new module();
doesn't appear significantly different from what I already had. What does this pattern let me do that I can't do the other way?
The key difference between the two is in the first example, you can't have private variables and functions if you want to work with the prototype. You can have private variables and functions, but only if your public properties and methods are created in the constructor by attaching them to this.
Example 1 with a private variable and function:
var Foo = function(){
var privateVar = "priv";
function privateFunction(){
console.log(privateVar);
}
this.publicProperty = 1;
this.publicFunction = function(){
console.log(privateVar);
}
}
The above is no problem if you don't want to use the prototype. However, if you do then there is no way to have private variables, without the new scope that your second example benefits from.
As you can see, you have to include everything within the constructor, whereas the second example you can leave the constructor just for initialising variables.
Conversely, the prototype methods in the second example are out of scope of the constructor, so they can't use any variables of functions within the constructor. All functions and variables that the prototype methods need must be declared in the outer closure scope.

Private JavaScript functions - this.name vs. var name

If I'm using some private functions in a class do certain naming conventions yield better performance or offer different functionality...or is it simply a matter of preference?
var MyClass = function() {
var private1 = function(msg){
// Do stuff.
console.log(msg);
};
this.private2 = function(msg) {
// Do stuff.
console.log(msg);
};
};
Your two variables have very different access so which one to use depends upon which type of access you want to offer, not just a coding style preference.
In your example, private1 is a local variable to your constructor and is ONLY available to code inside the constructor. It is NOT available to any code outside the constructor. It is actually private.
var yourObj = new MyClass();
yourObj.private1(); // undefined, will not work
private2 is an instance variable of a MyClass object you create with the new operator and is reachable by any code as yourObj.private2(). It is not private in any way - it is a publicly reachable method. Example:
var yourObj = new MyClass();
yourObj.private2(); // works
So private1 is private and private2 is public. One should select the implementation method that matches the desired goal of the code. This is not just a coding style preference.
private1 is a function inside constructor MyClass and private2 is function of MyClass instance:
var cl = new MyClass();
console.log(cl.private1); // undefined
console.log(cl.private2); // function

What are the differences between to create a "classic" class in javascript and JSON notation?

In Javascript there are several ways to create a class. But I have some doubts between these two ways:
function MyClass(){
this.myFun = function(){
// do stuff
}
}
and
var MyClass = {
myFun: function(){
// do stuff
}
}
The only difference is that the second way I can't to use a new operator? So the Json notation allows me to create a static class or singleton class, right?
The code you showed doesn't create classes. The notion of class is unknown to javascript, it uses prototypal inheritance. Now as to your code. The first piece of code represents a constructor function. From it, you can derive instances - javascript objects with shared properties -, using the keyword new.
function MyConstructor(name){
this.name = name || 'no name yet';
this.myFun = function(){
alert(this.name);
}
}
var instanceA = new MyConstructor('Webman')
,instanceB = new MyConstructor;
instanceA.myFun(); //=> 'Webman'
instanceB.myFun(); //=> 'no name yet'
The second piece of code creates a single javascript object. It uses an object literal notation.
var mySingleObject = {
myFun: function(){
alert('I am single');
}
};
mySingleObject.myFun(); //=> 'I am single'
The Mozilla Developer Network has a nice page, where things are explained in more detail.
Creating an object using an object literal, everything is public. Using a constructor, it is possible to have private variables, using javascripts closure mechanism:
function MyConstructor(name){
var namestring = 'the name property of this instance is: '+
(name || 'not set');
this.myFun = function(){
alert(namestring);
}
}
A few minor corrections. In JS these is only class simulation - the language lacks a formalised notion of actual classes. And your JSON notation is actually a JS object - that would be invalid JSON as you currently have it.
You do not have to use an object to simulate the singleton pattern. You can do this with constructors like so:
function Animal() {
if (Animal.instance) return Animal.instance;
Animal.instance = this;
/* constructor code here */
}
var animal_a = new Animal(); //constructor runs
var animal_b = new Animal(); //singleton instance returns
console.log(animal_a === animal_b); //true
Also, with your first approach, note it is better to put reusable, inheritable code on the prototype rather than declaring separately for each instance. This is faster, and also more sensible - the prototype is the place for this.
function Animal() {}
Animal.prototype.method = function() {}
This also avoids the problem of distinguishing between own and inherited properties, which, in your code, could not be done because you're declaring methods separately on each instance.
[EDIT - in response to the OP's question about private members]
Private members are implemented as local variables/functions, which means they are inaccessible outside the current closure.
function Animal() {
var private_var = 'foo';
function private_method = function() { alert('bar'); };
}
Public methods may (if you choose) be able to get or set them - but in order that they themselves have access to these private members, they would have to be declared inside the constructor, not separately, outside it.
function Animal() {
var private_var = 'foo';
function private_method = function() { alert('bar'); };
if (!Animal.prototype.public_method)
Animal.prototype.public_method = function() {
alert(private_var);
};
}
var dog = new Animal();
dog.public_method(); //'foo'
There are no classes in javascript, javascript is a prototypal language.
There is no way to explain this faster than watching: Crockford on JavaScript - Chapter 2: And Then There Was JavaScript for a simple CORRECT explanation by the father of json (amongst other things).
Good Luck!!

javascript private member not accessible through public method

I have following setup. method and method1 both are public methods of class Student. But why ca only "method" access private variable p
​function Student() {
var p = 10;
this.method = function() {
document.write(p);
};
};
Student.prototype.method1 = function() {
document.write('here');
document.write(p);
};
var s = new Student();
s.method();
s.method1();
​
How does it make sense, I mean is it "a public method that does not have access to private members!"
There is no magic going on with JavaScript's prototypal inheritance.
Student is still a function and p is local to that function. It cannot be accessed from outside code in any way. method can access p because it is defined inside Student and therefore forms a closure, but method1 is declared outside Student's scope.
Assigning a function to another function's prototype cannot give it access to its local variables.
Consider this example:
var p = 41;
function foo() {
console.log(p);
}
​function Student(){
var p = 10;
};
Student.prototype.bar = foo;
var s = new Student();
s.bar();
foo();
You might think that because foo is invoked as an object method it could have access to the local variables, but that's just not the case. The only value that is determined dynamically is this, it is a special keyword. All other variables are strictly defined through the scope chain.
method1 is defined outside of the base class definition for Student. As such, it cannot access variables declared as private inside the base class definition. If it could, then you could get around private variable restrictions in existing classes by just defining a public method for that class.
In JavaScript, public methods like method1 (i.e. methods added to the prototype) do not have access to private variables, but "privileged" methods like your method do.
Remember, JavaScript doesn't have the same scoping rules as other object-oriented languages. The method method forms a closure around the private variables within the Student constructor function, while method1 does not.

Categories

Resources