Подтвердить что ты не робот

Лучший способ создать класс getter/setters в Javascript?

Исходя из С#/PHP, я хотел бы иметь полные getters/setters для классов (функций), которые я создаю с помощью 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;
    }
}
4b9b3361

Ответ 1

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

var obj = {};

Object.defineProperty(obj, "value", {
    get: function () {
        return this.val;
    },
    set: function(val) {
        this.val = val;
    }
});

Ответ 2

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

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

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

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

где PutValue и GetValue являются неназванными, а не напрямую доступными функциями для сеттеров и getters для свойств. (См. стандарт ECMAScript, 3-е изд., раздел 8.7.1 и 8.7.2). Третье издание, похоже, явно не определяет как пользователи могут настраивать пользовательские функции getter и setter. Mozilla-реализация Javascript делала и продолжает делать, например. (это находится в 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, похоже, стандартизирует этот механизм. См. этот SO-вопрос о геттерах и сеттерах.


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

Ответ 3

Как насчет:

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];
    }
}

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

Ответ 4

Фактически вы можете определить сеттеры и геттеры в 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

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

//  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
    };
}

Ответ 6

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

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

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

Мы все соглашаемся с взрослыми здесь.

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

Котировку можно найти здесь.

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

Ответ 7

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

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!"]