Javascript getters和setters for dummies?

128 javascript getter setter

我一直在努力让自己的头脑能够吸引人并且不会陷入其中.我已经阅读过JavaScript Getters and SettersDefining Getters and Setters而且还没有得到它.

有人可以明确说明:

  1. 什么是吸气剂和制定者的意图,以及
  2. 举几个非常简单的例子?

Mat*_*ley 98

除了@ Sii的答案,setter还可用于更新其他值.

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

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

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

现在,您可以设置fullName,并firstlast将被更新,反之亦然.

  • MS不能正确地支持JS并且它们不会让他们的银光在任何地方运行真的很痛苦,所以我必须对所有内容进行两次编程,一次用于SL,一次用于世界其他地方:) (8认同)
  • @Akash:不,虽然,Internet Explorer 9确实支持可以定义getter和setter的更新的`Object.defineProperty`函数. (2认同)
  • @Martin:您可以使用与[John的答案]相同的技术将它们设为私有(http://stackoverflow.com/questions/812961/javascript-getters-and-setters-for-dummies/813227#813227).如果你想使用真正的getter/setter,你必须使用`this .__ defineGetter__`或更新的`Object.defineProperty`函数. (2认同)

mil*_*ose 58

例如,您可以使用它们来实现计算属性.

例如:

function Circle(radius) {
    this.radius = radius;
}

Object.defineProperty(Circle.prototype, 'circumference', {
    get: function() { return 2*Math.PI*this.radius; }
});

Object.defineProperty(Circle.prototype, 'area', {
    get: function() { return Math.PI*this.radius*this.radius; }
});

c = new Circle(10);
console.log(c.area); // Should output 314.159
console.log(c.circumference); // Should output 62.832
Run Code Online (Sandbox Code Playgroud)

(CodePen)


Bee*_*jor 56

JavaScript中的Getters和Setter

概观

JavaScript中的getter和setter用于定义计算属性访问器.计算属性是使用函数来获取或设置对象值的属性.基本理论是做这样的事情:

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'
Run Code Online (Sandbox Code Playgroud)

这对于在访问属性时自动执行幕后操作非常有用,例如保持数字在范围内,重新格式化字符串,触发值已更改事件,更新关系数据,提供对私有属性的访问等等.

下面的示例显示了基本语法,尽管它们只是获取并设置内部对象值而不做任何特殊操作.在实际情况下,您可以修改输入和/或输出值以满足您的需求,如上所述.

获取/设置关键字

ECMAScript 5支持getset关键字用于定义计算属性.它们适用于除IE 8及更低版本之外的所有现代浏览器.

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

自定义吸气剂和二传手

get并且set不是保留字,因此可以重载它们以创建您自己的自定义跨浏览器计算属性函数.这适用于任何浏览器.

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' );
Run Code Online (Sandbox Code Playgroud)

或者对于更紧凑的方法,可以使用单个功能.

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' );
Run Code Online (Sandbox Code Playgroud)

避免做这样的事情,这会导致代码膨胀.

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

对于上面的示例,内部属性名称用下划线抽象,以阻止用户简单地执行foo.barvs foo.get( 'bar' )和获取"未烹饪"值.您可以使用条件代码执行不同的操作,具体取决于要访问的属性的名称(通过name参数).

Object.defineProperty()

使用Object.defineProperty()是另一种添加getter和setter的方法,可以在定义后用于对象.它还可用于设置可配置和可枚举的行为.此语法也适用于IE 8,但遗憾的是仅适用于DOM对象.

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

__defineGetter __()

最后,__defineGetter__()是另一种选择.它已被弃用,但仍在网络上广泛使用,因此不太可能很快消失.它适用于IE 10及以下版本的所有浏览器.虽然其他选项在非IE上也很有效,但是这个选项并没有那么有用.

var foo = { bar : 123; }
foo.__defineGetter__( 'bar', function(){ return this.bar; } );
foo.__defineSetter__( 'bar', function( value ){ this.bar = value; } );
Run Code Online (Sandbox Code Playgroud)

也可以看看

MDN get,set, Object.defineProperty(),__ undefineGetter __(),__ undefineSetter __()
MSDN IE8 Getter支持

  • 设置/获取名称必须与属性名称不同。因此,代替 ```bar: 123``` 和 ```this.bar = value``` 等,例如将它们更改为 ```_bar ```。参见:https://www.hongkiat.com/blog/getters-setters-javascript/ (2认同)

roj*_*ojo 14

很抱歉重新提出一个旧问题,但我想我可能会提供一些非常基本的例子和for dummies解释.所发布的其他答案都没有说明像MDN指南的第一个例子那样的语法,它与人们可以获得的基本一样.

消气:

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

console.log(settings.fullname);
Run Code Online (Sandbox Code Playgroud)

... John Smith当然会记录.一吸气就像一个变量对象的属性,但提供了一个功能,实时计算其返回值的灵活性.它基本上是一种创建一个在调用时不需要()的函数的奇特方法.

二传手:

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);
Run Code Online (Sandbox Code Playgroud)

...将登录New York到控制台.像getter一样,setter的调用方法与设置object属性的值相同,但是在没有()的情况下调用函数是另一种奇特的方式.

请参阅此jsfiddle以获得更全面,更实际的示例.将值传递到对象的setter会触发其他对象项的创建或填充.具体来说,在jsfiddle示例中,传递一个数字数组会提示setter计算平均值,中位数,模式和范围; 然后为每个结果设置对象属性.


Joh*_*ohn 11

只有拥有类的私有属性时,getter和setter才真正有意义.由于Javascript实际上没有您通常从面向对象语言中想到的私有类属性,因此很难理解.这是私人柜台对象的一个​​例子.关于这个对象的好处是无法从对象外部访问内部变量"count".

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());
Run Code Online (Sandbox Code Playgroud)

如果您仍然感到困惑,请查看Crockford 在Javascript中关于私人会员的文章.

  • 我不同意.getter和setter对于封装信息非常有用,这些信息的定义可能不仅仅是一个简单的变量.如果您需要更改以前使用简单属性以及其他可能依赖的系统的行为,则可以很方便.此外,您的示例仅演示"伪getters",它们只是函数.真正的JavaScript getter*作为简单值出现*(并且无需函数表示法访问),因此它们的真正威力. (39认同)

mat*_*t b 7

我认为您链接的第一篇文章非常明确地说明了这一点:

以这种方式编写JavaScript的明显优势在于,您可以使用它不希望用户直接访问的模糊值.

这里的目标是通过仅允许通过get()或set()方法访问字段来封装和抽象字段.这样,您可以以任何方式在内部存储字段/数据,但外部组件仅在您发布的界面之外.这允许您在不更改外部接口的情况下进行内部更改,在set()方法中进行一些验证或错误检查等.


Mic*_*ski 6

虽然我们常常习惯于在没有任何访问控制的情况下查看具有公共属性的对象,但JavaScript允许我们准确地描述属性.实际上,我们可以使用描述符来控制如何访问属性以及我们可以应用于哪个逻辑.请考虑以下示例:

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"
};
Run Code Online (Sandbox Code Playgroud)

最终结果:

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
Run Code Online (Sandbox Code Playgroud)