Свойства доступа javascript
В Javascript кажется, что использование атрибутов свойств не так уж и много (в отличие от других языков OO, таких как Java, например).
Если у меня есть объект Person
с именем, определенным как
function Person(name) {
this.name = name;
}
Имя человека не изменится, но я хочу иметь доступ к нему, когда это необходимо, поэтому я мог бы сделать что-то вроде:
function Person(name) {
var name = name;
this.getName = function() {
return name;
}
}
Даже на динамическом языке я считаю, что принципы использования геттеров и сеттеров применяются так же, как и к статически типизированным OO-языкам (например, инкапсуляция, добавление проверки, ограничение доступа и т.д.)
Этот вопрос может быть закрыт как субъективный, но мне любопытно, почему это поведение чаще не проявляется (например, разработчики Java сойдут с ума, если все станет общедоступным).
Есть ли "стандартный" способ сделать это в javascript? Я видел Object.defineProperty
, но не все браузеры поддерживают это.
Ответы
Ответ 1
Javascript имеет доступ к активам, доступным для перехвата:
http://ejohn.org/blog/javascript-getters-and-setters/
IMHO это гораздо лучшее решение для обеспечения единообразного принципа доступа, чем Java, более строгие явные getters, но это также является частью простоты и негибкости этого языка (например, Groovy допускает аналогичный перехват).
Ответ 2
Я знаю свои мысли по этому вопросу.
Геттеры и сеттеры злы.
Подождите! В самом деле! Принесите мне мгновение и позвольте мне объяснить.
Просто используя метод, чтобы получить и установить значение, это.. ну.. kinda бессмысленно. Это не защищает, а не то, что вы вставляете, это то, что вы выходите.
С другой стороны, я предпочитаю методы ввода информации, а затем возвращаю информацию. НО вот волшебная часть! Это не та же информация. Не напрямую.
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 и большинством объектов хоста, вы устанавливаете свойства. Вы не играете с геттерами и сеттерами. Не использовать их подходит для остальных "ароматов" того, что делают JS-кодеры.
Ответ 3
Я думаю, что ответ заключается в том, что эмулирование классов в javascript - это не обычная практика, потому что язык на самом деле прототип.
Хотя можно создавать структуры типа типа (как в вашем примере), они не очень похожи на классы Java, а в качестве программиста вы вступаете в борьбу с нюансами.
Если, однако, вы используете прототипный характер javascript, вы вознаграждаетесь другой, но сплоченной и простой структурой для языка.
Нет необходимости использовать геттеры и сеттеры с прототипной структурой, так как вы можете просто установить объект, ну, установив его в значение и получить его, назвав его как значение.
Javascript не заставляет вас писать структурированный код и не мешает вам это делать. Я думаю, что культура, которая выросла вокруг javascript, разработала хороший стиль кодирования, который совершенно правдоподобен и отличается от любого другого языка, который я использую.
Я знаю, что этот ответ не является окончательным и убедительным, но, надеюсь, есть некоторые идеи, которые помогут вам найти anser, который вы ищете.
Ответ 4
Это то, что я использовал для локальных полей:
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);
Ответ 5
Извиняюсь, если я не правильно понял вопрос, но функции, выполняемые самим пользователем, являются одним из способов сделать публичные/частные члены.
var Person = function(){
var _name = "Roger",
self = { getName : function (){ return _name; }};
return self;
}()
Затем вы можете получить доступ к Person.getName() из любого места, но не установить _name.