[英]Is it possible to initialize an object with the literal notation if there are dependencies among its members?
[英]Is it possible to create read only members in JavaScript Object Literal Notation?
我有以下JavaScript對象文字表示法對象
var Parameters= {
modal_window:{
backdrop:true,
keyboard:true,
show:true,
remote:false,
type:{
normal:function(){
this.footer.button.accept.type='btn btn-primary';
this.header.type='modal-header';
},
success:function(){
this.footer.button.accept.type='btn btn-success';
this.header.type='modal-header alert alert-success';
},
info:function(){
this.footer.button.accept.type='btn btn-info';
this.header.type='modal-header alert alert-info';
},
error:function(){
this.footer.button.accept.type='btn btn-danger';
this.header.type='modal-header alert alert-error';
},
warning:function(){
this.footer.button.accept.type='btn btn-warning';
this.header.type='modal-header alert';
}
}
},
header:{
title:undefined,
type:this.window.type.normal.header
},
footer:{
button:
{
accept:{
title:'Accept',
click:undefined,
type:undefined
},
cancel:{
title:'Cancel',
click:undefined
}
}
}
};
是否可以使header.type和footer.button.accept.type只讀只能通過window.type.normal,window.type.success等進行更改的變量?
澄清:我想在這里做一些澄清。 我的Parameters.header.type應該是只讀的,並且應該具有默認值。 並且當用戶選擇例如Parameters.modal_window.type.normal Parameters.header.type時,必須進行更改。
不管大家怎么說,您都可以在支持Object.defineProperty
現代瀏覽器中創建只讀屬性。
var obj = {};
Object.defineProperty(obj, 'someProp', {
configurable: false,
writable: false,
value: 'initial value'
});
obj.someProp = 'some other value';
console.log(obj.someProp); //initial value
編輯:
再次閱讀您的問題后,我了解到您的意思是真正的私有成員或私有變量。 這可以通過使用閉包和自定義getter / setter來實現。
注意:為便於說明,我簡化了對象的結構。
var Parameters = (function () {
var headerType = 'some value'; //private variable
return {
modal_window: {
type: {
normal: function () {
//custom logic
headerType = 'some new value'; //set private variable
}
}
},
header: {
get type() { return headerType; } //define a getter only
//for older browsers, you could just define a normal function
//which you would have to access like Parameters.header.type()
//type: function () { return headerType; }
}
};
})();
var header = Parameters.header;
console.log(header.type); //some value
header.type = 'some other val';
console.log(header.type); //some value
Parameters.modal_window.type.normal();
console.log(header.type); //some new value
既然我們知道可以實施真正的隱私,但我不確定這是否值得。 實施真正的隱私會使設計復雜化,並降低可測試性(取決於情況)。 一種很流行的方法是使用諸如_myPrivateVar
的命名約定簡單地標識私有成員。 這清楚地表明了這種意圖,並告訴程序員他們應該像對待私人成員那樣對待該成員。
您可以使它們起作用,如下所示:
header:{
title:undefined,
type: function(){
return Parameters.modal_window.type.normal.header;
}
}
如果需要支持IE 8或更早版本,則可以創建一個訪問器方法來檢索該值,然后使用私有變量存儲實際數據。 如果您適當地定義方法,則可以從它們中設置私有變量,但外界不能設置。 在IE8中,無法定義只讀屬性,因此您必須改為使用訪問器。
有關如何設置訪問者可以用作接口的私有數據的詳細信息,請參見Crockford關於私有成員數據的論述: http : //javascript.crockford.com/private.html 。
如果您願意使用IE9或更高版本,則可以通過Object.defineProperty()
將getter與閉包中的私有變量結合使用。 如果沒有設置器,則無法從外部設置它,但是閉包中定義的方法(在克羅克福德的文章中進行了描述)仍然可以設置私有變量的值。 您將擁有一個只讀屬性,該屬性也可以由您自己的一些方法設置。
您可以創建一個屬性並將其設置為不可寫。 您的構造函數必須用屬性替換值。 如果屬性返回的變量是在閉包中捕獲的,並且沒有暴露給其他對象,則該變量將與只讀變量一樣好。 如果未更改,則甚至不需要關閉,只需使用value
配置選項即可。
編輯:根據您的要求,
var Properties = function(obj) {
var makePropRecursive = function(prop) {
var old_prop = obj[prop];
delete obj[prop];
var prop_obj = {};
for (var attr in old_prop) {
if (old_prop.hasOwnProperty(attr)) {
Object.defineProperty(prop_obj, attr, {
value: old_prop[attr],
writable: false,
enumerable: true
});
}
}
Object.defineProperty(obj, prop, {
value: prop_obj,
writable: false,
enumerable: true
});
};
makePropRecursive('header');
makePropRecursive('footer');
return obj;
};
var props = new Properties({
modal_window:{
backdrop:true,
keyboard:true,
show:true,
remote:false,
type:{
normal:function(){
this.footer.button.accept.type='btn btn-primary';
this.header.type='modal-header';
},
success:function(){
this.footer.button.accept.type='btn btn-success';
this.header.type='modal-header alert alert-success';
},
info:function(){
this.footer.button.accept.type='btn btn-info';
this.header.type='modal-header alert alert-info';
},
error:function(){
this.footer.button.accept.type='btn btn-danger';
this.header.type='modal-header alert alert-error';
},
warning:function(){
this.footer.button.accept.type='btn btn-warning';
this.header.type='modal-header alert';
}
}
},
header:{
title:"Whatever",
type:"Type"
},
footer:{
button:
{
accept:{
title:'Accept',
click:undefined,
type:undefined
},
cancel:{
title:'Cancel',
click:undefined
}
}
}
});
console.log(props.header);
props.header = 17;
props.header.type = 18;
props.header.title = 19;
console.log(props.header);
props.header
不變:輸出顯示
Object {title: "Whatever", type: "Type"}
Object {title: "Whatever", type: "Type"}
現在是凌晨3點,而遞歸函數不是,所以您只能“修復”一個對象的一個級別。 同樣,最好將值復制this
值而不是返回obj
; 但對其進行拋光應該並不難。
如果需要更改值,則可以在構造函數中設置整個對象的私有副本,然后進行吸氣( get: function(name) { return stuff.from.the.original.object }
)。
在較新版本的JavaScript中,您可以定義屬性訪問的工作方式:
var yourObj = function() {
var readOnly = "cannot be changed";
return {
get readOnly() { return readOnly; },
set readOnly(v) { return; },
specialSetter: function(something) {
if (something == "magic number") {
readOnly = "oops maybe it can";
}
}
};
}();
現在代碼可以得到如下值:
var theValue = yourObj.readOnly;
無需進行函數調用。 但是,如果嘗試更改該值:
yourObj.readOnly = "hello world";
那什么也不會發生
設置器或任何其他函數都可以在需要時仍更新訪問“ readOnly”屬性時將返回的值。 但是,任何直接設置屬性的嘗試都不會做任何事情(除非setter函數決定它喜歡該值)。
編輯您可能希望將“ specialSetter”設置為只讀,盡管沒有任何東西可以“破解”閉包。 另外,您可能想使用Object.defineProperty來使“ readOnly”不可寫,但是我不知道這樣是否可以正常工作。
怎么樣: Object.freeze()
您可以在此處找到更多信息: MDN Object.freeze
所以:
Object.freeze(Parameters.modal_window.header);
...
然后,在您希望能夠對其進行設置的功能中,對它們進行解凍,更改並重新凍結。
您絕對不能更改凍結的對象,這是錯誤地在程序中的其他任何地方。
這適用於IE9 + Chrome,Firefox和Safari。
您可以使用下面的顯示模塊模式來隱藏變量並防止其被更改,但這不會阻止任何人更改可訪問的“類型”功能。
在代碼下面,標頭屬性更改為_header並成為一個函數。 屬性類型已更改為_type,並通過用對象表示法包裝返回來將“ type”作為函數而不是屬性返回來隱藏。 有人可以通過重寫將類型函數更改為所需的任何內容,但不能更改_type的值。
var Parameters = function () {
var _modal_window = function modal_window() {
var backdrop = true,
keyboard = true,
show = true,
remote = false;
return {
type: {
normal: function () {
this.footer.button.accept.type = 'btn btn-primary';
this.header.type = 'modal-header';
},
success: function () {
this.footer.button.accept.type = 'btn btn-success';
this.header.type = 'modal-header alert alert-success';
},
info: function () {
this.footer.button.accept.type = 'btn btn-info';
this.header.type = 'modal-header alert alert-info';
},
error: function () {
this.footer.button.accept.type = 'btn btn-danger';
this.header.type = 'modal-header alert alert-error';
},
warning: function () {
this.footer.button.accept.type = 'btn btn-warning';
this.header.type = 'modal-header alert';
}
}
};
}();
var _header = function header() {
var _type = 'This causes error';//this.window.type.normal.header;
return {
title: undefined, type: function () { return _type; }
};
}();
var _footer = function footer() {
return {
button:
{
accept: {
title: 'Accept',
click: undefined,
type: undefined
},
cancel: {
title: 'Cancel',
click: undefined
}
}
};
}();
return {
modal_window: _modal_window,
header: _header,
footer: _footer
};
}();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.