Javascript getter和setter的傻瓜?
我一直试图让我的头在getter和setter,而不是陷入。我已经读了JavaScript Getters和Setters和定义Getters和Setters ,只是没有得到它。
有人可以明确指出:
- 什么是吸气和二手的意图去做,和
- 给一些非常简单的例子?
除了@ 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]; } };
现在,你可以设置fullName
, first
和last
会被更新,反之亦然。
你会用它们来实现计算的属性。
例如:
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)
Getters和Setter在JavaScript中
概观
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'
这对于在访问某个属性时自动执行幕后操作非常有用,例如保持范围内的数字,重新格式化string,触发值更改事件,更新关系数据,提供对私有属性的访问等等。
下面的例子展示了基本的语法,尽pipe它们只是简单地获取和设置内部对象的值,而没有做任何特殊的事情 在实际情况下,您可以修改input和/或输出值以满足您的需求,如上所述。
获取/设置关键字
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;
自定义Getters和Setters
get
和set
不是保留字,所以它们可以被重载来创build自己定制的,跨浏览器的计算属性函数。 这将在任何浏览器中工作。
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' );
或者为了更紧凑的方法,可以使用单个function。
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' )
并获得“未烹饪”值。 您可以使用条件代码根据正在访问的属性的name
(通过name
参数)做不同的事情。
Object.defineProperty()
使用Object.defineProperty()
是另一种添加getter和setter的方法,可以在定义对象后使用。 它也可以用来设置可configuration和可枚举的行为。 这个语法也适用于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__()
是另一个选项。 它已被弃用,但仍在networking上广泛使用,因此不可能很快消失。 它适用于除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支持
当你拥有类的私有属性时,获取者和设置者才真正有意义。 由于Javascript实际上并没有像通常从面向对象语言(Object Oriented Languages)那样想到的私有类属性,所以很难理解。 这是一个私人对象的例子。 这个对象的好处在于内部variables“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有关使用Javascript的Private Members的文章。
我认为你链接的第一篇文章说得很清楚:
以这种方式编写JavaScript的明显优势是,您可以使用不想让用户直接访问的模糊值。
这里的目标是通过只允许通过get()或set()方法访问它们来封装和抽象字段。 这样,您可以以任何您想要的方式在内部存储字段/数据,但外部组件只能远离您发布的界面。 这允许您在不更改外部接口的情况下进行内部更改,在set()方法内执行一些validation或错误检查等。
看一下:
定义Getters和Setter
和这个
Javascript圣经
对不起复活了一个老问题,但我想我可能会贡献一些非常基本的例子和傻瓜解释。 没有任何其他的答案可以说明这样的语法,如MDN指南的第一个例子,这是基本的,可以得到。
消气:
var settings = { firstname: 'John', lastname: 'Smith', get fullname() { return this.firstname + ' ' + this.lastname; } }; console.log(settings.fullname);
当然会loggingJohn Smith
。 一个getter的行为就像一个variables对象属性,但是提供了一个函数的灵活性来实时计算返回的值。 这基本上是一个奇特的方式来创build一个函数,调用时不需要()。
二传手:
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
login到控制台。 像getter一样, setter被调用的语法与设置对象属性的值相同,但是又是一种不带()的函数调用方式。
看到这个jsfiddle更彻底,也许更实际的例子。 将值传递给对象的setter会触发其他对象项的创build或填充。 具体来说,在jsfiddle示例中,传递数字数组会提示setter计算均值,中值,模式和范围; 然后为每个结果设置对象属性。
有什么让人困惑的… getter是函数,当你得到一个属性,setters,当你设置它。 例如,如果你这样做
obj.prop = "abc";
你正在设置属性道具,如果你使用getters / setter,那么setter函数将被调用,并以“abc”作为参数。 对象内部的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来运行此代码。
我读到的解释也有点困惑,因为我正在试图将一个属性添加到现有的原型中,因此replace原型看起来就像是错误的方法。 所以,为了后代,下面是我向Array
添加last
属性:
Object.defineProperty(Array.prototype, "last", { get: function() { return this[this.length - 1] } });
比添加一个函数恕我直言稍微好一点。
虽然我们经常习惯于在没有任何访问控制的情况下查看带有公共属性的对象,但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
如果您指的是访问者的概念,那么简单的目标就是隐藏底层存储以免被任意操纵。 最极端的机制是
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 / setterfunction,例如。 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;
为什么不使用get和set语法?
Getters和Setter只是一般的概念,完全按照名称的说法:获取一个variables/对象,并设置一个variables/对象。
下面是我个人“获得”和“设置”我自己的variables:
var data = "Hello World"
有些人有时需要抽象出来,所以他们这样做:
function get(value){ [...] } function set(name,value){ [...] } set("data","Hello World"); var data = get("data");
我不使用Getters和Setter,但是它们有一些很好的用法,例如当你需要抽象variables的存储/访问方式时。
对于你们来说,我有一个可能有点难看的东西,但是它确实跨平台完成了
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"
如果你真的想把事情搞定..你可以插入一个types的检查:
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];
或者在编码论坛(forumforums.com)上使用先进的type.of()代码进行更疯狂的操作