Могут ли свойства только для чтения быть реализованы в чистом JavaScript?

Просматривая документацию mozilla , просматривая пример регулярного выражения (озаглавленный «Создание массива с использованием результата совпадения»), мы имеем такие выражения:

input: свойство только для чтения, которое отражает исходную строку, с которой сопоставлялось регулярное выражение.

index: Свойство только для чтения, которое является нулевым индексом совпадения в строке.

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

14.12.2008 01:40:01
Я задал подобный вопрос здесь: stackoverflow.com/questions/7757337/…
Šime Vidas 13.10.2011 17:05:54
Если кто-то пытается создать полностью неизменяемую копию существующего объекта (то есть объекта, который имеет свойства только для чтения / неизменяемости), это может помочь: stackoverflow.com/questions/16064136/…
Himanshu P 18.04.2013 10:53:30
Object.sealпредотвращает добавление новых свойств к объекту (хотя существующие свойства могут быть изменены) и Object.freezeпредотвращает все изменения объекта. Оба Object.sealи Object.freezeхорошо поддерживаются.
Dave F 17.04.2020 21:50:40
8 ОТВЕТОВ
РЕШЕНИЕ

Редактировать: с тех пор, как этот ответ был написан, новый, лучший способ использования Object.definePropertyбыл стандартизирован в EcmaScript 5 с поддержкой в ​​более новых браузерах. Смотри ответ Айдамины . Если вам нужно поддерживать «старые» браузеры, вы можете использовать один из методов в этом ответе как запасной вариант.


В Firefox, Opera 9.5+ и Safari 3+, Chrome и IE (протестировано с v11) вы можете определить свойства получателя и установщика. Если вы определяете только метод получения, он фактически создает свойство только для чтения. Вы можете определить их в литерале объекта или вызвав метод объекта.

var myObject = {
    get readOnlyProperty() { return 42; }
};

alert(myObject.readOnlyProperty); // 42
myObject.readOnlyProperty = 5;    // Assignment is allowed, but doesn't do anything
alert(myObject.readOnlyProperty); // 42

Если у вас уже есть объект, вы можете позвонить __defineGetter__и __defineSetter__:

var myObject = {};
myObject.__defineGetter__("readOnlyProperty", function() { return 42; });

Конечно, это не очень полезно в Интернете, потому что оно не работает в Internet Explorer.

Вы можете прочитать больше об этом в блоге Джона Резига или в Центре разработчиков Mozilla .

66
23.05.2017 12:25:43
Неплохо! Я тестировал, и он работает в Firefox, Opera и Chrome, но не в IE.
some 14.12.2008 02:39:25
дополнительное примечание - это часть какой-либо спецификации javascript?
Claudiu 14.12.2008 03:46:16
Это не часть текущей спецификации. Я полагаю, что это запланировано на следующую версию ECMAScript, но сейчас это просто расширение Mozilla, которое поддерживается в нескольких других браузерах.
Matthew Crumley 14.12.2008 03:49:15
и до сих пор не поддерживается IE;)
Sergiy Belozorov 6.08.2010 13:26:36
Для вашей утилиты эта техника поддерживается IE начиная с 9-й версии. Вот хорошая таблица совместимости: kangax.github.io/es5-compat-table
Emanuele Del Grande 17.02.2014 11:39:04

В JavaScript можно иметь свойства только для чтения, которые доступны через методы получения. Обычно это называется шаблоном «Модуль».

В блоге YUI есть хорошая статья: http://yuiblog.com/blog/2007/06/12/module-pattern/

Фрагмент из поста:

YAHOO.myProject.myModule = function () {

//"private" variables:
var myPrivateVar = "I can be accessed only from within YAHOO.myProject.myModule.";

//"private" method:
var myPrivateMethod = function () {
    YAHOO.log("I can be accessed only from within YAHOO.myProject.myModule");
}

return  {
    myPublicProperty: "I'm accessible as YAHOO.myProject.myModule.myPublicProperty."
    myPublicMethod: function () {
        YAHOO.log("I'm accessible as YAHOO.myProject.myModule.myPublicMethod.");

        //Within myProject, I can access "private" vars and methods:
        YAHOO.log(myPrivateVar);
        YAHOO.log(myPrivateMethod());

        //The native scope of myPublicMethod is myProject; we can
        //access public members using "this":
        YAHOO.log(this.myPublicProperty);
    }
};

}(); // the parens here cause the anonymous function to execute and return
6
14.12.2008 02:19:13

Вот ссылка на страницу Дугласа Крокфорда «Частные члены в Javascript» .... мне кажется, что они будут читаться только при условии предоставления только методов получения, а не установки:

http://javascript.crockford.com/private.html

2
14.02.2014 14:28:14
Есть разница между приватным и только для чтения . Закрытые переменные (и то, как Крокфорд реализует их в JavaScript) являются просто частными , это означает, что они доступны внутри класса (конструктора), но не доступны извне, поэтому очевидно, что вы не можете изменить то, к чему у вас нет доступа. Свойства только для чтения могут быть выставлены извне, но не изменены.
Emanuele Del Grande 14.02.2014 13:47:19
Действительно ли нужно понижать ссылку только на ответы пяти с половиной лет назад? Текущие ограничения не были на месте
Dexygen 18.08.2014 14:52:32

С любым интерпретатором JavaScript, который реализует ECMAScript 5, вы можете использовать Object.defineProperty для определения свойств только для чтения. В свободном режиме интерпретатор игнорирует запись в свойстве, в строгом режиме он генерирует исключение.

Пример из ejohn.org :

var obj = {};
Object.defineProperty( obj, "<yourPropertyNameHere>", {
  value: "<yourPropertyValueHere>",
  writable: false,
  enumerable: true,
  configurable: true
});
64
10.02.2015 13:36:49
Примечание: это совместимо с IE9 +, поэтому довольно хорошо поддерживается сегодня.
Benjamin 31.01.2015 14:18:33

Каркас bob.js предоставляет способ объявления свойств только для чтения. Под капотом он объявляет приватное поле и предоставляет для него функции получения / установки. bob.js предоставляет несколько способов сделать то же самое, в зависимости от удобства и конкретных целей. Вот один подход, который использует объектно-ориентированный экземпляр Property(другие подходы позволяют определять установщики / получатели на самом объекте):

var Person = function(name, age) {  
    this.name = new bob.prop.Property(name, true); 
    var setName = this.name.get_setter(); 
    this.age = new bob.prop.Property(age, true); 
    var setAge = this.age.get_setter();  
    this.parent = new bob.prop.Property(null, false, true);  
};  
var p = new Person('Bob', 20);  
p.parent.set_value(new Person('Martin', 50));  
console.log('name: ' + p.name.get_value());  
console.log('age: ' + p.age.get_value());  
console.log('parent: ' + (p.parent.get_value ? p.parent.get_value().name.get_value() : 'N/A')); 
// Output: 
// name: Bob 
// age: 20 
// parent: N/A 

В конце p.name.set_valueне определено, потому что это свойство только для чтения.

0
29.04.2013 21:01:22

Как свойство только для чтения или переменная здесь это.

Как сказал aidamina , и вот короткий код для тестирования, кстати, очень полезный сейчас, когда JQuery делает вид, что устарел в свойстве селектора.

<script>
Object.defineProperties(window, {
  "selector": { value: 'window', writable: false }
});

alert (window.selector);  // outputs window

selector ='ddd';          // testing because it belong to the global object
alert (window.selector);  // outputs window
alert (selector);         // outputs window

window.selector='abc';
alert (window.selector);   // outputs window
alert (selector);          // outputs window
</script>

Итак, у вас есть свойство или переменная, доступная только для чтения.

5
23.05.2017 12:32:32
Я не могу поверить, что это не имеет больше голосов. ты знаешь как это работает?
czioutas 12.02.2014 08:22:57

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

        function Car(brand, color) {
            brand = brand || 'Porche'; // Private variable - Not accessible directly and cannot be frozen
            color = color || 'Red'; // Private variable - Not accessible directly and cannot be frozen
            this.color = function() { return color; }; // Getter for color
            this.setColor = function(x) { color = x; }; // Setter for color
            this.brand = function() { return brand; }; // Getter for brand
            Object.freeze(this); // Makes your object's public methods and properties read-only
        }

        function w(str) {
            /*************************/
            /*choose a logging method*/
            /*************************/
            console.log(str);
            // document.write(str + "<br>");
        }

        var myCar = new Car;
        var myCar2 = new Car('BMW','White');
        var myCar3 = new Car('Mercedes', 'Black');

        w(myCar.brand()); // returns Porche
        w(myCar.color()); // returns Red

        w(myCar2.brand()); // returns BMW
        w(myCar2.color()); // returns White

        w(myCar3.brand()); // returns Mercedes
        w(myCar3.color()); // returns Black

        // This works even when the Object is frozen
        myCar.setColor('Green');
        w(myCar.color()); // returns Green

        // This will have no effect
        myCar.color = 'Purple';
        w(myCar.color()); // returns Green
        w(myCar.color); // returns the method

        // This following will not work as the object is frozen
        myCar.color = function (x) {
            alert(x);
        };

        myCar.setColor('Black');
        w(
            myCar.color(
                'This will not work. Object is frozen! The method has not been updated'
            )
        ); // returns Black since the method is unchanged

Вышеуказанное было протестировано на Chromium версии 41.0.2272.76 Ubuntu 14.04 и дало следующий результат:

          Porche
          Red
          BMW
          White
          Mercedes
          Black
          Green
          Green
          function () { return color; }
          Black
1
8.07.2015 03:31:02
+1. Этот ответ намекает на использование Object.freeze(). ECMAScript 5 добавляет Object.sealи Object.freezeметоды. Метод печати предотвращает добавление свойств, но позволяет записывать / редактировать свойства. Object.freezeМетод будет полностью заблокировать объект, они будут оставаться именно так , как они были , когда вы заморозить их
S.Serpooshan 1.10.2018 06:34:54

Да, мы можем иметь свойство только для чтения для объекта в JavaScript. Это может быть достигнуто с помощью закрытой переменной и object.defineProperty()метода,

Смотрите следующий пример, который иллюстрирует объект, имеющий свойство только для чтения,

function Employee(name,age){
    var _name = name;
    var _age = age;

    Object.defineProperty(this,'name',{
        get:function(){
            return _name;
        }
    })
}

var emp = new Employee('safeer',25);
console.log(emp.name); //return 'safeer'
emp.name='abc';
console.log(emp.name); //again return 'safeer', since name is read-only property
3
7.12.2017 12:34:15