添加到可能存在也可能不存在的 json 属性
Posted
技术标签:
【中文标题】添加到可能存在也可能不存在的 json 属性【英文标题】:adding to json property that may or may not exist yet 【发布时间】:2011-02-01 07:51:57 【问题描述】:假设我想这样做:
var dashboard = ;
var page = "index";
$('.check').click(function()
$(this).toggleClass("active").siblings().slideToggle('slow', function()
dashboard['pages'][page][$(this).closest('li').attr("id")]['show'] = $(this).is(":hidden") ? 'collapsed' : 'expanded';
);
我收到一条错误消息:
Dashboard.pages 未定义
是否可以动态添加pages
和随后的子代,而无需检查它是否先定义,然后再检查是否定义:
dashboard['pages'] = ;
因为有时它们可能已经存在,我不想先检查树,我只想根据需要构建分支
编辑
我将pagename
更改为page
以表明页面名称会发生变化,而且我想指出这些页面实际上也可以是任何东西。
这个想法是你有任何对象可以包含带有参数的对象,而无需检查分支是否存在
看起来$extend
如前所述将是可行的方法,只是不确定它是如何工作的。必须解决这个问题。
【问题讨论】:
抱歉 - 脚本对我来说毫无意义。使用括号索引器意味着希望动态索引对象,但您使用的是常量。再加上你“不想做这项工作”的说法,我想知道你是否知道你想要完成什么。不是试图诋毁 - 只是观察一下为什么您可能无法得到您正在寻找的答案。 ES6 的更好解决方案在这里。 ***.com/a/52471690/10405671 【参考方案1】:在 Object
上定义 get 和 set 方法。实际上它可以只在 dashboard
对象上定义,而且只在它的后代上,但这很容易做到。
Object.prototype.get = function(prop)
this[prop] = this[prop] || ;
return this[prop];
;
Object.prototype.set = function(prop, value)
this[prop] = value;
使用此get()
方法遍历嵌套属性,并在必须设置值时调用set()
。
var dashboard = ;
dashboard.get('pages').get('user').set('settings', 'oh crap');
// could also set settings directly without using set()
dashboard.get('pages').get('user').settings = 'oh crap';
console.log(dashboard); // pages: user: settings: "oh crap";
您还可以扩展/修改get
方法以接受嵌套属性作为单独的参数或数组或字符串。使用它,您只需调用一次 get:
// get accepts multiple arguments here
dashboard.get('pages', 'user').set('settings', 'something');
// get accepts an array here
dashboard.get(['pages', 'user']).set('settings', 'something');
// no reason why get can't also accept dotted parameters
// note: you don't have to call set(), could directly add the property
dashboard.get('pages.user').settings = 'something';
更新:
由于get方法一般返回一个对象,不知道你需要一个数组还是其他类型的对象,所以你必须自己指定:
dashboard.get('pages.user').settings = [];
然后您可以将项目推送到设置数组
dashboard.get('pages.user').settings.push('something');
dashboard.get('pages.user').settings.push('something else');
要真正让 get 函数从给定字符串(例如 pages.user)构造对象层次结构,您必须将字符串拆分为多个部分并检查每个嵌套对象是否存在。这是 get
的修改版本,它就是这样做的:
Object.prototype.get = function(prop)
var parts = prop.split('.');
var obj = this;
for(var i = 0; i < parts.length; i++)
var p = parts[i];
if(obj[p] === undefined)
obj[p] = ;
obj = obj[p];
return obj;
// example use
var user = dashboard.get('pages.user');
user.settings = [];
user.settings.push('something');
user.settings.push('else');
console.log(dashboard); // pages: user: settings: ["something", "else"]
// can also add to settings directly
dashboard.get('pages.user.settings').push('etc');
【讨论】:
好的,这看起来像我要求的,除了我没有使用原型我将如何在 jquery 中执行此操作?也让我更进一步让我说我想这样做,所以我有 dashboard.get('pages.user.settings').push("something"); dashboard.get('pages.user.settings').push("somethingelse");那应该在设置中给我两个项目吧? @mmcgrail,这是常规的 javascript,而不是 Prototype 框架。获取每个属性的第一种方法应该适用于每个浏览器(不需要 jquery)。更新其他查询的答案。 我会告诫不要以这种方式盲目地添加到Object
的原型中。【参考方案2】:
我会用三元运算符来做:
dashboard['pages'][page] = dashboard['pages'][page] ? dashboard['pages'][page] : ;
无论它是设置/为空还是其他,这都可以解决问题。
【讨论】:
【参考方案3】:我不认为有一个好的内置方法可以做到这一点,但你总是可以用一个函数来抽象它。
function getProperty(obj,prop)
if( typeof( obj[prop] ) == 'undefined' )
obj[prop] = ;
return obj[prop];
那你就用
getProperty(dashboard,'pages')['pagename']
或
getProperty(getProperty(dashboard,'pages'),'pagename');
如前所述,$.extend 将减轻这方面的负担。
【讨论】:
【参考方案4】:对我来说最好的解决方案是做一个对象原型
/**
* OBJECT GET
* Used to get an object property securely
* @param object
* @param property
* @returns *
*/
Object.get = function(object, property)
var properties = property.split('.');
for (var i = 0; i < properties.length; i++)
if (object && object[properties[i]])
object = object[properties[i]];
else
return null;
return object;
;
然后你可以像这样得到你的财产
var object = step1: step2: step3: ['value1', 'value2']
Object.get(object, 'step1.step2.step3'); // ['value1', 'value2']
Object.get(object, 'step1.step2.step3.0'); // 'value1'
Object.get(object, 'step1.step2.step3.step4'); // null
希望对你有帮助:)
【讨论】:
【参考方案5】:var foo = dashboard['pages'] || ;
foo['pagename'] = 'your thing here';
dashboard['pages'] = foo;
说明:第一行会检查第一个值是null、undefined还是...使用它。
【讨论】:
【参考方案6】:$.extend 是要走的路
function elem(a,b)
var r='pages':'pagename':;
r.pages.pagename[a]='show':b;
return r;
data=;
//inside the event handler or something:
data = $.extend(true,data,elem($(this).closest('li').attr("id"),$(this).is(":hidden") ? 'collapsed' : 'expanded'));
但老实说 - 无论如何,存储这些信息是一个相当混乱的想法。 我敢打赌,如果您以后需要这些信息,可以使用一个好的选择器或 jQuery.data()
【讨论】:
但在函数中定义 json 并不是动态的。我会研究你的其他建议 不,我正在构建一个只有一个元素的对象并将其合并到数据变量中。如果您的代码有效,它会做同样的事情,但在您的代码无效时也可以。我仍然很高兴你尝试不同的方式:)【参考方案7】:我猜你需要这个:
var dashBoard = new Array();
if(!dashboard['page123'])
dashBoard.push('page123');
else
...do what you want
您似乎正在处理 XML。
【讨论】:
【参考方案8】:如果你使用下划线>= 1.9.0,你可以使用property
和propertyOf
:
d=a: b: "c"
_.property(["a", "b", "c", "e"])(d) // undefined
_.property(["a", "b"])(d) // "c"
_.propertyOf(d)(["a", "b", "c", "e"]) // undefined
_.propertyOf(d)(["a", "b"]) // "c"
【讨论】:
【参考方案9】:我的小对象实用程序库中的这个方法回答了@mcgrailm 在他对标记答案的评论中提出的问题: 问题 dashboard.get('pages.user.settings').push("something"); dashboard.get('pages.user.settings').push("somethingelse") 回答
const users =
0:
name:"John",
age:30,
car:null,
job: "Developer",
address: "Dakar",
interest:
music: ["rnb", "rap"],
sports: ["football", "basketball"],
food: [
senegal: 0:"yassa", 1:"mafé",
mali: ["yassa", "mafé", "jolof rice"]
,
usa: ["burger", "nuggets",
[
jfr:["jfr_sn", "jfr_ng"]
]
]
,
italia: ["pizza", "peperoni"]
]
,
1:
name:"Jane",
age:20,
car:null,
job: "attorney",
address: "Dakar",
interest:
music: ["rnb", "rap"],
sports: ["football", "basketball"],
language: ["deutch", "english"]
,
2:
name:"Moussa",
age:26,
car:null,
job: "plice officer",
address: "Dakar",
interest:
music: ["rnb", "rap", "trap"],
sports: ["basketball", "handball"],
countries:
Africa: ["Senegal", "Rwanda", "Morroco"],
Europe: ["England", "Russia"],
Asia: ["China", "Saudi Arabia", "Palestine"],
America: ["Brasil", "Mexico", "USA"],
Oceania: ["Australia"]
/*In this example we are using our users object declared previously and we are tryin to access the jfr key
by using the path that leads to this key
*/
//using vanilla js
let result1 = users[0].interest.food[1].usa[2][0].jfr
//using this library
let result2 = _Object(users).getEntryByPath("0.interest.food.1.usa.2.0.jfr")
//expected output for both method
[ "jfr_sn", "jfr_ng" ]
更多实用程序访问https://www.npmjs.com/package/spicy_object
【讨论】:
以上是关于添加到可能存在也可能不存在的 json 属性的主要内容,如果未能解决你的问题,请参考以下文章