Solved

How to create Accessor methods (getter/setter) with my constructor

Posted on 2014-03-03
18
238 Views
Last Modified: 2014-03-04
I know how to define getter/setters with in object literal mode, e.g.:

var person = {
    ...
    get firstName() {
        return firstName;
    },
    set firstName(value) {
        firstName = value;
    }
    ...
}

Open in new window


What I'd like to know is how to make a getter/setter on this following constructor. Thanks.

function Person(firstName, lastName) {
    /**
     * Private properties and methods
     */
    var _firstName = firstName == undefined ? "" : firstName; // private
    var _lastName = lastName == undefined ? "" : lastName; // private
    var initials = function(_firstName, _lastName) { // private
            return _firstName.substr(0,1) + " " + _lastName.substr(0,1);
        };
    /**
     * Public properties and methods
     */
    this.firstName = _firstName; // [How do turn firstName and lastName into getters/setters?]
    this.lastName = _lastName;
    
    this.toString = function() {
        return firstName + " " + lastName;
    };
    this.toStringInitials = function() {
        return initials(_firstName, _lastName);
    };
};

var p = new Person("John", "Doe");
var p2 = new Person("Jane", "Dopey");

Open in new window

0
Comment
Question by:elepil
  • 9
  • 6
18 Comments
 

Author Comment

by:elepil
Comment Utility
Hmm.. if there was a suggested solution, I'm not seeing it. :(
0
 
LVL 25

Expert Comment

by:Kyle Hamilton
Comment Utility
function Person(firstName, lastName) {
    /**
     * Private properties and methods
     */
    var _firstName = firstName == undefined ? "" : firstName; // private
    var _lastName = lastName == undefined ? "" : lastName; // private
    var initials = function(_firstName, _lastName) { // private
            return _firstName.substr(0,1) + " " + _lastName.substr(0,1);
        };
    /**
     * Public properties and methods
     */
    this.getFirstName = function (){
        return _firstName;
    }
    this.getLastName = function (){
        return _lastName;
    }
    this.setFirstName = function (firstName){
        _firstName = firstName;
    }
    this.setLastName = function (lastName){
        _lastName = lastName;
    }
    
    this.toString = function() {
        return _firstName + " " + _lastName;
    };
    this.toStringInitials = function() {
        return initials(_firstName, _lastName);
    };
};

var p = new Person("John", "Doe");
var p2 = new Person("Jane", "Dopey");
p.getFirstName()
"John"
p.setFirstName("Sally")
p.getFirstName()
"Sally"

Open in new window

0
 

Author Comment

by:elepil
Comment Utility
Kyle, thanks for responding.

I knew how to create getter and setter functions the way you did, and as much as it works, it is not "true-to-form" to JavaScript getters/setters and is not what I was looking for.

If you look at my original post at the very top, I actually gave a sample of get/set syntax in object literal mode. The 'get' and 'set' you see are actual keywords in JavaScript. What I wanted to know was how to define, using the Javascript get/set keywords, in NON-object literal mode (in this case, a function).

Thanks.
0
 
LVL 25

Expert Comment

by:Kyle Hamilton
Comment Utility
not sure what you mean by "not-true-to-form". That is the way public methods are written in javascript.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_Getters_and_Setters
0
 
LVL 25

Expert Comment

by:Kyle Hamilton
Comment Utility
You might want to have a look at this article as well, which describes some getter/setter syntaxes:

http://whereswalden.com/2010/04/16/more-spidermonkey-changes-ancient-esoteric-very-rarely-used-syntax-for-creating-getters-and-setters-is-being-removed/
0
 

Author Comment

by:elepil
Comment Utility
Kyle, what I meant by "not-true-to-form" is that you used "getFirstName/setFirstName" instead of the JavaScript keywords get and set. I was trying to create a getter/setter using those keywords because they have the added advantage of being able to access the property without seeing the words get and set. For example, if you defined the following in object literal form:

var Person = {
    _firstName: "John",
    get firstName () {
       return "First Name";
    },
    set firstName(value) {
        _firstName = value;
    }
}

You would access the firstName property as:

var p = Person();
console.log(p.firstName);

But the way you did it was define functions called getFirstName and setFirstName. That means, to access them, you'd have to say:

var p = Person();
console.log(p.getFirstName);

Do you see the distinction I am making? You did it the Java way, which is the way I'd do it in Java, too. But certain languages like Actionscript and JavaScript have the get/set constructs especially designed for getter/setters that Java doesn't have.
0
 
LVL 25

Expert Comment

by:Kyle Hamilton
Comment Utility
I hear you. I just don't think those keywords are available for functions. Though I'm sure you could do some fancy shenanigans to extend your functions with ObjectProperties or some other construct. I think it will make the code unreadable without bringing any real advantage.

If you want to use p.firstName, then you might as well write this.firstName = firstName; Making first name and last name private doesn't give you much if you are going to offer public setters for them. If you are concerned about encapsulation, any processing of first and last name can still be done in the Person object without the need for your library users to know anything about it.

If you look over the the second link I posted, the syntax you would like to use is not "recommended".

I would write it like this, since for me, it's a lot easier to read and maintain, but that is just a personal preference. I hate arguing about coding. You are welcome to "request attention" to get more eyes on this.

function Person(firstName, lastName) {

    this.firstName = firstName == undefined ? "" : firstName;
    this.lastName = lastName == undefined ? "" : lastName;
    var initials = function() { // private
            return this.firstName.substr(0,1) + " " + this.lastName.substr(0,1);
        };

    this.toString = function() {
        return this.firstName + " " + this.lastName;
    };
    this.toStringInitials = function() {
        return initials();
    };
};

Open in new window

0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
hey, I tried and tried to get the p.firstName to be an Object reference for an Object that has the
get firstName()

but I could not do it, after failing for many different tries, I believe (for me anyway) to use an OO and have both names (first, last) in a names object, Not really a solution, but a workable to have an interactive (many values in function object changed) by simply assigning a value (no function call);

function Person2(firstName1, lastName1) {
    /* Private properties and methods */
    var _firstName = firstName1 == undefined ? "" : firstName1; // private
    var _lastName = lastName1 == undefined ? "" : lastName1; // private
    var initials = function(_firstName, _lastName) { // private
            return _firstName.substr(0,1) + " " + _lastName.substr(0,1);
        };

  this.names = {count:1,  // object
  get first() {
    return _firstName;
    },
  set first(value) {
    this.count++;
    _firstName = value+this.count;
    },
  get last() {
    return _lastName;
    },
    set last(value) {
	this.count++;
    _lastName = value+this.count;
    }
};

  this.toString = function() {
        return _firstName + " " + _lastName;
    };
  this.toStringInitials = function() {
        return initials(_firstName, _lastName);
    };
};

var p = new Person2("KILohn", "DoeJoke");

p.names.first = "New Name";
p.names.last = "How IT";
document.write("Names = "+p.names.first+" - "+p.names.last);

Open in new window

Just a way, but the functions are different than the objects for containing some operations.
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 25

Expert Comment

by:Kyle Hamilton
Comment Utility
@Slick812,

What advantage does this offer? Why are we trying to force the get set keywords?

Why is p.names.first better than p.getFirstName ?

I'm not being a jerk, I really would like to know what the benefit is.

The comments in this Ajaxian article are also pretty mixed:
http://ajaxian.com/archives/getters-and-setters-in-javascript
0
 
LVL 25

Accepted Solution

by:
Kyle Hamilton earned 500 total points
Comment Utility
OK, I take everything I said before back.

Here's how you do it:

function Field(val){
    var value = val;
   
    this.__defineGetter__("value", function(){
        return value;
    });
   
    this.__defineSetter__("value", function(val){
        value = val;
    });
}

Open in new window


// setter
Field.value = "hi"

// getter
Field.value 

Open in new window


taken from John Resig's blog:
http://ejohn.org/blog/javascript-getters-and-setters/

(You might want to double check compatibility across browsers)
0
 

Author Comment

by:elepil
Comment Utility
Kyle,

The this.firstName = firstName, while it works, would not be using getters/setters. The reason why that is important to me is because my application will very possibly need to throw an event when a property value is changed so that those that are listening can react accordingly, and that's not possible if you don't set up a setter function.

Maybe you're right, that there's no way to use the get/set keywords in a function. I'm new to this, and that's why I created this post, to try to learn from those more experienced than I am like yourself. I hate using the Object.defineProperty because the sequence of code becomes bizarre where I'd have to instantiate an object first, and then apply Object.defineProperty for each of the properties. I have experimental code that tells me this has its own problems as well. I guess I just want to implement OOP and still keep things simple (as in Java, C#, etc.), and that is getting to be problematic with JavaScript.
0
 
LVL 25

Expert Comment

by:Kyle Hamilton
Comment Utility
having said that, I'm still not sure about the wisdom of doing this.

The user of your library may get unexpected results if you process their values. I would expect that when I set Field.value, that value will not be changed. This is along the lines of modifying native functionality, for example messing with Object.prototype

I still think it is a lot clearer to provide explicit getter or setter methods. no confusion.
0
 
LVL 25

Expert Comment

by:Kyle Hamilton
Comment Utility
Hi elepil, maybe we posted at the same time. did you see the John Resig example above?

correction to above post:

var v = new Field();
v.value = "whatever"
console.log(v.value);
0
 

Author Comment

by:elepil
Comment Utility
You did it, Kyle! Your solution is the only one that meets all criteria of a typical OOP object as we know with languages such as Java, C#, etc. Here's a more elaborate code sample expounding on your solution:

function Person(firstName, lastName, gender){
    /**
     * Private properties and methods
     */
    var _firstName = firstName; // private property
    var _lastName = lastName; // private property
    var _initials = function() { // private method
        return _firstName.substr(0,1) + " " + _lastName.substr(0,1);
    }
    
    /**
     * Public properties and methods
     */
    this.gender = gender; // public

    // public getter/setters for firstName and lastName
    this.__defineGetter__("firstName", function(){
        return _firstName;
    });
   
    this.__defineSetter__("firstName", function(value){
        _firstName = value;
    });

    this.__defineGetter__("lastName", function() {
        return _lastName;
    });
    
    this.__defineSetter__("lastName", function(value) {
        _lastName = value;
    })
    
    // Public methods
    this.toString = function() {
        return _firstName + " " + _lastName;
    }
    
    this.toStringInitials = function() {
        return _initials();
    }
} 

var p1 = new Person("John", "Doe", "M");
var p2 = new Person("Jane", "Bimbo", "F");

console.log(p1.firstName);
console.log(p2.lastName);
console.log(p1.toString());
console.log(p2.toStringInitials());

Open in new window


As far as I can tell, your solution provides the ability to simulate the creation of an OOP data model as used with languages like Java, C#, etc.

It allows definition of private and public properties/methods, as well as providing definition of properties by way of getters/setters.

Thanks for your help!
0
 

Author Closing Comment

by:elepil
Comment Utility
Excellent, Kyle, nailed it!! Many thanks for your help!
0
 
LVL 25

Expert Comment

by:Kyle Hamilton
Comment Utility
:)
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Having worked on larger scale sites, we found out that you are bound to look at more scalable solutions to integrating widgets, code snippets or complete applications and mesh them into functional sites, in any given composition. To share some of…
This article will show, step by step, how to integrate R code into a R Sweave document
Learn the basics of if, else, and elif statements in Python 2.7. Use "if" statements to test a specified condition.: The structure of an if statement is as follows: (CODE) Use "else" statements to allow the execution of an alternative, if the …
Learn the basics of modules and packages in Python. Every Python file is a module, ending in the suffix: .py: Modules are a collection of functions and variables.: Packages are a collection of modules.: Module functions and variables are accessed us…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now