【问题标题】:adding to json property that may or may not exist yet添加到可能存在也可能不存在的 json 属性
【发布时间】: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 的更好解决方案在这里。 stackoverflow.com/a/52471690/10405671

标签: javascript jquery arrays json


【解决方案1】:

$.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 并不是动态的。我会研究你的其他建议
  • 不,我正在构建一个只有一个元素的对象并将其合并到数据变量中。如果您的代码有效,它会执行相同的操作,但在您的代码无效时也可以。我仍然很高兴你尝试不同的方式:)
【解决方案2】:
var foo = dashboard['pages'] || {};
foo['pagename'] = 'your thing here';
dashboard['pages'] = foo;

说明:第一行会检查第一个值是null、undefined还是...使用它。

【讨论】:

    【解决方案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】:

      我会用三元运算符来做:

      dashboard['pages'][page] = dashboard['pages'][page] ? dashboard['pages'][page] : {};
      

      无论它是设置/为空还是其他,这都可以解决问题。

      【讨论】:

        【解决方案5】:

        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 的原型中。
        【解决方案6】:

        我猜你需要这个:

        var dashBoard = new Array();
        if(!dashboard['page123']) {
            dashBoard.push('page123');
        } else {
        ...do what you want
        }
        

        您似乎正在处理 XML。

        【讨论】:

          【解决方案7】:

          对我来说最好的解决方案是做一个对象原型

           /**
           * 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
          

          希望对你有帮助:)

          【讨论】:

            【解决方案8】:

            如果你使用下划线>= 1.9.0,你可以使用propertypropertyOf

            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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2022-01-05
                • 1970-01-01
                • 2010-09-20
                • 1970-01-01
                • 2017-08-04
                • 2013-08-22
                相关资源
                最近更新 更多