傻瓜的吸气剂\设定者

问题描述 投票:123回答:12

我一直试图让我的头围绕着吸气剂和二传手并且它没有下沉。我读过JavaScript Getters and SettersDefining Getters and Setters并且没有得到它。

有人可以明确说明:

  1. 什么是吸气剂和制定者的意图,以及
  2. 举几个非常简单的例子?
javascript setter getter
12个回答
94
投票

除了@Sii's answer之外,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];
    }
};

现在,您可以设置fullNamefirstlast将更新,反之亦然。

n = new Name('Claude', 'Monet')
n.first # "Claude"
n.last # "Monet"
n.fullName # "Claude Monet"
n.fullName = "Gustav Klimt"
n.first # "Gustav"
n.last # "Klimt"

2
投票

我也对explanation I read感到有些困惑,因为我试图将一个属性添加到我没写过的现有原型中,所以替换原型似乎是错误的方法。所以,对于后代,这是我如何将last属性添加到Array

Object.defineProperty(Array.prototype, "last", {
    get: function() { return this[this.length - 1] }
});

比添加功能恕我直言更好一点。


1
投票

如果您指的是访问器的概念,那么简单的目标是隐藏底层存储以防任意操作。最极端的机制是

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();

如果您指的是实际的JS getter / setter功能,例如。 defineGetter / defineSetter,或{ get Foo() { /* code */ } },那么值得注意的是,在大多数现代引擎中,这些属性的后续使用将比其他情况慢得多。例如。比较性能

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

var a = { get value(){ return 5; }; }
for (var i = 0; i < 100000; i++)
    a.value;

-1
投票

我有一个可能有点难看的人,但它确实可以跨平台完成

function myFunc () {

var _myAttribute = "default";

this.myAttribute = function() {
    if (arguments.length > 0) _myAttribute = arguments[0];
    return _myAttribute;
}
}

这样,当你打电话的时候

var test = new myFunc();
test.myAttribute(); //-> "default"
test.myAttribute("ok"); //-> "ok"
test.myAttribute(); //-> "ok"

如果你真的想要加油......你可以插入一个类型的支票:

if (arguments.length > 0 && typeof arguments[0] == "boolean") _myAttribute = arguments[0];
if (arguments.length > 0 && typeof arguments[0] == "number") _myAttribute = arguments[0];
if (arguments.length > 0 && typeof arguments[0] == "string") _myAttribute = arguments[0];

或使用先进的类型检查更加疯狂:type.of() code at codingforums.com


57
投票

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

例如:

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

(CodePen)


53
投票

Getters and Setters in JavaScript

概观

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'

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

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

获取/设置关键字

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;

自定义吸气剂和二传手

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

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' );

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

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' );

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

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

对于上面的示例,内部属性名称用下划线抽象,以阻止用户简单地执行foo.barfoo.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;

__defineGetter __()

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

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

也可以看看

MDN getsetObject.defineProperty()__defineGetter__()__defineSetter__() MSDN IE8 Getter Support


14
投票

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

消气:

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

console.log(settings.fullname);

...当然会记录John Smith。 getter的行为类似于变量对象属性,但提供了函数的灵活性,可以动态计算其返回值。它基本上是一种创建一个在调用时不需要()的函数的奇特方法。

二传手:

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);

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

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


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());

如果你仍然感到困惑,请看看Crockford关于Private Members in Javascript的文章。


6
投票

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

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

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


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: "[email protected]"
};

最终结果:

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

2
投票

令人困惑的是...... getter是当你设置一个属性,setter时调用的函数。例如,如果你这样做

obj.prop = "abc";

你正在设置属性prop,如果你正在使用getter / setter,那么将调用setter函数,并以“abc”作为参数。理想情况下,对象内部的setter函数定义如下所示:

set prop(var) {
   // do stuff with var...
}

我不确定在各种浏览器中实现的效果如何。似乎Firefox也有一种替代语法,使用双重下划线特殊(“魔术”)方法。像往常一样,Internet Explorer不支持任何此类操作。


2
投票

您可以通过构造函数的原型为js类定义实例方法。

以下是示例代码:

// 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

而且,这适用于任何浏览器,您也可以简单地使用nodejs来运行此代码。

© www.soinside.com 2019 - 2024. All rights reserved.