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

时间:2008-12-14 01:40:01

标签: javascript browser

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

  

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

     

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

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

8 个答案:

答案 0 :(得分:64)

编辑:由于编写了这个答案,使用Object.defineProperty的一种新的,更好的方法已在EcmaScript 5中标准化,并支持更新的浏览器。见Aidamina's answer。如果您需要支持“较旧”的浏览器,您可以使用此答案中的一种方法作为后备。


在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's blogMozilla Developer Center了解更多信息。

答案 1 :(得分:61)

使用any javascript interpreter that implements ECMAScript 5,您可以使用Object.defineProperty来定义只读属性。在松散模式下,解释器将忽略对属性的写入,在严格模式下,它将抛出异常。

来自ejohn.org的示例:

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

答案 2 :(得分: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

答案 3 :(得分:5)

这里只读取属性或变量。

作为aidamina said,顺便说一下,这是一个简短的测试代码,现在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>

所以你有一个只读的属性或变量。

答案 4 :(得分: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

答案 5 :(得分:2)

以下是Douglas Crockford关于“Javascript私人会员”页面的链接....在我看来,如果只提供了getter方法,并且没有setter,那么这些只会被读取:

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

答案 6 :(得分: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 Version 41.0.2272.76 Ubuntu 14.04上测试过,并产生了以下输出:

          Porche
          Red
          BMW
          White
          Mercedes
          Black
          Green
          Green
          function () { return color; }
          Black

答案 7 :(得分:0)

bob.js framework提供了一种声明只读属性的方法。在引擎盖下,它声明了一个私有字段并为它公开了getter / setter函数。 bob.js提供了多种方法来完成同样的事情,具体取决于方便性和具体目标。这是一种使用Property的面向对象实例的方法(其他方法允许在对象本身上定义setter / getters):

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未定义,因为这是一个只读属性。