5

I am familiar with strongly typed OOP language such as C# and Java, so I am a little confused with Javascript. I want my class to be encapsulated, for example:

function Human() {
    var _name = '';
    var _nameChangeCounter = 0;
}

Human.constructor = Human;
Human.prototype = Object.create(Animal);

As you can see, Human extends the Animal class. Now I need a getter and setter for Name, and a getter for NameChangeCounter. In the setter of Name, it should increase the NameChangeCounter. I looked up how to make getter and setter in Javascript in this question:

Name.prototype = {
    get fullName() {
        return this.first + " " + this.last;
    },

    set fullName(name) {
        var names = name.split(" ");
        this.first = names[0];
        this.last = names[1];
    }
};

However, now that prototype is taken for inheritance, how can I do it? Do I have to do the Java-style (create getName, setName, getNameChangeCounter functions)? How do properties like window.location.href implemented?

Community
  • 1
  • 1
Luke Vo
  • 17,859
  • 21
  • 105
  • 181
  • 1
    *window* is a host object, it is setup however an implementation wishes to set it up. It isn't necessarily (or even likely) setup using a constructor. It's similar to built-in objects like *Math* or *Date* that just *are*. – RobG May 01 '14 at 13:39
  • You can have a look at the [Mozilla JS documentation about classes and inheritance](https://developer.mozilla.org/en-US/Add-ons/SDK/Guides/Contributor_s_Guide/Classes_and_Inheritance) and at the free book [Eloquent JavaScript](http://eloquentjavascript.net/). I found them very informative and helpful. – keenthinker May 01 '14 at 13:52
  • Don't mess DOM with JS ... they are different things ... DOM has lots of "native code". – rafaelcastrocouto May 01 '14 at 13:59
  • `Human.prototype = Object.create(Animal)` is not good form. Object.create(Animal) already returns an object with the prototype set to Animal. You have created a 2-long prototype chain with Human.prototype.prototype === Animal. Human.prototype is pointing to an empty object whose prototype then points to Animal. All you need is Human = Object.create(Animal). – mastaBlasta May 06 '14 at 16:27

3 Answers3

3

This works for me:

function Name(){
    this.first = '';
    this.last = '';
}

Name.prototype.getFullName = function() {
    return this.first + ' ' + this.last;
}

Name.prototype.setFullName = function(fullName){
    var names = fullName.split(" ");
    this.first = names[0];
    this.last = names[1];
}


function Human() {
    var name = new Name(), 
        counter = 0;
    Object.defineProperty(this, 'name', {
        configurable: true,
        enumerable: true,
        get: function(){
            return name;
        },
        set: function(fullName){
            name.setFullName(fullName);
        }
    });
    Object.defineProperty(this, 'counter', {
        configurable:true,
        enumerable: true,
        get: function(){
            return counter;
        },
        set: function(value){
            counter = value;
        }
    });
}

var luke = new Human();
luke.name = 'Luke Skywalker';

console.log(luke.name.first); //Luke
console.log(luke.name.last); //Skywalker
console.log(luke.name.getFullName()); //Luke Skywalker
console.log(luke.name); //Object

luke.name = 'Peter Parker';
console.log(luke.name.first); //Peter
console.log(luke.name.last); //Parker
console.log(luke.name.getFullName()); //Peter Parker
Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
1

Found this function on mdn: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Summary

Here is an example fiddle: http://jsfiddle.net/EfyCX/1/

And here is some javascript for getters and setters using Object.defineProperties

Object.defineProperties(Person.prototype, {
    "name": {
        get: function() { return this._name },
        set: function(name) { 
            this.changeCount++
            this._name = name
        }
    }
})
bottens
  • 3,834
  • 1
  • 13
  • 15
-2

You're trying to use a classical inheritance in a prototype based language. In javascript there are no Class definitions and Class instances. There are only static objects, that share methods through a prototype chain.

To make objects that inherit from Animal:

var Animal = {vertebrae: "jelly"};
var Human = Object.create(Animal)

console.log(Human.vertebrae); //=> jelly

To make objects that inherit from Human

var programmer = Object.create(Human);
console.log(programmer.vertebrae); //=> jelly

Some JS authorities (mainly Crockford) discourage overriding the standard get and set methods, unless you absolutely know what you're doing.

Also important to note that JS does not have private properties, and that functionality can be achieved by use of an outer function scope and closure. Search for javascript private properties.

To add methods to Human

Human._name = 'Human';
Human.getName = function(){ return this._name; }
Human.setName = function(val){ this._name = val; }

console.log(programmer.getName()); //=> 'Human'

programmer.setName("Bob");
console.log(programmer.getName()); //=> 'Bob'
console.log(Human.getName()); //=> 'Human'
console.log(Animal.getName()); //=> not a function

you can use the properties object if you like to set the methods when doing Object.create(), but that syntax is unfortunately verbose.

mastaBlasta
  • 5,700
  • 1
  • 24
  • 26