在 JavaScript 中定义只读属性

给定一个对象 obj,我想定义一个只读属性 'prop',并将其值设置为 val。这样做合适吗?

Object.defineProperty( obj, 'prop', {
get: function () {
return val;
}
});

结果应该是(对于 val = 'test') :

obj.prop; // 'test'
obj.prop = 'changed';
obj.prop; // still 'test' since it's read-only

这个方法工作顺便说一下: http://jsfiddle.net/GHMjN/
我只是不确定这是不是最简单/最顺利/最合适的方法..。

81913 次浏览

相反,您可以使用属性描述符的 writable属性,它可以防止需要 get访问器:

var obj = {};
Object.defineProperty(obj, "prop", {
value: "test",
writable: false
});

正如评论中提到的,writable选项默认为 false,所以在这种情况下可以省略它:

Object.defineProperty(obj, "prop", {
value: "test"
});

这是 ECMAScript 5,所以不能在较老的浏览器中工作。

由于旧的浏览器(向后兼容性) ,我不得不为属性提供访问器函数。我把它变成了 Bob Js的一部分:

var obj = { };
//declare read-only property.
bob.prop.namedProp(obj, 'name', 'Bob', true);
//declare read-write property.
bob.prop.namedProp(obj, 'age', 1);


//get values of properties.
console.log(bob.string.formatString('{0} is {1} years old.', obj.get_name(), obj.get_age()));
//set value of read-write property.
obj.set_age(2);
console.log(bob.string.formatString('Now {0} is {1} years old.', obj.get_name(), obj.get_age()));


//cannot set read-only property of obj. Next line would throw an error.
// obj.set_name('Rob');


//Output:
//========
// Bob is 1 years old.
// Now Bob is 2 years old.

希望能有所帮助。

在新的浏览器或 Node Js中,可以使用 Ref = “ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global _ Objects/Proxy”rel = “ nofollow noReferrer”> Proxy 创建只读对象。

var obj = {
prop: 'test'
}


obj = new Proxy(obj ,{
setProperty: function(target, key, value){
if(target.hasOwnProperty(key))
return target[key];
return target[key] = value;
},
get: function(target, key){
return target[key];
},
set: function(target, key, value){
return this.setProperty(target, key, value);
},
defineProperty: function (target, key, desc) {
return this.setProperty(target, key, desc.value);
},
deleteProperty: function(target, key) {
return false;
}
});

您仍然可以为该对象分配新属性,并且它们也将是只读的。

例子

obj.prop
// > 'test'


obj.prop = 'changed';
obj.prop
// > 'test'


// New value
obj.myValue = 'foo';
obj.myValue = 'bar';


obj.myValue
// > 'foo'

我试过了,很管用。

element.readOnly = "readOnly"  (then .readonly-> true)
element.readOnly = ""  (then .readonly-> false)

在我的例子中,我需要一个只能设置其属性一次的对象。
所以当有人试图更改已经设置的值时,我让它抛出一个错误。

class SetOnlyOnce {
#innerObj = {}; // private field, not accessible from outside


getCurrentPropertyName(){
const stack = new Error().stack; // probably not really performant method
const name = stack.match(/\[as (\w+)\]/)[1];
return name;
}


getValue(){
const key = this.getCurrentPropertyName();


if(this.#innerObj[key] === undefined){
throw new Error('No global param value set for property: ' + key);
}


return this.#innerObj[key];
}


setValue(value){
const key = this.getCurrentPropertyName();


if(this.#innerObj[key] !== undefined){
throw new Error('Changing global parameters is prohibited, as it easily leads to errors: ' + key)
}


this.#innerObj[key] = value;
}
}




class GlobalParams extends SetOnlyOnce {
get couchbaseBucket() { return this.getValue()}
set couchbaseBucket(value){ this.setValue(value)}


get elasticIndex() { return this.getValue()}
set elasticIndex(value){ this.setValue(value)}
}


const _globalParams = new GlobalParams();


_globalParams.couchbaseBucket = 'some-bucket';
_globalParams.elasticIndex = 'some-index';


console.log(_globalParams.couchbaseBucket)
console.log(_globalParams.elasticIndex)


_globalParams.elasticIndex = 'another-index'; // ERROR is thrown here
console.log(_globalParams.elasticIndex)