纯JavaScript可以实现只读属性吗?

问题描述 投票:0回答:10

查看 mozilla 文档,查看正则表达式示例(标题为“使用匹配结果创建数组”),我们有如下语句:

input:只读属性,反映正则表达式匹配的原始字符串。

index:只读属性,是字符串中匹配项的从零开始的索引。

等等...是否可以在 JavaScript 中创建自己的对象,该对象将具有只读属性,或者这是为特定浏览器实现的内置类型保留的特权?

javascript browser
10个回答
73
投票

使用任何实现 ECMAScript 5 的 javascript 解释器,您可以使用 Object.defineProperty 来定义只读属性。在松散模式下,解释器将忽略对属性的写入,在严格模式下,它将引发异常。

来自

ejohn.org的示例:

var obj = {}; Object.defineProperty( obj, "<yourPropertyNameHere>", { value: "<yourPropertyValueHere>", writable: false, enumerable: true, configurable: true });
    

70
投票

编辑:自从编写此答案以来,EcmaScript 5 中已经标准化了一种使用 Object.defineProperty

 的新的、更好的方法,并得到了较新浏览器的支持。请参阅
Aidamina 的回答。如果您需要支持“旧版”浏览器,您可以使用此答案中的方法之一作为后备。


在 Firefox、Opera 9.5+、Safari 3+、Chrome 和 IE(使用 v11 测试)中,您可以定义 getter 和 setter 属性。如果您只定义一个 getter,它会有效地创建一个只读属性。您可以在对象文字中或通过调用对象上的方法来定义它们。

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 中不起作用。

您可以从

John Resig 的博客Mozilla 开发人员中心 阅读更多相关信息。


6
投票
JavaScript 中可以有只读属性,可通过 getter 方法获取这些属性。这通常称为“模块”模式。

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
    

5
投票
这里它是只读属性或变量。

正如

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>

因此您已经测试了只读属性或变量。


3
投票
是的,我们可以在 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
    

2
投票
这里有一个指向 Douglas Crockford 的“Javascript 中的私有成员”页面的链接....在我看来,只有在仅提供 getter 方法而不提供 setter 的情况下,这些内容才会被读取:

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


1
投票
您将看到我已经定义了颜色的 setter 和 getter,以便可以对其进行修改。另一方面,一旦定义了对象,品牌就变为只读。我相信这就是您正在寻找的功能。

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
投票
如果您希望在运行时获得只读属性而不必启用“严格模式”,一种方法是定义“抛出设置器”。示例:

Object.defineProperty(Fake.prototype, 'props', { set: function() { // We use a throwing setter instead of frozen or non-writable props // because that won't throw in a non-strict mode function. throw Error(); }, });
参考自

React


0
投票

bob.js 框架提供了一种声明只读属性的方法。在底层,它声明了一个私有字段并公开了它的 getter/setter 函数。 bob.js 提供了多种方法来完成同一件事,具体取决于便利性和具体目标。这是一种使用 Property

 面向对象实例的方法(其他方法允许在对象本身上定义 setter/getter):

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
投票
其他答案是正确的,但没有人提到

私有类字段,这是定义只读属性的另一种选择(假设类对您的用例有意义):

class Car { color = ''; // public field #serialNumber = ''; // # is a private field constructor(color, serialNumber) { this.color = color; this.#serialNumber = serialNumber; } // Public read-only access to serial number get serialNumber() { return this.#serialNumber; } } const car = new Car('black', '123XYZ'); car.color = 'red'; // Changes color car.serialNumber; // Returns private value car.serialNumber = 'other'; // Does nothing car.serialNumber; // Returns private value as before
    
© www.soinside.com 2019 - 2024. All rights reserved.