在Javascript中,似乎使用属性访问器并不常见(例如,与Java等其他OO语言不同)。
如果我有一个名为Person
的对象,则定义为
function Person(name) {
this.name = name;
}
一个人的名字不会改变,但我确实希望能够在需要时访问它,所以我可以这样做:
function Person(name) {
var name = name;
this.getName = function() {
return name;
}
}
即使是动态语言,我认为使用getter和setter的原则与静态类型的OO语言的使用方式相同(例如封装,添加验证,限制访问等)
这个问题可能会被认为是主观的,但我很好奇为什么这种行为不会更频繁出现(例如,如果一切都是公开的,Java开发人员就会疯狂)。
在javascript中有“标准”方法吗?我见过Object.defineProperty
,但并非所有浏览器都支持此版本。
答案 0 :(得分:15)
Javascript具有可拦截的属性访问器:
http://ejohn.org/blog/javascript-getters-and-setters/
恕我直言,这是一个比Java更严格的显式getter强制执行统一访问原则的更好的解决方案,但这也是该语言的简单性和不灵活性的一部分(例如Groovy允许类似的拦截)。
答案 1 :(得分:7)
我知道我对这个问题的想法。
吸气剂和制定者是邪恶的。
等待!真!请耐心等待我,让我解释一下。
只是使用一个方法来获取和设置一个值是......好吧..有点无意义。它没有保护,不是真的,你输入的是你得到的东西。
另一方面,我非常喜欢将信息输入的方法,然后将信息取回。但这里是神奇的部分!这是不一样的信息。不是直接的。
function Person(name) {
this.getFullName = function() {return this.firstName + " " + this.lastName;};
this.setBirthday = function(date) { this.birthday = date; };
this.getAge = function() { /* Return age based on the birthday */ };
this.isOfLegalDrinkingAge function() { /* do your math here too */ };
}
但是大多数时候我只是推送静态数据并获取静态数据。将它隐藏在吸气剂和制定者背后的意义何在?
作为次要原因,在处理DOM和大多数主机对象时,您需要设置属性。你不玩getter和setter。不使用它们符合JS编码员所做的其他“风格”。
答案 2 :(得分:3)
我认为答案是在javascript中模拟类并不常见,因为语言实际上是原型。
虽然可以创建类结构(如在你的例子中),但它们并不像java类,作为程序员,你最终会与细微差别作斗争。
但是,如果您接受javascript的原型性质,那么您将获得一种不同但又有凝聚力且简单的语言结构。
没有必要使用具有原型结构的getter和setter,因为你可以简单地设置一个对象,并将其设置为一个值,然后通过将其作为一个值来调用它。
Javascript不会强迫您编写结构化代码,也不会阻止您这样做。我认为围绕javascript成长起来的文化已经形成了一种良好的编码风格,完全有效,并且与我使用的任何其他语言不同。
我知道这个答案不是确定的,也不是决定性的,但希望有一些想法可以帮助你找到你正在寻找的anser。
答案 3 :(得分:0)
如果我不正确理解这个问题,我道歉,但自动执行功能是使成员公开/私人的一种方式
var Person = function(){
var _name = "Roger",
self = { getName : function (){ return _name; }};
return self;
}()
然后,您可以从任何地方访问Person.getName(),但不能设置_name。
答案 4 :(得分:0)
这是我用于本地字段的内容:
TYPE_DEFAULT_VALUE= {
number: 0,
string: "",
array: [],
object: {},
};
typeOf = function (object) {
if (typeof object === "number" && isNaN(object))
return NaN;
try {
return Object.prototype.toString.call(object).slice(8, -1).toLowerCase();
}
catch(ex) {
return "N/A";
};
};
getAccessor = function(obj, key, type, defaultValue) {
if (defaultValue === undefined)
defaultValue = TYPE_DEFAULT_VALUE[type] === undefined ? null : TYPE_DEFAULT_VALUE[type];
return {
enumerable: true,
configurable: true,
get: function () {
if (obj[key] === undefined)
obj[key] = defaultValue;
return obj[key];
},
set: function (value) {
if (typeOf(value) === type)
obj[key] = value;
},
};
}
LocalFields = function (fields, object) {
/**
* field properties
* {
* type: [ required ] ( number | string | array | object | ... ),
* defaultValue: [ optional ]
* }
*/
if (! fields)
throw "Too few parameters ...";
if (! object)
object = this;
var obj = this;
var fieldsAccessor = {};
for(key in fields){
field = fields[key];
fieldHandler = key[0].toUpperCase() + key.substr(1);
if(! field.type)
throw "Type not set for field: " + key;
fieldsAccessor[fieldHandler] = getAccessor(obj, fieldHandler, field.type, field.defaultValue)
}
Object.defineProperties(object, fieldsAccessor);
}
现在每个班级我都可以打电话给:
Person = function(){
new LocalFields({
id: { type: "number" },
name: { type: "string" },
}, this);
}
然后就像VS getter和setter一样,你打电话:
var alex = new Person();
alex.Name = "Alex Ramsi";
console.clear();
console.info(alex.Name);