Results 1 to 4 of 4

Thread: JS Classes?

  1. #1
    Join Date
    May 2006
    Location
    Alaska
    Posts
    163
    Thanks
    5
    Thanked 2 Times in 2 Posts

    Angry JS Classes?

    I am wanting to make js classes, but I don't have any clue how. I heard lots of stuff about prototype.js and there seems to be new classes in there, and something that makes classes, but when I looked in the source, I couldn't find how you make one.It's sort of making me mad, and I don't really want to use prototype.js, I just kinda get a feeling that I can do it myself so I should. + when I finally found something on the web about classes, it seemed to use prototype, but it didn't say it did. I was thinking js classes would be like as classes, but I don't know. Could someone tell me how you make classes, or direct me somewhere I can learn?

  2. #2
    Join Date
    Dec 2004
    Location
    UK
    Posts
    2,358
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Quote Originally Posted by ??? View Post
    I am wanting to make js classes, but I don't have any clue how.
    There are no classes in Javascript: it is a prototype-based language, not class-based. However, you can do something conceptually similar. I'll get to that in a moment.

    I heard lots of stuff about prototype.js ...
    As you are new to this subject, I would advise you to stay away from the Prototype library - I'd even advise you to do that if you weren't! It, and other frameworks, try to transform the language. Unless you understand precisely what they are doing, you may run into unexpected and unwanted behaviour.


    Whilst there are no classes, there are constructor functions, and the objects created by these can have a default set of members added. Hopefully that means something to you: it should if you're familiar with object-oriented concepts.

    A constructor function is little different from any other function. In fact, the only clues that you'll have without documentation is the convention of starting the function name with a capital letter - other functions should begin with lower-case letters - and the function may make use the this operator.

    Code:
    function MyObject() {
        this.member = 'value';
    }
    When a constructor function is invoked with the new operator, the this operator will refer to a new object. This allows you to modify the object.

    Code:
    var myObject = new MyObject();
    
    // myObject.member : 'value'
    All user-defined functions, as well as the built-in constructor functions like String and Number, have a property named prototype. It is an object. Whenever an object is created using a constructor function, the properties of the prototype object are effectively added to the object - the reality is more complicated, but we can come back to that later.

    Code:
    function MyObject() {
        /* Do nothing. */
    }
    MyObject.prototype.member = 'value';
    MyObject.prototype.method = function () {
        return this.member;
    };
    
    var myObject = new MyObject();
    myObject.method(); // 'value'
    If you have no problems with that, I'll move on to the prototype chain in a follow-up post, which will explain how the prototype object really works, and how it can be used to implement a form of inheritance.
    Mike

  3. #3
    Join Date
    May 2006
    Location
    Alaska
    Posts
    163
    Thanks
    5
    Thanked 2 Times in 2 Posts

    Default

    THANK YOU SO MUCH!!!! I made a thing that said lol when its created! I'm so excited!!!!!!

  4. #4
    Join Date
    Dec 2004
    Location
    UK
    Posts
    2,358
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Quote Originally Posted by ??? View Post
    THANK YOU SO MUCH!!!!
    So no problems or major questions so far? Good. If you do have any, or if you think I'm rushing over topics too quickly, do tell me so! Now is especially the time as I'm going to write about more technical issues. And of course, make sure you play around with the things I mention - I don't know about you, but I learn best by doing.


    I showed previously that by using the prototype object, newly-created objects can be given members. In fact, so long as the prototype object can be referenced, new members can be given to all "instances" even after creation!

    Code:
    function MyObject() {}
    MyObject.prototype.method = function () {
        return 'value';
    };
    
    var myObject = new MyObject();
    myObject.method(); // evaluates to 'value'
    
    
    MyObject.prototype.anotherMethod = function () {
        return 'another value';
    };
    
    myObject.anotherMethod(); // evaluates to 'another value';
    If you understand the concept of pointers or references, this shouldn't come as much of a surprise, though you might not have thought about it: objects, including the prototype object, are referenced, therefore any changes can be observed by anything that references that object.

    To break this chain, one can create a new object to act as a prototype, though we could still make changes if the old prototype object is referenced somewhere.

    Code:
    function MyObject() {}
    MyObject.prototype.method = function () {
        return 'value';
    };
    
    var a = new MyObject();
    typeof a.method; // evaluates to 'function'
    
    MyObject.prototype = new Object();
    MyObject.prototype.anotherMethod = function () {
        return 'another value';
    };
    
    var b = new MyObject();
    typeof a.method; // evaluates to 'function'
    typeof b.method; // evaluates to 'undefined'
    
    typeof a.anotherMethod; // evaluates to 'undefined'
    typeof b.anotherMethod; // evaluates to 'function'
    So, how does this isolation work? Every native object (and some host objects) has a hidden property named [[Prototype]]. When the object is created, the prototype object from the constructor function is assigned to that property. In this way, every object keeps track of its own prototype.

    Keep in mind that I wrote "every...object". This means that even the prototype for an object has a [[Prototype]] property. This, as you might guess, forms the prototype chain, an important concept surrounding objects. The chain always ends with the Object prototype object.

    Every time you use a member access operator (the dot [.] and square bracket operators), you use the prototype chain. Consider myObject.member. First, myObject is searched for a property named member. If no match is found, the search starts again with the object referenced by the [[Prototype]] property. This continues until [[Prototype]] is null, in which case the value, undefined is returned.

    The way in which the prototype chain search works allows one to override the value of a property on a given object: by assigning a value to a property, you actually create that property on the object.

    Code:
    function MyObject() {}
    MyObject.prototype.member = 0;
    
    var a = new MyObject();
    // At this point, the object, a, has no direct properties. They are all obtained from the
    // prototype chain.
    a.member; // evaluates to 0.
    MyObject.prototype.member = 5;
    a.member; // evaluates to 5.
    
    a.member = 9;
    // The object, a, now has its own property, member. A search for that property will now end
    // immediately.
    a.member; // evaluates to 9.

    You might have seen by now the scope for inheritance: by assigning an object to the prototype property of a constructor function, the objects created thereafter will "inherit" the members of that object. However, limitations quickly become obvious:

    Code:
    function Vehicle(maxSpeed) {
        this.maximumSpeed = maxSpeed;
    }
    Vehicle.prototype.shortestJourneyTime = function (distance) {
        return distance / this.maximumSpeed;
    };
    
    function Car(make, model) {
        /* ... */
    }
    Car.prototype = new Vehicle( /* No sensible value! */ );
    Whilst in the example above, Car "instances" will have a maximumSpeed property and a shortestJourneyTime method, creating the prototype object is rather nonsensical. Whilst the Car constructor function could (and should) be modified to include a speed argument, it does illustrate the fact that base objects cannot be configured in this way unlike in C++, for instance. Things are worse, of course, if the Vehicle constructor were to calculate a value.

    Of course, in a language as flexible as this, there are alternate forms of inheritance. When the constructor of the base object is of little or no importance, one can just copy methods on to the prototype.

    Code:
    Function.prototype.copyMethods = function (constructor) {
        for (var i = 1, n = arguments.length; i < n; ++i) {
            var propertyName = arguments[i];
            this.prototype[propertyName] = constructor.prototype[propertyName];
        }
    };
    
    Car.copyMethods(Vehicle, 'shortestJourneyTime');
    Adding to that, one can call the base object constructor in a similar way to constructors in Java and C++:

    Code:
    function Car(make, model, maxSpeed) {
        Vehicle.call(this, maxSpeed);
    
        /* ... */
    }
    Though this won't work on earlier IE versions without supporting code to emulate the call method.

    There's yet another approach, though I'd like to draw your attention to something else, first. You might have noticed in the examples so far that the constructor function doesn't return anything. As you might have guessed, this is normal. However, constructor functions can return values, though you'll rarely ever need to do so. There isn't much to say about this subject, except this: constructor functions can only return object references. Any other type, including null, is ignored and acts like returning this - the newly constructed object. However, if you do return an object reference, that reference is the result of evaluating the new expression:

    Code:
    function MyObject(object) {
        return object;
    }
    
    new MyObject('value'); // evaluates to a MyObject "instance".
    new MyObject(null); // evaluates to another MyObject "instance".
    new MyObject(document); // evaluates to a reference to the document host object.
    We can use this with our constructors: create a new Vehicle, modify it, and return it from Car!

    Code:
    function Car(make, model, maxSpeed) {
        var object = new Vehicle(maxSpeed);
    
        /* Add other members to object... */
        return object;
    }
    Unfortunately, this approach prevents us using the prototype object of Car.

    A lot to take in, I know. ECMAScript is more complicated than many people realise.

    I realise that began to ramble, but it's late here, and I'd like to get to sleep. Still, I hope you can make sense of what I've written.
    Mike

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •