На сегодняшний день наилучшей ссылкой для этой проблемы остается ответ, опубликованный в трекере проблем для платформы Google.
У меня есть один для вас, ребята, который может быть немного уродлив, но он делает это на разных платформах
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"
Если вы действительно хотите оживить ситуацию, вы можете вставить проверку типа:
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];
или пойти еще более сумасшедшим с расширенной проверкой типа: type.of () code at codingforums.com
Геттеры и сеттеры в JavaScript используются для определения вычисленных свойств или accessors . Вычисленное свойство - это свойство, которое использует функцию для получения или установки значения объекта. Основная теория делает что-то вроде этого:
var user = { /* ... object with getters and setters ... */ };
user.phone = '+1 (123) 456-7890'; // updates a database
console.log( user.areaCode ); // displays '123'
console.log( user.area ); // displays 'Anytown, USA'
Это полезно для автоматического выполнения вещей за кадром при доступе к ресурсу, например, при хранении чисел в диапазоне, переформатировании строк, срабатывании значения - изменения событий, обновление реляционных данных, предоставление доступа к приватным свойствам и т. д.
В приведенных ниже примерах показан базовый синтаксис, хотя они просто получают и устанавливают значение внутреннего объекта, не делая ничего особенного.
ECMAScript 5 поддерживает get
и set
для определения вычисленных свойств. Они работают со всеми современными браузерами, кроме IE 8 и ниже.
var foo = {
bar : 123,
get bar(){ return bar; },
set bar( value ){ this.bar = value; }
};
foo.bar = 456;
var gaz = foo.bar;
get
и set
не являются зарезервированными словами, поэтому они могут быть перегружены для создания собственных пользовательских функций, связанных с перекрестными браузерами. Это будет работать в любом браузере.
var foo = {
_bar : 123,
get : function( name ){ return this[ '_' + name ]; },
set : function( name, value ){ this[ '_' + name ] = value; }
};
foo.set( 'bar', 456 );
var gaz = foo.get( 'bar' );
Или для более компактного подхода может использоваться одна функция.
var foo = {
_bar : 123,
value : function( name /*, value */ ){
if( arguments.length < 2 ){ return this[ '_' + name ]; }
this[ '_' + name ] = value;
}
};
foo.value( 'bar', 456 );
var gaz = foo.value( 'bar' );
Избегайте делать что-то вроде этого, что может привести для кодирования bloat.
var foo = {
_a : 123, _b : 456, _c : 789,
getA : function(){ return this.bar; },
getB : ..., getC : ..., setA : ..., setB : ..., setC : ...
};
В приведенных выше примерах имена внутренних свойств абстрагируются с помощью подчеркивания, чтобы препятствовать пользователям просто делать foo.bar
vs. foo.get( 'bar' )
и получать «сырые», стоимость. Вы можете использовать условный код для выполнения разных действий в зависимости от имени доступного свойства (через параметр name
).
Используя Object.defineProperty()
это еще один способ добавления геттеров и сеттеров и их можно использовать на объектах после их определения. Его также можно использовать для настройки настраиваемого и перечислимого поведения. Этот синтаксис также работает с IE 8, но, к сожалению, только на объектах DOM.
var foo = { bar : 123 };
Object.defineProperty( foo, 'bar', {
get : function(){ return bar; },
set : function( value ){ this.bar = value; }
} );
foo.bar = 456;
var gaz = foo.bar;
Наконец, __defineGetter__()
- это еще один вариант. Он устарел, но все еще широко используется в Интернете и, следовательно, вряд ли исчезнет в ближайшее время. Он работает во всех браузерах, кроме IE 10 и ниже. Хотя другие варианты также хорошо работают на не-IE, поэтому это не так полезно.
var foo = { bar : 123; }
foo.__defineGetter__( 'bar', function(){ return this.bar; } );
foo.__defineSetter__( 'bar', function( value ){ this.bar = value; } );
MDN get , set , Object.defineProperty () , __ defineGetter __ () , __ defineSetter __ () MSDN Поддержка IE8 Getter
this[ '_' + name ] = value;
может быть this[ '_' + name ] = arguments[1];
, и нет необходимости указывать value
arg.
– Redhart
31 December 2016 в 11:38
var foo = { bar : 123, get bar(){ return bar; }, set bar( value ){ this.bar = value; } }; foo.bar = 456;
Вызывает исключение: Uncaught RangeError: максимальный размер стека вызовов превышен на панели Object.set [как строка] (& lt; анонимный & gt;: 4: 32) на панели Object.set [в виде строки] (& lt; anonymous & gt; ;: 4: 32) на панели Object.set [в виде бара] (& анонимный & gt;: 4: 32) на панели Object.set [в виде строки] (& анонимный & gt;: 4: 32) на панели Object.set [ как bar] (& anonymous & gt;: 4: 32) на панели Object.set [в виде строки] (& lt; анонимный & gt;: 4: 32)
– nevf
8 May 2018 в 23:36
bar: 123
и this.bar = value
и т. Д. Измените их на _bar
, например. Смотрите: hongkiat.com/blog/getters-setters-javascript
– nevf
8 May 2018 в 23:43
В дополнение к @ ответ Sii , установщики могут также использоваться для обновления других значений.
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];
}
};
Теперь вы можете установить fullName
и first
и last
будут обновлены и наоборот.
Object.defineProperty
, которая может определять геттеры и сеттеры.
– Matthew Crumley
22 March 2011 в 16:46
this.__defineGetter__
или новую функцию Object.defineProperty
.
– Matthew Crumley
6 July 2011 в 14:35
Вы можете определить метод экземпляра для js-класса через прототип конструктора.
Ниже приведен пример кода:
// BaseClass
var BaseClass = function(name) {
// instance property
this.name = name;
};
// instance method
BaseClass.prototype.getName = function() {
return this.name;
};
BaseClass.prototype.setName = function(name) {
return this.name = name;
};
// test - start
function test() {
var b1 = new BaseClass("b1");
var b2 = new BaseClass("b2");
console.log(b1.getName());
console.log(b2.getName());
b1.setName("b1_new");
console.log(b1.getName());
console.log(b2.getName());
}
test();
// test - end
И это должно работать для любого браузера, вы также можете просто использовать nodejs для запуска этого кода.
Getters и seters действительно имеют смысл только тогда, когда у вас есть частные свойства классов. Поскольку Javascript действительно не обладает свойствами частного класса, как вы обычно думаете об объектно-ориентированных языках, это может быть трудно понять. Вот один пример частного счетного объекта. Хорошая вещь об этом объекте заключается в том, что внутренняя переменная «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());
Если вы все еще смущены, посмотрите статью Крокфорда на Частные члены в Javascript .
var baz = foo.bar
будет иметь полный набор скрытого поведения за ним. I будет i> ожидать, что из foo.getBar()
, однако.
– AgmLauncher
20 July 2016 в 18:15
Я думаю, что первая статья, на которую вы ссылаетесь, гласит:
Очевидное преимущество написания JavaScript таким образом заключается в том, что вы можете использовать его в неясных значениях, которые вы не хотите
blockquote>Цель состоит в том, чтобы инкапсулировать и абстрагировать поля, разрешая доступ к ним через метод get () или set (). Таким образом, вы можете хранить поле / данные внутренне в зависимости от того, какой вы хотите, но внешние компоненты находятся только вдали от вашего опубликованного интерфейса. Это позволяет делать внутренние изменения без изменения внешних интерфейсов, выполнять некоторую проверку или проверку ошибок в методе set () и т. Д.
Хотя часто мы привыкли видеть объекты с общедоступными свойствами без какого-либо контроля доступа, JavaScript позволяет нам точно описывать свойства. Фактически, мы можем использовать дескрипторы, чтобы контролировать доступ к объекту и какую логику мы можем применить к нему. Рассмотрим следующий пример:
var employee = {
first: "Boris",
last: "Sergeev",
get fullName() {
return this.first + " " + this.last;
},
set fullName(value) {
var parts = value.toString().split(" ");
this.first = parts[0] || "";
this.last = parts[1] || "";
},
email: "boris.sergeev@example.com"
};
Конечный результат:
console.log(employee.fullName); //Boris Sergeev
employee.fullName = "Alex Makarenko";
console.log(employee.first);//Alex
console.log(employee.last);//Makarenko
console.log(employee.fullName);//Alex Makarenko
Вы использовали бы их, например, для реализации вычисленных свойств.
Например:
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
Object.defineProperties
.
– r0estir0bbe
31 March 2016 в 13:39
Если вы имеете в виду концепцию аксессоров, тогда простая цель - скрыть базовое хранилище от произвольных манипуляций. Самый экстремальный механизм для этого -
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();
Если вы имеете в виду фактическую функцию GET-приемника / сеттера, например. defineGetter
/ defineSetter
или { get Foo() { /* code */ } }
, то стоит отметить, что в большинстве современных двигателей последующее использование этих свойств будет намного медленнее, чем в противном случае. например. сравнить производительность
var a = { getValue: function(){ return 5; }; }
for (var i = 0; i < 100000; i++)
a.getValue();
vs.
var a = { get value(){ return 5; }; }
for (var i = 0; i < 100000; i++)
a.value;
Извините, что воскресил старый вопрос, но я подумал, что могу внести пару очень простых примеров и объяснений для «манекенов». Ни один из других ответов, опубликованных таким образом, не иллюстрирует синтаксис, как первый пример MDN guide , который примерно такой же простой, как можно получить.
Getter:
var settings = {
firstname: 'John',
lastname: 'Smith',
get fullname() { return this.firstname + ' ' + this.lastname; }
};
console.log(settings.fullname);
..., конечно, будет записывать John Smith
. A getter ведет себя как свойство переменной объекта, но предлагает гибкость функции для вычисления возвращаемого значения на лету. Это в основном причудливый способ создания функции, которая не требует () при вызове.
Setter:
var address = {
set raw(what) {
var loc = what.split(/\s*;\s*/),
area = loc[1].split(/,?\s+(\w{2})\s+(?=\d{5})/);
this.street = loc[0];
this.city = area[0];
this.state = area[1];
this.zip = area[2];
}
};
address.raw = '123 Lexington Ave; New York NY 10001';
console.log(address.city);
... будет записывать New York
на консоль. Как и геттеры, сеттеры вызываются с тем же синтаксисом, что и установка значения свойства объекта, но являются еще одним причудливым способом вызова функции без ().
См. this jsfiddle для более тщательного, возможно, более практического примера. Передача значений в установщик объекта запускает создание или совокупность других объектов объекта. В частности, в примере jsfiddle передача массива чисел приводит к тому, что сеттер вычисляет средний, средний, режим и диапазон; затем устанавливает свойства объекта для каждого результата.
maps.roll
как свойство, а не возвращать val maps.roll()
. Это просто предпочтение.
– rojo
30 November 2016 в 01:27
maps.roll()
– Andreas
30 November 2016 в 10:24
Что с этим сбивает с толку ... getters - это функции, которые вызывается, когда вы получаете свойство, сеттеры, когда вы его устанавливаете. Например, если вы выполняете
obj.prop = "abc";
Вы устанавливаете свойство prop, если вы используете геттеры / сеттеры, тогда будет вызываться функция setter, в качестве аргумента будет «abc». Определение функции setter внутри объекта идеально выглядело бы примерно так:
set prop(var) {
// do stuff with var...
}
Я не уверен, насколько хорошо это реализовано в браузерах. Похоже, у Firefox также есть альтернативный синтаксис, с использованием специальных методов («волшебных») с двойным подчеркиванием. Как обычно, Internet Explorer не поддерживает ничего из этого.
Меня также несколько смутило объяснение , которое я прочитал , потому что я пытался добавить свойство к существующему прототипу, который я не писал, поэтому замена прототипа казалась неправильным подходом. Итак, для потомков, вот как я добавил свойство last
в Array
:
Object.defineProperty(Array.prototype, "last", {
get: function() { return this[this.length - 1] }
});
Когда-либо настолько приятнее, чем добавление функции IMHO.