Getters \ setters for dummies

后端 未结 12 2144
说谎
说谎 2020-11-22 04:55

I\'ve been trying to get my head around getters and setters and its not sinking in. I\'ve read JavaScript Getters and Setters and Defining Getters and Setters and just not g

相关标签:
12条回答
  • 2020-11-22 05:12

    Although often we are used to seeing objects with public properties without any access control, JavaScript allows us to accurately describe properties. In fact, we can use descriptors in order to control how a property can be accessed and which logic we can apply to it. Consider the following example:

    var employee = {
        first: "Boris",
        last: "Sergeev",
        get fullName() {
            return this.first + " " + this.last;
        },
        set fullName(value) {
            var parts = value.toString().split(" ");
            this.first = parts[0] || "";
            this.last = parts[1] || "";
        },
        email: "boris.sergeev@example.com"
    };
    

    The final result:

    console.log(employee.fullName); //Boris Sergeev
    employee.fullName = "Alex Makarenko";
    
    console.log(employee.first);//Alex
    console.log(employee.last);//Makarenko
    console.log(employee.fullName);//Alex Makarenko
    
    0 讨论(0)
  • 2020-11-22 05:13

    If you're referring to the concept of accessors, then the simple goal is to hide the underlying storage from arbitrary manipulation. The most extreme mechanism for this is

    function Foo(someValue) {
        this.getValue = function() { return someValue; }
        return this;
    }
    
    var myFoo = new Foo(5);
    /* We can read someValue through getValue(), but there is no mechanism
     * to modify it -- hurrah, we have achieved encapsulation!
     */
    myFoo.getValue();
    

    If you're referring to the actual JS getter/setter feature, eg. defineGetter/defineSetter, or { get Foo() { /* code */ } }, then it's worth noting that in most modern engines subsequent usage of those properties will be much much slower than it would otherwise be. eg. compare performance of

    var a = { getValue: function(){ return 5; }; }
    for (var i = 0; i < 100000; i++)
        a.getValue();
    

    vs.

    var a = { get value(){ return 5; }; }
    for (var i = 0; i < 100000; i++)
        a.value;
    
    0 讨论(0)
  • 2020-11-22 05:14

    You can define instance method for js class, via prototype of the constructor.

    Following is the sample code:

    // BaseClass
    
    var BaseClass = function(name) {
        // instance property
        this.name = name;
    };
    
    // instance method
    BaseClass.prototype.getName = function() {
        return this.name;
    };
    BaseClass.prototype.setName = function(name) {
        return this.name = name;
    };
    
    
    // test - start
    function test() {
        var b1 = new BaseClass("b1");
        var b2 = new BaseClass("b2");
        console.log(b1.getName());
        console.log(b2.getName());
    
        b1.setName("b1_new");
        console.log(b1.getName());
        console.log(b2.getName());
    }
    
    test();
    // test - end
    

    And, this should work for any browser, you can also simply use nodejs to run this code.

    0 讨论(0)
  • 2020-11-22 05:15

    Sorry to resurrect an old question, but I thought I might contribute a couple of very basic examples and for-dummies explanations. None of the other answers posted thusfar illustrate syntax like the MDN guide's first example, which is about as basic as one can get.

    Getter:

    var settings = {
        firstname: 'John',
        lastname: 'Smith',
        get fullname() { return this.firstname + ' ' + this.lastname; }
    };
    
    console.log(settings.fullname);
    

    ... will log John Smith, of course. A getter behaves like a variable object property, but offers the flexibility of a function to calculate its returned value on the fly. It's basically a fancy way to create a function that doesn't require () when calling.

    Setter:

    var address = {
        set raw(what) {
            var loc = what.split(/\s*;\s*/),
            area = loc[1].split(/,?\s+(\w{2})\s+(?=\d{5})/);
    
            this.street = loc[0];
            this.city = area[0];
            this.state = area[1];
            this.zip = area[2];
        }
    };
    
    address.raw = '123 Lexington Ave; New York NY  10001';
    console.log(address.city);
    

    ... will log New York to the console. Like getters, setters are called with the same syntax as setting an object property's value, but are yet another fancy way to call a function without ().

    See this jsfiddle for a more thorough, perhaps more practical example. Passing values into the object's setter triggers the creation or population of other object items. Specifically, in the jsfiddle example, passing an array of numbers prompts the setter to calculate mean, median, mode, and range; then sets object properties for each result.

    0 讨论(0)
  • 2020-11-22 05:16

    Getters and setters really only make sense when you have private properties of classes. Since Javascript doesn't really have private class properties as you would normally think of from Object Oriented Languages, it can be hard to understand. Here is one example of a private counter object. The nice thing about this object is that the internal variable "count" cannot be accessed from outside the object.

    var counter = function() {
        var count = 0;
    
        this.inc = function() {
            count++;
        };
    
        this.getCount = function() {
            return count;
        };
    };
    
    var i = new Counter();
    i.inc();
    i.inc();
    // writes "2" to the document
    document.write( i.getCount());
    

    If you are still confused, take a look at Crockford's article on Private Members in Javascript.

    0 讨论(0)
  • 2020-11-22 05:20

    Getters and Setters in JavaScript

    Overview

    Getters and setters in JavaScript are used for defining computed properties, or accessors. A computed property is one that uses a function to get or set an object value. The basic theory is doing something like this:

    var user = { /* ... object with getters and setters ... */ };
    user.phone = '+1 (123) 456-7890'; // updates a database
    console.log( user.areaCode ); // displays '123'
    console.log( user.area ); // displays 'Anytown, USA'
    

    This is useful for automatically doing things behind-the-scenes when a property is accessed, like keeping numbers in range, reformatting strings, triggering value-has-changed events, updating relational data, providing access to private properties, and more.

    The examples below show the basic syntax, though they simply get and set the internal object value without doing anything special. In real-world cases you would modify the input and/or output value to suit your needs, as noted above.

    get/set Keywords

    ECMAScript 5 supports get and set keywords for defining computed properties. They work with all modern browsers except IE 8 and below.

    var foo = {
        bar : 123,
        get bar(){ return bar; },
        set bar( value ){ this.bar = value; }
    };
    foo.bar = 456;
    var gaz = foo.bar;
    

    Custom Getters and Setters

    get and set aren't reserved words, so they can be overloaded to create your own custom, cross-browser computed property functions. This will work in any browser.

    var foo = {
        _bar : 123,
        get : function( name ){ return this[ '_' + name ]; },
        set : function( name, value ){ this[ '_' + name ] = value; }
    };
    foo.set( 'bar', 456 );
    var gaz = foo.get( 'bar' );
    

    Or for a more compact approach, a single function may be used.

    var foo = {
        _bar : 123,
        value : function( name /*, value */ ){
            if( arguments.length < 2 ){ return this[ '_' + name ]; }
            this[ '_' + name ] = value;
        }
    };
    foo.value( 'bar', 456 );
    var gaz = foo.value( 'bar' );
    

    Avoid doing something like this, which can lead to code bloat.

    var foo = {
        _a : 123, _b : 456, _c : 789,
        getA : function(){ return this._a; },
        getB : ..., getC : ..., setA : ..., setB : ..., setC : ...
    };
    

    For the above examples, the internal property names are abstracted with an underscore in order to discourage users from simply doing foo.bar vs. foo.get( 'bar' ) and getting an "uncooked" value. You can use conditional code to do different things depending on the name of the property being accessed (via the name parameter).

    Object.defineProperty()

    Using Object.defineProperty() is another way to add getters and setters, and can be used on objects after they're defined. It can also be used to set configurable and enumerable behaviors. This syntax also works with IE 8, but unfortunately only on DOM objects.

    var foo = { _bar : 123 };
    Object.defineProperty( foo, 'bar', {
        get : function(){ return this._bar; },
        set : function( value ){ this._bar = value; }
    } );
    foo.bar = 456;
    var gaz = foo.bar;
    

    __defineGetter__()

    Finally, __defineGetter__() is another option. It's deprecated, but still widely used around the web and thus unlikely to disappear anytime soon. It works on all browsers except IE 10 and below. Though the other options also work well on non-IE, so this one isn't that useful.

    var foo = { _bar : 123; }
    foo.__defineGetter__( 'bar', function(){ return this._bar; } );
    foo.__defineSetter__( 'bar', function( value ){ this._bar = value; } );
    

    Also worth noting is that in the latter examples, the internal names must be different than the accessor names to avoid recursion (ie, foo.bar calling foo.get(bar) calling foo.bar calling foo.get(bar)...).

    See Also

    MDN get, set, Object.defineProperty(), __defineGetter__(), __defineSetter__()
    MSDN IE8 Getter Support

    0 讨论(0)
提交回复
热议问题