5

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 :(

Ben_hawk
  • 2,476
  • 7
  • 34
  • 59
  • possible duplicate of [Difference between a constructor and an Object](http://stackoverflow.com/questions/4559207/difference-between-a-constructor-and-an-object) – qwertymk Jul 13 '12 at 22:16
  • but does that not destroy the whole point of OOP? – Ben_hawk Jul 13 '12 at 22:17
  • btw. you're missing a new in your `var Block=...` statement – Julien Ch. Jul 13 '12 at 22:23
  • Some great reading on the subject: http://ejohn.org/blog/simple-class-instantiation/ John Resig (author of jQuery) details his through process while creating his own base object in js. – Julian Jul 13 '12 at 22:26
  • 1
    @juliench. He isn't, that's the code that creates the constructor. You can tell the intent by the fact that `Block` is uppercased – Ruan Mendes Jul 13 '12 at 22:32

6 Answers6

14

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

Decker W Brower
  • 931
  • 6
  • 16
3

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
Mitya
  • 33,629
  • 9
  • 60
  • 107
  • 1
    It's the simplest, albeit a naive way, which requires instantiating the base object just to setup the prototype chain. Good enough to answer the question. I wrote a post about what makes up correct inheritance in JS. http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html – Ruan Mendes Jul 13 '12 at 22:31
  • You're quite right, Juan - this is definitely the simplest of several means of implementing inheritance (none of which are perfect and all have peculiarities). I included it here so as to not obfuscate from the main point of the answer. I'll check out your post. – Mitya Jul 13 '12 at 22:38
  • I actually also wrote about the mitigating the problem with calling constructor functions without the new operator :) http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html that seems to be what you're doing in your test for `this.constructor` – Ruan Mendes Jul 13 '12 at 23:19
3

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
Kristian
  • 21,204
  • 19
  • 101
  • 176
  • What does "undefined because we have scope" mean? You never assigned `this.name = name`. Also, why do you create a local variable name when there's one already (the argument). Answers the question but it's not very clear – Ruan Mendes Jul 13 '12 at 23:17
  • oh, i was just making a note that in our Egg() object, you can stop things from merely being public by differentiating between var x and this.x... i will rewrite that to be more clear – Kristian Jul 14 '12 at 00:21
3

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.

kikito
  • 51,734
  • 32
  • 149
  • 189
2

You want to look at "Prototypal Inheritance" for JavaScript. http://www.crockford.com/javascript/inheritance.html

Abhishek Mehta
  • 1,447
  • 1
  • 14
  • 16
1

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();
shalitha senanayaka
  • 1,905
  • 20
  • 37