Геттеры \ сеттеры для чайников

В качестве альтернативы:

git push origin +364705c23011b0fc6a7ca2d80c86cef4a7c4db7ac8^:master

Подключите главную ветвь исходного репозитория к родительскому объекту последнего коммита

128
задан Alexander Abakumov 22 March 2019 в 19:54
поделиться

6 ответов

Вы можете использовать их, например, для реализации вычисляемых свойств.

Например:

function Circle(radius) {
    this.radius = radius;
}

Object.defineProperty(Circle.prototype, 'circumference', {
    get: function() { return 2*Math.PI*this.radius; }
});

Object.defineProperty(Circle.prototype, 'area', {
    get: function() { return Math.PI*this.radius*this.radius; }
});

c = new Circle(10);
console.log(c.area); // Should output 314.159
console.log(c.circumference); // Should output 62.832

(CodePen)

58
ответ дан 24 November 2019 в 00:38
поделиться

Методы получения и установки действительно имеют смысл, только если у вас есть закрытые свойства классов. Поскольку Javascript на самом деле не имеет свойств закрытого класса, как вы обычно думаете из Object Oriented Languages, это может быть трудно понять. Вот один пример частного счетчика объекта. Хорошая вещь об этом объекте состоит в том, что внутренняя переменная "count" не может быть доступна извне объекта.

var counter = function() {
    var count = 0;

    this.inc = function() {
        count++;
    };

    this.getCount = function() {
        return count;
    };
};

var i = new Counter();
i.inc();
i.inc();
// writes "2" to the document
document.write( i.getCount());

Если вы все еще в замешательстве, взгляните на статью Крокфорда о Private Members in Javascript .

11
ответ дан 24 November 2019 в 00:38
поделиться

Если вы ссылаетесь на концепцию методов доступа, то простая цель - скрыть базовое хранилище от произвольных манипуляций. Самый экстремальный механизм для этого -

function Foo(someValue) {
    this.getValue = function() { return someValue; }
    return this;
}

var myFoo = new Foo(5);
/* We can read someValue through getValue(), but there is no mechanism
 * to modify it -- hurrah, we have achieved encapsulation!
 */
myFoo.getValue();

Если вы ссылаетесь на фактическую функцию получения / установки JS, например. defineGetter / defineSetter или {get Foo () {/ * code * /}} , тогда стоит отметить, что в большинстве современных механизмов последующее использование этих свойства будут намного медленнее, чем в противном случае. например. сравнить производительность

var a = { getValue: function(){ return 5; }; }
for (var i = 0; i < 100000; i++)
    a.getValue();

с

var a = { get value(){ return 5; }; }
for (var i = 0; i < 100000; i++)
    a.value;
1
ответ дан 24 November 2019 в 00:38
поделиться

Я думаю, что первая статья, на которую вы ссылаетесь, довольно четко заявляет:

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

Цель здесь - инкапсулировать и абстрагировать поля, предоставляя им доступ только через метод get () или set () . Таким образом, вы можете хранить поле / данные внутри себя любым удобным вам способом, но внешние компоненты находятся только вне вашего опубликованного интерфейса. Это позволяет вам вносить внутренние изменения без изменения внешних интерфейсов, выполнять некоторую проверку или проверку ошибок в методе set () и т. Д.

7
ответ дан 24 November 2019 в 00:38
поделиться

In addition to @millimoose's answer, setters can also be used to update other values.

function Name(first, last) {
    this.first = first;
    this.last = last;
}

Name.prototype = {
    get fullName() {
        return this.first + " " + this.last;
    },

    set fullName(name) {
        var names = name.split(" ");
        this.first = names[0];
        this.last = names[1];
    }
};

Now, you can set fullName, and first and last will be updated and vice versa.

n = new Name('Claude', 'Monet')
n.first # "Claude"
n.last # "Monet"
n.fullName # "Claude Monet"
n.fullName = "Gustav Klimt"
n.first # "Gustav"
n.last # "Klimt"
98
ответ дан 24 November 2019 в 00:38
поделиться

У меня есть для вас один вариант, который может быть немного уродлив, но он работает на всех платформах

function myFunc () {

var _myAttribute = "default";

this.myAttribute = function() {
    if (arguments.length > 0) _myAttribute = arguments[0];
    return _myAttribute;
}
}

Таким образом, когда вы вызываете

var test = new myFunc();
test.myAttribute(); //-> "default"
test.myAttribute("ok"); //-> "ok"
test.myAttribute(); //-> "ok"

Если вы действительно хотите разнообразить ситуацию... вы можете вставить проверку typeof:

if (arguments.length > 0 && typeof arguments[0] == "boolean") _myAttribute = arguments[0];
if (arguments.length > 0 && typeof arguments[0] == "number") _myAttribute = arguments[0];
if (arguments.length > 0 && typeof arguments[0] == "string") _myAttribute = arguments[0];

или пойти еще дальше с расширенной проверкой typeof: type.of() код на codingforums.com

-1
ответ дан 24 November 2019 в 00:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: