Im finding it really difficult to grasp OOP in javascript.
Normally I would expect to have to create a class, and then create objects from that class.
However, according to one tutorial the following makes an object.
var egg = {}
Have I not just made an object named egg without actually making a class.
If thats the case how would I make multiple objects from an object :S
Also according to a different tutorial an object is made like below, which is completely difference to what I was told above :S
var Block = function(){
}
Can anyone help me unravel my confusion :(
Both of the above examples are correct. to put it simply EVERYTHING in javascript is an object. classes do not exist but there are many ways to imitate them. my favorite method is as follows:
var myClass = function() { <----------------------------- class declaration
var prop1,
prop2, <------------------------------------ private properties
prop3;
var addMe = function( arg1, arg2 ) { <------------ private method
var result = arg1 + arg2;
return result;
}
var obj = { <------------------------------------- constructor method
Prop1: prop1,
Prop2: value2, <----------------------------- public properties
Prop3: value3,
Method: function() { <------------------------ public method
obj.prop3 = obj.prop1 + obj.prop2;
return obj.prop3;
}
}
obj.Prop4 = addme( prop1, prop2 ); <-------------- public property set
with the private method
return obj;
}
var myClassObj = new myClass;
myClassObj is now an object of myClass with four public properties
Prop1, Prop2, Prop3, Prop4 and one public method called Method
Javascript is a different language than those that you have learned so far. You can't expect things to work exactly as they do when you change languages.
A quick sneak peek: in javascript, you can assign a function to a variable. I bet on those other languages you have used, that was not possible:
var myCounter = 1;
var myFunction = function(x){ return x + 1; };
Going back to your question: In javascript there are no "real classes". There are just objects. I know this might sound confusing at first.
Javascript's object model is called "prototypal inheritance". It's different than "classical" (pun intended) inheritance. And it is also not very cleanly implemented.
Basically, you start with one reduced set of objects (Array, Function, Object, etc. are Objects, not classes) and then you use those objects to build others. The relationships between them can be "class-and-instance-like", but they don't have to. They can be other kinds of relationships, too.
Since there are no classes, you can't create them. But you can create a regular object, assign it to the variable Car, and just think "I'm going to use this object to create lots of other objects. And those other objects will have some attributes by default, like methods and stuff, so that they behave like cars". And the language allows you do do that. Car will behave like a class does in other languages, and the objects it produces will be "like instances of Car".
To javascript, though, they will look like objects with some relationships between them.
In a way, prototypal inheritance is a "superset" of classical inheritance. You can do classical inheritance, but also other things.
Have I not just made an object named egg without actually making a
class.
That's right. All you're doing there is instantiating the base Object object - you've not made anything that you can make instances of.
In JavaScript there is no formalised concept of classes - there is merely a simulation of them, achieved by instantiating rather than invoking functions.
function Animal() { this.animal = true; }
Animal.prototype.sayHi = function() { alert(this.name+' says hi!'); }
function Dog(name) { this.name = name; }
Dog.prototype = new Animal();
...
var fido = new Dog('Fido');
fido.sayHi(); //"Fido says hi!";
Note the 4th line is just one of several means of simulating inheritance.
So in JavaScript, classes and functions are both just functions. There is nothing inherent to prevent a function intended for instantiation from being called without the new operator, nor visa-versa.
In the former case, the common workaround is to check that the constructor is the 'class' (if invoked and not instantiated, the constructor will be Object) and re-route as necessary:
function Dog(name) {
//if we weren't instantiated, the constructor will be Object, not Dog
if(this.constructor != Dog) return new Dog(name);
this.name = name;
}
var fido = Dog(); //bad - invocation should be instantiation
Yes var egg = {} is an object, but its not an instance of an object.
In javascript, simply saying something in that way is basically js's idea of a singleton, meaning it is exactly what it equals.
//this is a js singleton, and all properties of this object are public.
var egg = {
name: 'humpty',
smush: function() { console.log('splat!'); },
weight: '4oz'
};
console.log(egg.weight); //4oz
whereas, the more traditional type of object would be making it a function that you can then instantiate:
var Egg = function( name, weight ) {
var name = name;
this.smush = function() { console.log('splat!'); }
this.weight = weight;
};
var e2 = new Egg('dumpty','6oz');
console.log(e2.name); //will not return name. (since i wrote var name and not this.name, its "private" and thus cannot be accessed.)
console.log(e2.weight); //4oz
You want to look at "Prototypal Inheritance" for JavaScript.
http://www.crockford.com/javascript/inheritance.html
Create an object oriented with jQuery. Make use of the constructor() method and access public and private methods from within the class scope.
/*
* myClass
*/
var myClass = function(options){
/*
* Variables accessible
* in the class
*/
var vars = {
myVar : ''
};
/*
* Can access this.method
* inside other methods using
* root.method()
*/
var root = this;
/*
* Constructor
*/
this.construct = function(options){
$.extend(vars , options);
};
/*
* Public method
* Can be called outside class
*/
this.myPublicMethod = function(){
console.log(vars.myVar);
myPrivateMethod();
};
/*
* Private method
* Can only be called inside class
*/
var myPrivateMethod = function() {
console.log('private method called');
};
/*
* Pass options when class instantiated
*/
this.construct(options);
};
/*
* USAGE
*/
/*
* Set variable myVar to new value
*/
var newMyClass = new myClass({ myVar : 'new Value' });
/*
* Call myMethod inside myClass
*/
newMyClass.myPublicMethod();
Related
I'm working on a chess game built in JavaScript. I'm taking an object-oriented approach to it and am having some difficulty working with JavaScript's inheritance. I want there to be a "Piece" abstract class that holds some fields and basic getters/setters such as is this piece black or white. I then want to have classes for each type of piece that I can instantiate like so:
var pieceOne = new Pawn();
The Pawn() should have all the fields and methods of Piece but have its own method for movement, and additional fields (such as whether or not it has moved yet, as this doesn't matter for most pieces). Here's my current Piece class:
//This object specifies basic information about pieces.
"use strict";
function Piece(color, type, captured, hasMoved) {
this.color = color;
this.type = type;
this.captured = captured;
this.hasMoved = hasMoved;
this.image = color + "_" + type + ".svg";
}
Piece.prototype.getImage = function getImage(){
return this.image;
}
Piece.prototype.isCaptured = function isCaptured(){
return this.captured;
};
I know if I am going to make a subclass for every kind of piece that I'd probably eliminate the "type" field, but how could I make a Pawn subclass? Something like this?
function Pawn() = new Piece(color, captured, hasMoved);
Pawn.prototype.getLegalMoves = function getLegalMoves(){
//return legal moves
}
var pieceOne = new Pawn("black", false, false);
Extending a class can be done in different ways. The simplest method to extend an class is to use Object.create method. This is common method which is used to achieve abstraction (Link to my blog). Let's give an example of the Object.create method as follows.
var Logger = { log : function(log){} }
var ConsoleLogger = function() {};
ConsoleLogger.prototype = Object.create(Logger);
If you are willing to take an object oriented approach on JS I would recommend you to follow the power constructor pattern.
Basically you have a function that creates objects for you and take advantage of the closures to hide the internal properties (fields or methods).
function myObject(){
var that={};
var myPrivateField;
var myPrivateFunction=function(){
}
that.myPublicMethod=function(){
}
return that;
}
Then you can just call the method myObject() and you will get a new object of this type.
You can extend this example to use inheritance by just calling the power constructor of another object and then use object augmentation. Take a look at the example of parasatic inheritance of Douglas Crockford.
You can call Piece's constructor from Pawn and have that constructor operate on the Pawn instance:
function Pawn(/* args... */) {
Piece.call(this, color, type, captured, hasMoved);
/* Pawn-specific constructor code... */
}
I believe it's just a matter of setting the prototype of the specific piece constructors to an instance of Piece. For example:
Pawn.prototype = new Piece("", false, false);
However, this will not call the Piece (super) constructor every time you instantiate a new Pawn, so you'll have to manually assign color, type, etc. from the Pawn constructor:
-- EDIT --
You might prefer this instead: Javascript inheritance: call super-constructor or use prototype chain?
Take a look at this: https://github.com/haroldiedema/joii
var BaseClass = function()
{
this.some_var = "foobar";
/**
* #return string
*/
this.someMethod = function() {
return this.some_var;
}
};
var MyClass = new Class({ extends: BaseClass }, function()
{
/**
* #param string value
*/
this.__construct = function(value)
{
this.some_var = value;
}
})
Usage:
var obj = new MyClass("Hello World!");
console.log( obj.someMethod() ); // Hello World!
In JavaScript I see a few different ways, certain tasks can be performed within an object for example, the object Egg I have below.
Can anyone tell me the difference between each one, why I would use one and not the other etc
var Egg = function(){
//Properties
var shell = "cracked" // private property
this.shell = "cracked" // public property
shell: "cracked" // what is this??
//functions
function cook(){
//standard function
}
cook: function(){
//what kind of function is this?
}
//not sure what this is
details: {
//What is this? an array :S it holds 2 elements?
cost: 1.23,
make: 'Happy Egg';
}
}
Your code snippet isn't quite valid, but here are a few things it raises:
Property initializers, object initializers
You've asked what shell: cracked is. It's a property initializer. You find them in object initializers (aka "object literals"), which are written like this:
var obj = {
propName: "propValue"
};
That's equivalent to:
var obj = {};
obj.propName = "propValue";
Both of the above create an object with a property called propName which has a string value "propValue". Note that this doesn't come into it.
Functions
There are a couple of places where functions typically come into it vis-a-vis objects:
Constructor functions
There are constructor functions, which are functions you call via the new operator. Here's an example:
// Constructor function
function Foo(name) {
this.name = name;
}
// Usage
var f = new Foo("Fred");
Note the use of the keyword this in there. That's where you've seen that (most likely). When you call a constructor function via new, this refers to the new object created by the new operator.
this is a slippery concept in JavaScript (and completely different from this in C++, Java, or C#), I recommend these two (cough) posts on my blog:
You must remember this
Mythical methods
Builder/factory functions
You don't have to use constructor functions and new, another pattern uses "builder" or "factory" functions instead:
// A factory function
function fooFactory(name) {
var rv = {}; // A new, blank object
rv.name = name;
return rv;
}
// Usage
var f = fooFactory("Fred");
Private properties
You mentioned "private" properties in your question. JavaScript doesn't have private properties at all (yet, they're on their way). But you see people simulate them, by defining functions they use on the object as closures over an execution context (typically a call to a constructor function or a factory function) which contains variables no one else can see, like this:
// Constructor function
function EverUpwards() {
var counter = 0;
this.increment = function() {
return ++counter;
};
}
// Usage:
var e = new EverUpwards();
console.log(e.increment()); // "1"
console.log(e.increment()); // "2"
(That example uses a constructor function, but you can do the same thing with a factory function.)
Note that even though the function we assign to increment can access counter, nothing else can. So counter is effectively a private property. This is because the function is a closure. More: Closures are not complicated
Sure, Ben.
This sort of gets to the bottom of the dynamism of JavaScript.
First, we'll look at basics -- if you're coming from a place where you understand class-based languages, like, say, Java or C++/C#, the one that is going to make the most sense is the constructor pattern which was included very early on:
function Egg (type, radius, height, weight) {
// private properties (can also have private functions)
var cost = (type === "ostrich") ? 2.05 * weight : 0.35 * weight;
// public properties
this.type = type;
this.radius = radius;
this.height = height;
this.weight = weight;
this.cracked = false;
// this is a public function which has access to private variables of the instance
this.getCost = function () { return cost; };
}
// this is a method which ALL eggs inherit, which can manipulate "this" properly
// but it has ***NO*** access to private properties of the instance
Egg.prototype.Crack = function () { this.cracked = true; };
var myEgg = new Egg("chicken", 2, 3, 500);
myEgg.cost; // undefined
myEgg.Crack();
myEgg.cracked; // true
That's fine, but sometimes there are easier ways of getting around things.
Sometimes you really don't need a class.
What if you just wanted to use one egg, ever, because that's all your recipe called for?
var myEgg = {}; // equals a new object
myEgg.type = "ostrich";
myEgg.cost = "......";
myEgg.Crack = function () { this.cracked = true; };
That's great, but there's still a lot of repetition there.
var myEgg = {
type : "ostrich",
cost : "......",
Crack : function () { this.cracked = true; }
};
Both of the two "myEgg" objects are exactly the same.
The problem here is that EVERY property and EVERY method of myEgg is 100% public to anybody.
The solution to that is immediately-invoking functions:
// have a quick look at the bottom of the function, and see that it calls itself
// with parens "()" as soon as it's defined
var myEgg = (function () {
// we now have private properties again!
var cost, type, weight, cracked, Crack, //.......
// this will be returned to the outside var, "myEgg", as the PUBLIC interface
myReturnObject = {
type : type,
weight : weight,
Crack : Crack, // added benefit -- "cracked" is now private and tamper-proof
// this is how JS can handle virtual-wallets, for example
// just don't actually build a financial-institution around client-side code...
GetSaleValue : function () { return (cracked) ? 0 : cost; }
};
return myReturnObject;
}());
myEgg.GetSaleValue(); // returns the value of private "cost"
myEgg.Crack();
myEgg.cracked // undefined ("cracked" is locked away as private)
myEgg.GetSaleValue(); // returns 0, because "cracked" is true
Hope that's a decent start.
You are mixing syntaxes between object property declaration and simple javascript statements.
// declare an object named someObject with one property
var someObject = {
key: value
};
// declare an anonymous function with some statements in it
// and assign that to a variable named "someFunction"
var someFunction = function () {
// any javascript statements or expressions can go here
};
There's a key distinction in JavaScript between objects and functions. Objects hold a bunch of data (including functions), and functions can be used to make or modify objects, but they aren't inherently the same thing. OOP in JavaScript is based around using functions as classes. For example, take the following class:
Test = function(){
this.value = 5;
}
If you just call the function Test(), then nothing will happen. Even if you say var x = Test(), the value of x will be undefined. However, using the new keyword, magic happens! So if we say var x = new Test(), then now the variable x will contain a Test object. If you do console.log(x.value), it would print 5.
That's how we can use functions to make objects. There's also a key different in syntax--a function can contain any sort of JavaScript block you want, whether that's if statements or for loops or what have you. When declaring an object, though, you have to use the key: value syntax.
Hope that clears things up a little bit!
In John Resig's post on Simple "Class" Instantiation in Javascript, he states:
"...if you have a frequently-accessed function (returning an object) that you want people to interact with, then it's to your advantage to have the object properties be in the prototype chain and instantiate it. Here it is, in code:"
// Very fast
function User(){}
User.prototype = { /* Lots of properties ... */ };
// Very slow
function User(){
return { /* Lots of properties */ };
}
I would like to apply this to a function like the following (which happens to live inside a "class" declaration)
//...
this.get_subscription = function(args)
{
return {
property_one: "value",
property_two: {
sub_prop: args.something
}
}
}
but have no idea where to put the args. If I do
this.get_subscription = function(args) {}
this.get_subscription.prototype = {
property_one: "value"
//...
}
it'll say args are undefined. I've tried several variants, none of which work. How should I properly do this, in a way that doesn't put args in the parent class's scope?
You seem to misunderstand the point of prototype. Prototype holds methods and fields that should be common to all instances of the object. Therefore, if property_two is based upon args passed to the constructor, then it does not belong to the prototype!
After all, in this code
this.get_subscription = function(args) {}
this.get_subscription.prototype = {
property_one: "value"
//...
}
first, the function get_subscription is created, then its prototype is set to the object literal. There is no args until you call the constructor, so it does not make sense to do something with the args in the prototype.
So, your usual javascript object should look like this example - a 2D point class.
function Point(x, y) {
/* In constructor:
* initialize fields that are related to the constructor parameters
* and are different for different instances
*/
this.x = x;
this.y = y;
}
// in prototype, define fields that are common to all instances
Point.prototype.RED = '#FF0000';
/* in prototype, also define the methods; as they can use the "this" keyword,
* they can reference their own instance, so you don't have to include them
* in each instance manually
*/
Point.prototype.toString = function() { return '[' + this.x + ', ' + this.y + ']'; };
Yes, that's the drawback of the "everything-to-prototype"-idea: You don't have access to the constructor arguments - they are only available inside the function body (exept you put them into a public property there). Everything that needs to use them does not belong to the prototype; you only will fill "default properties" on the prototype (usually methods that are common to all instances).
I think that you don't need that anyway in here. The pattern is only useful for real constructor functions, which you don't seem to have here (I then would expect this.Subscription). Also, the promised "performance boost" is negligible.
If you really would want to use it in here, it would be:
function Class() {
this.Subscription = function(args) {
this.propertyTwo = {
subprop: args.something
};
};
this.Subscription.prototype = {
property_one: "value",
property_two: {}
};
}
// a method callable without the "new" operator:
Class.prototype.get_subscription = function(args) {
return new this.Subscription(args);
}
usage:
var object = new Class();
var sub = new object.Subscription();
var sub2 = new object.Subscription();
// the promised boost is less memory usage for:
sub.propertyOne === object.Subscription.prototype.propertyOne === sub2.propertyOne;
Also care for Crockford's Prototypal inheritance - Issues with nested objects when you attempt to set/change/delete properties on the propertyTwo-Object(s).
I am getting confused over which way I should be creating an object in javascript. It seems there are at least two ways. One is to use object literal notation while the other uses construction functions. Is there an advantage of one over the other?
If you don't have behaviour associated with an object (i.e. if the object is just a container for data/state), I would use an object literal.
var data = {
foo: 42,
bar: 43
};
Apply the KISS principle. If you don't need anything beyond a simple container of data, go with a simple literal.
If you want to add behaviour to your object, you can go with a constructor and add methods to the object during construction or give your class a prototype.
function MyData(foo, bar) {
this.foo = foo;
this.bar = bar;
this.verify = function () {
return this.foo === this.bar;
};
}
// or:
MyData.prototype.verify = function () {
return this.foo === this.bar;
};
A class like this also acts like a schema for your data object: You now have some sort of contract (through the constructor) what properties the object initializes/contains. A free literal is just an amorphous blob of data.
You might as well have an external verify function that acts on a plain old data object:
var data = {
foo: 42,
bar: 43
};
function verify(data) {
return data.foo === data.bar;
}
However, this is not favorable with regards to encapsulation: Ideally, all the data + behaviour associated with an entity should live together.
It essentially boils down to if you need multiple instances of your object or not; object defined with a constructor lets you have multiple instances of that object. Object literals are basically singletons with variables/methods that are all public.
// define the objects:
var objLit = {
x: 0,
y: 0,
z: 0,
add: function () {
return this.x + this.y + this.z;
}
};
var ObjCon = function(_x, _y, _z) {
var x = _x; // private
var y = _y; // private
this.z = _z; // public
this.add = function () {
return x + y + this.z; // note x, y doesn't need this.
};
};
// use the objects:
objLit.x = 3;
objLit.y = 2;
objLit.z = 1;
console.log(objLit.add());
var objConIntance = new ObjCon(5,4,3); // instantiate an objCon
console.log(objConIntance.add());
console.log((new ObjCon(7,8,9)).add()); // another instance of objCon
console.log(objConIntance.add()); // same result, not affected by previous line
Another way to create objects in a uniform way is to use a function that returns an object:
function makeObject() {
var that = {
thisIsPublic: "a public variable"
thisIsAlsoPublic: function () {
alert(that.thisIsPublic);
}
};
var secret = "this is a private variable"
function secretFunction() { // private method
secret += "!"; // can manipulate private variables
that.thisIsPublic = "foo";
}
that.publicMethod = function () {
secret += "?"; // this method can also mess with private variables
}
that.anotherPublicVariable = "baz";
return that; // this is the object we've constructed
}
makeObject.static = "This can be used to add a static varaible/method";
var bar = makeObject();
bar.publicMethod(); // ok
alert(bar.thisIsPublic); // ok
bar.secretFunction(); // error!
bar.secret // error!
Since functions in JavaScript are closures we can use private variables and methods and avoid new.
From http://javascript.crockford.com/private.html on private variables in JavaScript.
The code below shows three methods of creating an object, Object Literal syntax, a Function Constructor and Object.create(). Object literal syntax simply creates and object on the fly and as such its __prototype__ is the Object object and it will have access to all the properties and methods of Object. Strictly from a design pattern perspective a simple Object literal should be used to store a single instance of data.
The function constructor has a special property named .prototype. This property will become the __prototype__ of any objects created by the function constructor. All properties and methods added to the .prototype property of a function constructor will be available to all objects it creates. A constructor should be used if you require multiple instances of the data or require behavior from your object. Note the function constructor is also best used when you want to simulate a private/public development pattern. Remember to put all shared methods on the .prototype so they wont be created in each object instance.
Creating objects with Object.create() utilizes an object literal as a __prototype__ for the objects created by this method. All properties and methods added to the object literal will be available to all objects created from it through true prototypal inheritance. This is my preferred method.
//Object Example
//Simple Object Literal
var mySimpleObj = {
prop1 : "value",
prop2 : "value"
}
// Function Constructor
function PersonObjConstr() {
var privateProp = "this is private";
this.firstname = "John";
this.lastname = "Doe";
}
PersonObjConstr.prototype.greetFullName = function() {
return "PersonObjConstr says: Hello " + this.firstname +
" " + this.lastname;
};
// Object Literal
var personObjLit = {
firstname : "John",
lastname: "Doe",
greetFullName : function() {
return "personObjLit says: Hello " + this.firstname +
", " + this.lastname;
}
}
var newVar = mySimpleObj.prop1;
var newName = new PersonObjConstr();
var newName2 = Object.create(personObjLit);
It depends on what you want to do. If you want to use (semi-)private variables or functions in you object, a constructor function is the way to do it. If your object only contains properties and methods, an object literal is fine.
function SomeConstructor(){
var x = 5;
this.multiply5 = function(i){
return x*i;
}
}
var myObj = new SomeConstructor;
var SomeLiteral = {
multiply5: function(i){ return i*5; }
}
Now the method multiply5 in myObj and SomeLiteral do exactly the same thing. The only difference is that myObj uses a private variable. The latter may be usefull in some cases. Most of the times an Object literal is sufficient and a nice and clean way to create a JS-object.
Do you want single instance of the object for the page -- Literal.
Do you want to just transfer data like DTO objects simple GET SET :- Literal
Do you want to create real objects with method behaviors , multiple instances - Constructor function , Follow OOP principles , inheritance :- Constructor functions.
Below is the youtube video which explains in detail what is literal , what are constructor functions and how they differ from each other.
https://www.youtube.com/watch?v=dVoAq2D3n44
As mentioned in https://www.w3schools.com/js/js_object_definition.asp
Using an object literal, you both define and create , one object in one
statement.
Also
Object literal only create a single object. Sometimes we like to have
an object type that can be used to create many objects of one type.
Go with object literal, it's more consise and expands better with the introduction of initial values.
The Object() constructor function is a bit slower and more verbose. As
such, the recommended way to create new objects in JavaScript is to
use literal notation
Udacity Object-Oriented JavaScript
Actually, methinks, we can have private methods in object literals. Consider code below:
var myObject = {
publicMethod: function () {
privateMethod1();
privateMethod2();
function privateMethod1(){
console.log('i am privateMethod1');
}
function privateMethod2(){
console.log('i am privateMethod2');
}
}
}
Matter of taste, but I prefer to use object literals where it is possible.
Here is a benchmark that shows the access time for accessing properties on literals, constructors and classes. It might take a while but it shows almost every way to access properties. To me this benchmark shows literal properties access time overall are slightly slower than class and constructor properties access time. The worst performing times are from getters and setters on an object literal. Unlike getters and setters on classes and constructors which seem to be even faster than most other access times.
Benchmark: https://www.measurethat.net/Benchmarks/Show/12245/0/the-grand-dictionary-property-accessor-schema
// Object Literal and Object constructor
function MyData(foo, bar) {
this.foo = foo;
this.bar = bar;
}
MyData.prototype.verify = function () {
return this.foo === this.bar;
};
//add property using prototype
var MD = new MyData;//true.
var MD = new MyData();//true.
MD.verify// return only the function structure.
MD.verify(); //return the verify value and in this case return true coz both value is null.
var MD1 = new MyData(1,2); // intialized the value at the starting.
MD1.verify// return only the function structure.
MD1.verify(); // return false coz both value are not same.
MD1.verify(3,3);// return false coz this will not check this value intialized at the top
MyData.prototype.verify = function (foo,bar) {
return this.foo === this.bar;
};
var MD1 = new MyData(1,2);
MD1.verify();
MD1.verify(3,3);// return false coz this keyword used with foo and bar that will check parent data
I was just wondering about the difference between the following declaration of JavaScript objects. Specifically, the difference between thing object literal and thing1 object from thing class.
Code:
var thing = {
sanity:0,
init:function(){
//code
},
send:function(){
//code
}
}
function thing(){
this.sanity = 0;
this.init = function(){
//code
};
this.send = function(){
//code
};
}
thing1 = new thing();
Static Objects / Object Literals
Static objects, or object literals, don't require instantiation with the new operator and also behave like singletons. Consider the following example:
Code:
var staticObject1 = {
a: 123,
b: 456
};
var staticObject2 = staticObject1;
console.log(staticObject1, staticObject2);
staticObject2.b = "hats";
console.log(staticObject1, staticObject2);
Output:
Object a=123 b=456 Object a=123 b=456
Object a=123 b=hats Object a=123 b=hats
Notice that changing staticObject2.b also affected staticObject1.b. However, this may not always be the desired effect. Many libraries, such as Dojo, offer an object cloning method that can alleviate this situation if you want to make a copy of a static object. Continuing the previous example, consider the following:
Code:
var staticObject3 = dojo.clone(staticObject1); // See the doc in the link above
staticObject1.a = "pants";
console.log(staticObject1, staticObject2, staticObject3);
Output:
Object a=pants b=hats Object a=pants b=hats Object a=123 b=hats
Notice that the values of the members of staticObject1 and staticObject2 are the same, whereas staticObject3 is not affected by changes to these other objects.
Static objects are also useful for creating project or library namespaces, rather than filling up the global scope, and promotes compatibility like no one's business.
This is useful when creating libraries that require portability or interoperability. This can be seen in popular libraries such as Dojo, YUI and ExtJs, where all or most methods are called as dojo.examplMethod(), YUI().exampleMethod(), or Ext.exampleMethod() respectively.
Static objects can also be considered loosely analogous to struct's in C/C++.
Class Constructors / Instantiated Objects
Classes in JavaScript are based on prototypal inheritance, which is a far more complex subject and can be read about here, here and here.
As opposed to static objects, this method of object creation gives the unique opportunity for private scope object members and methods because of JavaScript's closuer property. Consider the following example of private class members:
Code:
var SomeObject = function() {
var privateMember = "I am a private member";
this.publicMember = "I am a public member";
this.publicMethod = function() {
console.log(privateMember, this.publicMember);
};
};
var o = new SomeObject();
console.log(typeof o.privateMember, typeof o.publicMember);
o.publicMethod();
Output:
undefined string
I am a private member I am a public member
Notice that typeof o.privateMember is "undefined" and not accessible outside of the object, but is from within.
Private methods can also be made, but are not as straight forward yet are still simple to implement. The issue lies in that the value of this inside of the private method defaults to window and one of two techniques must be applied to ensure that this refers to the object that we are working within, in this case, the instance of SomeObject. Consider the following example:
Code:
var SomeObject = function() {
var privateMember = "I am a private member";
var privateMethod = function() {
console.log(this.publicMember);
};
this.publicMember = "I am a public member";
this.publicMethod = function() {
console.log(privateMember, this.publicMember);
};
this.privateMethodWrapper = function() {
privateMethod.call(this);
}
};
var o = new SomeObject();
console.log(typeof o.privateMethod, typeof o.publicMethod, typeof o.privateMethodWrapper);
o.privateMethodWrapper();
Output:
undefined function function
I am a public member
Notice that withing privateMethodWrapper(), privatemethod was executed using call and passing in this for the function's context. This is all fine; however, the following technique is preferable (in my opinion) as it simplifies the calling scope and produces identical results. The previous example can be changed to the following:
Code:
var SomeObject = function() {
var self = this;
var privateMember = "I am a private member";
var privateMethod = function() {
console.log(self.publicMember);
};
this.publicMember = "I am a public member";
this.publicMethod = function() {
console.log(privateMember, this.publicMember);
};
this.privateMethodWrapper = function() {
privateMethod();
}
};
var o = new SomeObject();
console.log(typeof o.privateMethod, typeof o.publicMethod, typeof o.privateMethodWrapper);
o.privateMethodWrapper();
Output:
undefined function function
I am a public member
This answer was the basis for a post on my blog, where I give additional examples. Hope that helps ;)
Case 2 is referencing javascript class constructors. A glaring difference is that the variable is not yet an object, so you cannot internally reference thing1.sanity. You would have to initialize the class by creating an instance of said class prior to calling any internal members:
var myConstructor = function() {
this.sanity = 0;
}
// wont work
alert(myConstructor.sanity);
// works
var thing1 = new myConstructor();
alert(thing1.sanity);
Here is an article going further in-depth than my quick example:
Class Constructors vs. Object Literals
The difference is that the thing1 object is associated with the thing1 class, and will inherit (not literally) the thing1 prototype.
For example, you can later write
thing.prototype.initAndSend = function() { this.init(); this.send(); };
You will then be able to write thing1.initAndSend() without modifying thing1. In addition, thing1.constructor will be equal to the thing method, whereas {}.constructor is equal to Object.
By the way, standard convention is to capitalize class names.
Functions are objects and also constructors (you can instantiate them using new).
Hash-tables/Objects ({}) are not able to be instantiated, thus they are commonly used as data structures. And I am not so sure if it is wise to call them "Objects".
With the first method, you are declaring a single object. With the second, you are declaring a class from which you can instantiate (i.e. create) many different copies.