Лучший способ создать класс getter / setters в Javascript? - PullRequest
17 голосов
/ 15 декабря 2010

Исходя из C # / PHP, я хотел бы иметь полные геттеры / сеттеры для классов (функций), которые я создаю с помощью Javascript.

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

Мне было приятно найти статью Джона Ресига о геттерах и сеттерах, но некоторые комментарии к ней, в которых говорится, что некоторые браузеры "не поддерживают геттерыи сеттеры », что меня смущает, так как они не« особенность »Javascript, а скорее простой шаблон, использующий базовый синтаксис Javascript.Эта статья также была написана в 2007 году, поэтому к настоящему времени она может быть устаревшей.

Каково текущее состояние методов получения и установки в Javascript? Действительно ли они сегодня "поддерживаются" всеми браузерами (что бы это ни значило)?Являются ли они полезным шаблоном программирования для Javascript или классы Javascript (будучи функциями) лучше с открытыми переменными?Есть ли лучший способ их реализации, чем следующий?

$(document).ready(function() {
    var module = new Module('idcode');
    module.set_id_code('new idcode');
    module.set_title('new title');
    $('body').html(module.get_id_code()+': '+module.get_title());
});

function Module(id_code, title) {
    var id_code = id_code;
    var title = title;

    //id_code
    this.get_id_code = function() {
        return id_code;
    }
    this.set_id_code = function(value) {
        id_code = value;
    }

    //title
    this.get_title = function() {
        return title;
    }
    this.set_title = function(value) {
        title = value;
    }
}

Ответы [ 7 ]

15 голосов
/ 15 декабря 2010

Firefox, Safari, Chrome и Opera (но не IE) имеют одинаковый нестандартный встроенный механизм getter и setter . ECMAScript 5 включает в себя другой синтаксис:1005 * в настоящее время пробивается в браузеры и станет стандартом в будущем.IE 8 уже имеет эту функцию, но только на узлах DOM, а не на обычных объектах JavaScript.Вот как выглядит синтаксис:

var obj = {};

Object.defineProperty(obj, "value", {
    get: function () {
        return this.val;
    },
    set: function(val) {
        this.val = val;
    }
});
9 голосов
/ 15 декабря 2010

Думаю, вы упускаете суть.(Или, может быть, другие ответчики упускают суть.) ECMAScript предоставляет «закулисный» механизм получения / установки, так что

x.foo = 3;
y = x.foo;

действительно переводит в (вроде)

x.PutValue("foo",3);
y = x.GetValue("foo");

, где PutValue и GetValue - безымянные, не доступные напрямую функции для сеттеров и геттеры для свойств.(См. Стандарт ECMAScript, 3-е изд. , раздел 8.7.1. И 8.7.2.) 3-е издание, по-видимому, явно не определяет, как пользователи могут настраивать пользовательские методы получения и установки.Реализация JavaScript в Mozilla была и остается, например (это JSDB , использующий Javascript 1.8):

js>x = {counter: 0};
[object Object]
js>x.__defineGetter__("foo", function() {return this.counter++; });
js>x.foo
0
js>x.foo
1
js>x.foo
2
js>x.foo
3
js>x.foo
4

Синтаксис (или, по крайней мере, до сих пор) былконкретный.В частности, отсутствует Internet Explorer, по крайней мере, согласно этому вопросу SO .

Пятое издание стандарта ECMAScript, похоже, стандартизирует этот механизм.См. этот вопрос о геттерах и установщиках .


edit : возможно, более практичный пример для ваших целей:

function makePrivateObject()
{
   var state = 0;
   var out = {};
   out.__defineSetter__("foo", function(x) {});
   // prevent foo from being assigned directly
   out.__defineGetter__("foo", function() { return state; });
   out.count = function() { return state++; }
   return out;
}

js>x = makePrivateObject()
[object Object]
js>x.foo
0
js>x.foo = 33
33
js>x.foo
0
js>x.count()
0
js>x.count()
1
js>x.count()
2
js>x.foo
3
5 голосов
/ 12 июля 2013

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

$(document).ready(function() {
  var module = new Module('idcode');
  module.id = 'new idcode';
  module.title = 'new title';
  $('body').html(module.id + ': ' + module.title);
});

function Module(id, title) {
  return {
    id_code: id_code,
    _title: title,

    get id() {
      return id_code;
    },
    set id(value) {
      id_code = value;
    },

    get title() {
      return _title;
    },
    set title(value) {
      title = value;
    }
  }
};
5 голосов
/ 15 декабря 2010

Как насчет:

function Module(id_code, title) {
    var id_code = id_code;
    var title = title;

    var privateProps = {};

    this.setProperty = function(name, value) {
      // here you could e.g. log something
      privateProps[name] = value;
    }

    this.getProperty = function(name) {
      return privateProps[name];
    }
}

Методы получения и установки здесь действуют на закрытый объект, используемый для хранения свойств, к которым нет доступа из других методов.Таким образом, вы можете, например, реализовать метод установки (или метод получения), который регистрирует или выполняет ajax или что-то еще, когда свойство модифицируется (одна из целей методов получения / установки).

2 голосов
/ 21 марта 2014

Мне нравится это:

//  Module
var Module = function() {

    // prive getter/setter value
    var __value;

    // private getter/setter method
    var _value = function() {
        if(!arguments.length) return __value;
        else __value = arguments[0];
    };

    // output/public     
    return {
        value: _value
    };
}
1 голос
/ 15 декабря 2010

Геттеры и сеттеры - это не функции, а «шаблоны проектирования» (в данном случае кодовое пятно) для языков, которые не поддерживают синтаксис свойств.

Поскольку в Javascript не нужны геттеры и сеттеры,не хочу их писать.Используйте доступные вам языковые функции, и идиомы, которые отлично работают на одном языке, не очень хорошо работают на другом.

Одна из моих любимых цитат взята из сообщества Python:

Мы все согласны с тем, что взрослые здесь

, когда обсуждают, почему частные переменные и скрытие информации не нужны.

С цитатой можно ознакомиться здесь .

Узнайте, что предлагает вам язык, и примите его культуру и правила.

0 голосов
/ 04 августа 2015

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

var myComplexObject = {
  changelog: {},
  log: function(name, val) {
    console.log("set " + name + " to " + val);
    if (!this.changelog[name])
      this.changelog[name] = [];
    this.changelog[name].push(val);
  },
  set o (val) {
    this.log("o", val);
  },
  get o () {
    console.log("You will never know the true value!");
    return 42;
  }
}

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

myComplexObject.o = "oxygen";
set o to oxygen

Затем, в этом примере, попытка прочитать значение приводит к следующему:

var read = myComplexObject.o;
console.log(read);
You will never know the true value!
42

И, в этом примере, каждое новое заданное вами значение записывается в журнал:

myComplexObject.o = "Oh no!";
console.log(myComplexObject.changelog.o);
set o to Oh no!
["oxygen", "Oh no!"]
...