簡體   English   中英

可以在純 JavaScript 中實現只讀屬性嗎?

[英]Can Read-Only Properties be Implemented in Pure JavaScript?

查看mozilla 文檔,查看正則表達式示例(標題為“使用匹配結果創建數組”),我們有如下語句:

輸入:一個只讀屬性,反映與正則表達式匹配的原始字符串。

index:只讀屬性,它是字符串中匹配項的從零開始的索引。

等等...是否可以在 JavaScript 中創建您自己的具有只讀屬性的對象,或者這是為特定瀏覽器實現的內置類型保留的特權?

編輯:由於編寫了這個答案,使用Object.defineProperty一種新的,更好的方法已在EcmaScript 5中標准化,並支持更新的瀏覽器。 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; });

當然,這在Web上並不實用,因為它在Internet Explorer中不起作用。

您可以從John Resig的博客Mozilla開發人員中心了解更多相關信息。

使用任何實現ECMAScript 5的javascript解釋器,您可以使用Object.defineProperty來定義只讀屬性。 在松散模式下,解釋器將忽略對屬性的寫入,在嚴格模式下,它將拋出異常。

來自ejohn.org的示例:

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

可以在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

作為readonly屬性或變量在這里。

正如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>

所以你有一個readonly屬性或變量測試。

是的,我們可以在JavaScript中擁有對象的只讀屬性。 它可以通過private變量和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

這里是道格拉斯·克羅克福德關於“Javascript私人會員”頁面的鏈接......在我看來,如果只提供了getter方法,並且沒有setter,這些只會被讀取:

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

您將看到我已經為顏色定義了一個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 

bob.js框架提供了一種聲明只讀屬性的方法。 在引擎蓋下,它聲明了一個私有字段並為它公開了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因為這是一個只讀屬性。

如果您想在運行時獲得只讀屬性而不必啟用“嚴格模式”,一種方法是定義“拋出設置器”。 例子:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM