我一直在努力使自己了解getter和setter,而不会陷入其中。我已经阅读了JavaScript Getters和Setters和定义Getters和Setters,只是没有得到它。
有人可以明确指出:
- 吸气器和装夹器的作用是什么,以及
- 举几个非常简单的例子吗?
a = setValue(5);
为a = 5;
,setValue()
从而可以在后台调用任何您喜欢的事情。
我一直在努力使自己了解getter和setter,而不会陷入其中。我已经阅读了JavaScript Getters和Setters和定义Getters和Setters,只是没有得到它。
有人可以明确指出:
a = setValue(5);
为a = 5;
,setValue()
从而可以在后台调用任何您喜欢的事情。
Answers:
除了@millimoose的答案外,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"
Object.defineProperty
可以定义getter和setter 的较新功能。
Name.prototype.constructor
吗?似乎是对millimoose的Answer的不好选择。
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支持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._a; },
getB : ..., getC : ..., setA : ..., setB : ..., setC : ...
};
对于上面的示例,内部属性名称用下划线抽象出来,以阻止用户简单地执行foo.bar
vs foo.get( 'bar' )
和获取“未经烹煮”的值。您可以使用条件代码来执行不同的操作,具体取决于要访问的属性的名称(通过name
参数)。
使用Object.defineProperty()
是添加getter和setter的另一种方法,并且可以在定义对象后将其用于对象。它也可以用来设置可配置和可枚举的行为。此语法也可用于IE 8,但不幸的是仅适用于DOM对象。
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__()
是另一种选择。它已过时,但仍在网络上广泛使用,因此不太可能很快消失。它适用于除IE 10及以下版本的所有浏览器。尽管其他选项在非IE上也能很好地工作,所以这个选项不是那么有用。
var foo = { _bar : 123; }
foo.__defineGetter__( 'bar', function(){ return this._bar; } );
foo.__defineSetter__( 'bar', function( value ){ this._bar = value; } );
另外值得注意的是,在后面的示例中,内部名称必须与访问者名称不同,以避免递归(即,foo.bar
调用,foo.get(bar)
调用,foo.bar
调用foo.get(bar)
...)。
MDN get,set,
Object.defineProperty(),__ defineGetter __(),__ defineSetter __()
MSDN
IE8 Getter支持
this[ '_' + name ] = value;
可以this[ '_' + name ] = arguments[1];
并且不需要指定value
arg。
var foo = { bar : 123, get bar(){ return bar; }, set bar( value ){ this.bar = value; } }; foo.bar = 456;
引发异常:未捕获RangeError:在Object.set bar [as bar](<anonymous>:4:32)处Object.set bar [as bar](<anonymous>:4:32)超出最大调用堆栈大小)在Object.set bar [as bar](<anonymous>:4:32)在Object.set bar [as bar](<anonymous>:4:32)at Object.set bar [as bar](<anonymous> :4:32)at Object.set bar [as bar](<anonymous>:4:32)
bar: 123
和this.bar = value
等,将其更改_bar
为例如。请参阅:hongkiat.com/blog/getters-setters-javascript
_foo
或mFoo
。如果它与getter / setter相同,则将由于递归而导致无限循环,然后将导致Stack Overflow™;-),因为当您说a = b时,它将调用a.get(b),后者本身将调用a = b ,它调用a.get(b),...
例如,您将使用它们来实现计算属性。
例如:
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
Object.defineProperties
。
很抱歉再次提出一个老问题,但我想我可能会提供几个非常基本的示例和伪造的解释。到目前为止,没有任何其他答案能像MDN指南的第一个示例那样说明语法,这几乎是一个基本知识。
吸气剂:
var settings = {
firstname: 'John',
lastname: 'Smith',
get fullname() { return this.firstname + ' ' + this.lastname; }
};
console.log(settings.fullname);
...将记录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);
...将登录New York
到控制台。像getter一样,setter的调用语法与设置对象属性值的语法相同,但这是调用不带()的函数的另一种奇特的方式。
有关更全面,更实际的示例,请参见此jsfiddle。将值传递到对象的设置器中会触发其他对象项的创建或填充。具体来说,在jsfiddle示例中,传递数字数组会提示设置器计算均值,中位数,众数和范围;然后为每个结果设置对象属性。
maps.roll
作为属性而不是maps.roll()
return val 很有帮助。这只是一个偏爱。
maps.roll()
仅当您具有类的私有属性时,getter和setter才有意义。由于Java语言实际上并不像您通常从面向对象语言中所想到的那样具有私有类属性,因此可能很难理解。这是私有计数器对象的一个示例。关于这个对象的好处是,不能从对象外部访问内部变量“ 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的Java私有成员文章。
var baz = foo.bar
背后有完整的隐藏行为。我会想到的是从foo.getBar()
,但是。
尽管我们经常习惯于在没有任何访问控制的情况下查看具有公共属性的对象,但是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
令人困惑的是... getter是在获取属性时调用的函数,setters是在设置属性时调用的。例如,如果你这样做
obj.prop = "abc";
您正在设置属性prop,如果您使用的是getters / setters,则将使用“ abc”作为参数来调用setter函数。理想情况下,对象内部的setter函数定义如下所示:
set prop(var) {
// do stuff with var...
}
我不确定跨浏览器的实施情况如何。Firefox似乎还具有另一种语法,带有双下划线的特殊(“魔术”)方法。与往常一样,Internet Explorer不支持任何一个。
您可以通过构造函数的原型为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来运行此代码。
如果您指的是访问器的概念,那么简单的目标是对底层存储进行任意操作。最极端的机制是
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;
我为你们准备了一个可能有点丑陋的工具,但确实可以跨平台完成
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"
如果您真的想让事情变得有趣..您可以插入typeof检查:
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];
或使用高级typeof检查甚至更疯狂:位于encodingforums.com的type.of()代码