我一直在努力让自己的目标围绕着吸气剂和二传手而不是沉没。我已经阅读了JavaScript Getters and Setters和Defining Getters and Setters并且没有得到它。
有人可以明确说明:
答案 0 :(得分:91)
除了@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];
}
};
现在,您可以设置fullName
,first
和last
将会更新,反之亦然。
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"
答案 1 :(得分: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
答案 2 :(得分:53)
JavaScript中的getters和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支持get
和set
关键字来定义计算属性。它们适用于除IE 8及以下版本的所有现代浏览器。
var foo = {
bar : 123,
get bar(){ return bar; },
set bar( value ){ this.bar = value; }
};
foo.bar = 456;
var gaz = foo.bar;
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' );
或者对于更紧凑的方法,可以使用单个函数。
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.bar
与foo.get( 'bar' )
并获得&#34;未烹饪&#34;值。您可以使用条件代码执行不同的操作,具体取决于所访问属性的名称(通过name
参数)。
使用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__()
是另一种选择。它已被弃用,但仍在网络上广泛使用,因此不太可能很快消失。它适用于IE 10及以下版本的所有浏览器。虽然其他选项在非IE上也很有效,但是这个选项并不是很有用。
var foo = { bar : 123; }
foo.__defineGetter__( 'bar', function(){ return this.bar; } );
foo.__defineSetter__( 'bar', function( value ){ this.bar = value; } );
MDN get,set,
Object.defineProperty(),__defineGetter__(),__defineSetter__()
MSDN
IE8 Getter Support
答案 3 :(得分:14)
很抱歉重新提出一个旧问题,但我想我可能会提供一些非常基本的例子和假人解释。所发布的其他答案都没有说明像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一样,使用与设置对象属性值相同的语法来调用 setters ,但这是另一种在没有()的情况下调用函数的奇特方式。
请参阅this jsfiddle以获得更全面,更实际的示例。将值传递到对象的 setter 会触发其他对象项的创建或填充。具体来说,在jsfiddle示例中,传递一个数字数组会提示setter计算平均值,中位数,模式和范围;然后为每个结果设置对象属性。
答案 4 :(得分: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的文章。
答案 5 :(得分:6)
我认为您链接的第一篇文章非常明确地说明了这一点:
以这种方式编写JavaScript的一个明显优势是,您可以使用它不希望用户直接访问的模糊值。
这里的目标是通过只允许通过get()或set()方法访问字段来封装和抽象字段。这样,您可以以任何方式在内部存储字段/数据,但外部组件仅在您发布的界面之外。这允许您在不更改外部接口的情况下进行内部更改,在set()方法中进行一些验证或错误检查等。
答案 6 :(得分: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"
};
最终结果:
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
答案 7 :(得分:2)
令人困惑的是...... getter是当你设置一个属性,setter时调用的函数。 例如,如果你这样做
obj.prop = "abc";
你正在设置属性prop,如果你使用getter / setter,那么将调用setter函数,并以“abc”作为参数。 对象内部的setter函数定义理想情况如下:
set prop(var) {
// do stuff with var...
}
我不确定在各种浏览器中实现的效果如何。似乎Firefox也有一种替代语法,使用双重下划线特殊(“魔术”)方法。像往常一样,Internet Explorer不支持任何此类功能。
答案 8 :(得分: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来运行此代码。
答案 9 :(得分:2)
我也对explanation I read感到有些困惑,因为我试图将一个属性添加到我没写过的现有原型中,所以替换原型似乎是错误的方法。因此,对于子孙后代,我在last
添加Array
属性的方式如下:
Object.defineProperty(Array.prototype, "last", {
get: function() { return this[this.length - 1] }
});
比添加函数恕我直言更好。
答案 10 :(得分: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();
VS
var a = { get value(){ return 5; }; }
for (var i = 0; i < 100000; i++)
a.value;
答案 11 :(得分:0)
您也可以使用__defineGetter__
:
function Vector2(x,y) {
this.x = x;
this.y = y;
}
Vector2.prototype.__defineGetter__("magnitude", function () {
return Math.sqrt(this.x*this.x+this.y*this.y);
});
console.log(new Vector2(1,1).magnitude)
或者,如果您愿意:
function Vector2(x,y) {
this.x = x;
this.y = y;
this.__defineGetter__("magnitude", function () {
return Math.sqrt(this.x*this.x+this.y*this.y);
});
}
console.log(new Vector2(1,1).magnitude)
Object.defineProperty()
。
答案 12 :(得分:0)
这里没有 ES6 class
的例子(现在甚至不是“新的”,这是常态):
class Student {
contructor(firstName, lastName){
this.firstName = firstName
this.lastName = lastName
this.secretId = Math.random()
}
get fullName() {
return `${this.firstName} ${this.lastName}`; // this is backtick in js, u can check it out here: https://stackoverflow.com/a/27678299/12056841
}
set firstName(newFirstName) {
// validate that newFirstName is a string (and maybe limit length)
this.firstName = newFirstName
}
get studentId() { return this.secretId }
}
并且 没有 setter 用于 secretId,因为我们不希望任何人更改它。
** if secretId
根本不应该改变,一个很好的方法是通过向它添加一个“#”来将它声明为这个类的“私有”
(例如:this.#secretId = Math.random()
和 return this.#secretId
答案 13 :(得分:-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