Sammy Blake
Sammy Blake

Reputation: 25

JavaScript: Using Object.defineProperties()

I'm trying to learn how to use Object.defineProperties(). I'm using the following code:

var Person = function(firstName, lastName)
{
    this.firstName = firstName;
    this.lastName = lastName;
};

Object.defineProperties(Person, {
    sayHi : {
        get : function() {return "Hello";},
        enumerable : true
    },
    sayBye : {
        get : function() {return "Bye";},
        enumerable : true
    }
});


var john = new Person('John', 'Doe');
console.log(john.sayHi());

But I keep getting:

TypeError: john.sayHi is not a function
console.log(john.sayHi());

Can someone tell me what is wrong with this code?

Thanks

Upvotes: 0

Views: 266

Answers (2)

laruiss
laruiss

Reputation: 3816

Well, you are not defining sayHi as a function. This is how to define it as a function:

var Person = function(firstName, lastName)
{
    this.firstName = firstName;
    this.lastName = lastName;
};
// Define the properties on the prototype, not the Person object itself
Object.defineProperties(Person.prototype, {
    sayHi : {
        get : function() {
          return function() {
            return "Hello, I am " + this.firstName + " " + this.lastName;
          };
        },
        enumerable : true
    },
    sayBye : {
        get : function() {
          return function() {
            return "Bye";
          };
        },
        enumerable : true
    }
});

var john = new Person('John', 'Doe');
console.log(john.sayHi());
console.log(john.sayBye());

To be precise: in your code, john.sayHi returns the "Hello" string, which is a string primitive, and therefore definitely not a function ;-)

The get function for the property must return a function in order to achieve what you want.

To give you a longer answer, see this following other implementation, taking fully advantage of two things: first the new features from ES5 (Object.create()) and ES6 (Object.defineProperties()) and the prototypal nature of JS (no use of new operator, prototypal inheritance):

var Person = {
    init: function(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
};

Object.defineProperties(Person, {
    sayHi : {
        get : function() {return function() {return "Hello, I am " + this.firstName + " " + this.lastName;}},
        enumerable : true
    },
    sayBye : {
        get : function() {return function() {return "Bye";};},
        enumerable : true
    }
});

var Employee = Object.create(Person); // Employee inherits from Person

Employee.init = function(firstName, lastName, position) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.position = position;
};

Object.defineProperties(Employee, {
    introduce : {
        get : function() {return function() {
            return this.sayHi() + ", " + this.position;
        }},
        enumerable : true
    },
    farewell : {
        get: function() {return function() {
            return this.sayBye() + ", it was a pleasure to meet you";
        }},
        enumerable: true
    }
});

var john = Object.create(Employee); // john inherits from Employee
john.init('John', 'Doe', 'Manager');

console.log(john.sayHi()); // Inherited from Person
console.log(john.introduce()); // Inherited from Employee
console.log(john.sayBye()); // Inherited from Person
console.log(john.farewell()); // Inherited from Employee

JSFIddle demo

Upvotes: 3

Sebri Zouhaier
Sebri Zouhaier

Reputation: 745

Replace

get : function() {return "Hello";}   with

get : function() {return function() {return "Hello";};}

Upvotes: 1

Related Questions