Solved

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

Posted on 2014-03-03
18
249 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
ID: 39902621
Hmm.. if there was a suggested solution, I'm not seeing it. :(
0
 
LVL 25

Expert Comment

by:Kyle Hamilton
ID: 39903145
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
ID: 39903717
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
The New “Normal” in Modern Enterprise Operations

DevOps for the modern enterprise offers many benefits — increased agility, productivity, and more, but digital transformation isn’t easy, especially if you’re not addressing the right issues. Register for the webinar to dive into the “new normal” for enterprise modern ops.

 
LVL 25

Expert Comment

by:Kyle Hamilton
ID: 39903861
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
ID: 39903904
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
ID: 39904072
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
ID: 39904134
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 34

Expert Comment

by:Slick812
ID: 39904519
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
 
LVL 25

Expert Comment

by:Kyle Hamilton
ID: 39904579
@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
ID: 39904614
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
ID: 39904623
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
ID: 39904644
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
ID: 39904650
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
ID: 39904856
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
ID: 39904862
Excellent, Kyle, nailed it!! Many thanks for your help!
0
 
LVL 25

Expert Comment

by:Kyle Hamilton
ID: 39904894
:)
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

I hope you'll find this tutorial useful and interesting. So let's try to extend Tcl with a new package.  For anyone more deeply interested please check out the book "Practical Programming in Tcl and Tk". It's really one of the best written books abo…
JavaScript can be used in a browser to change parts of a webpage dynamically. It begins with the following pattern: If condition W is true, do thing X to target Y after event Z. Below are some tips and tricks to help you get started with JavaScript …
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

861 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