Средства доступа к свойствам javascript

В Javascript кажется, что использование методов доступа к свойствам встречается не так часто (в отличие от других ОО-языков, таких как, например, Java).

Если у меня есть Person объект с именем, определенным как

function Person(name) {
   this.name = name;
}

Имя человека не изменится, но я хочу иметь к нему доступ при необходимости, чтобы я мог сделать что-то вроде:

function Person(name) {
   var name = name;
   this.getName = function() {
      return name;
   }
}

Даже в динамическом языке, я думаю, что принципы использования методов получения и установки применяются так же, как и к статически типизированным языкам ОО (например, инкапсуляция, добавление проверки, ограничение доступа и т. Д.)

Этот вопрос может быть закрыт как субъективный, но мне любопытно, почему такое поведение не появляется чаще (например, Java-разработчики сошли бы с ума, если бы все было публично).

Есть ли "стандартный" способ сделать это в JavaScript? я видел Object.defineProperty, но не все браузеры поддерживают это.

5 ответов

Решение

Javascript имеет методы доступа к перехватываемым свойствам:

http://ejohn.org/blog/javascript-getters-and-setters/

ИМХО, это гораздо лучшее решение для реализации принципа унифицированного доступа, чем более строгие явные методы получения Java, но это также является частью простоты и негибкости этого языка (например, Groovy допускает аналогичный перехват).

Я знаю свои мысли по этому вопросу.

Геттеры и сеттеры - это зло.

Подождите! В самом деле! Потерпи минуту и ​​позволь мне объяснить.

Просто использовать метод для получения и установки значения... ну.. вроде бессмысленно. Это не защищает, на самом деле, и то, что вы вкладываете, это то, что вы получаете.

С другой стороны, я довольно люблю методы, которые вводят информацию, а затем возвращают информацию. НО здесь волшебная часть! Это не та же информация. Не напрямую.

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-кодеры.

Я думаю, что ответ заключается в том, что эмуляция классов в javascript не является обычной практикой, потому что язык на самом деле является прототипом.

Хотя можно создавать классоподобные структуры (как в вашем примере), они на самом деле не похожи на java-классы, и как программист вы столкнетесь с нюансами.

Однако, если вы принимаете прототипную природу javascript, вы будете вознаграждены другой, но сплоченной и простой структурой языка.

Нет необходимости использовать геттеры и сеттеры с прототипной структурой, так как вы можете просто установить объект, установив для него значение, и получить его, вызвав его как значение.

Javascript не заставляет вас писать структурированный код и не мешает вам делать это. Я думаю, что культура, которая выросла вокруг javascript, разработала хороший стиль кодирования, который является абсолютно допустимым и отличается от любого другого языка, который я использую.

Я знаю, что этот ответ не является окончательным и окончательным, но, надеюсь, есть некоторые идеи, которые помогут вам найти искателя, который вы ищете.

Вот что я использовал для локальных полей:

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);

Я прошу прощения, если я не правильно понял вопрос, но самоисполняющиеся функции являются одним из способов сделать членов публичными / частными

var Person = function(){
  var _name = "Roger",
      self = { getName : function (){ return _name; }};
  return self;
}()

Затем вы можете получить доступ к Person.getName() из любого места, но не можете установить _name.

Другие вопросы по тегам