【问题标题】:How can I slice an object in Javascript?如何在 Javascript 中对对象进行切片?
【发布时间】:2017-01-13 04:14:03
【问题描述】:

我试图使用 Array.prototype 对对象进行切片,但它返回一个空数组,除了传递参数之外还有什么方法可以切片对象,还是只是我的代码有问题?谢谢!!

var my_object = {
 0: 'zero',
 1: 'one',
 2: 'two',
 3: 'three',
 4: 'four'
};

var sliced = Array.prototype.slice.call(my_object, 4);
console.log(sliced);

【问题讨论】:

  • 最接近的方法是使用delete object.property 删除密钥,并确保在此之前将该属性存储在单独的变量中。
  • 您的预期输出是什么?切片对象没有任何意义 - 它没有任何意义,但如果你能解释你希望你的预期输出是什么,我们可以努力实现。
  • 我尝试创建一个新数组,仅使用我可能需要的属性,即:var obj = {car: 'audi', engine: 'diesel', color: 'blue'} as输出我想要一个只有“颜色”属性的新对象。
  • 我想要一个新对象 - 但Array.slice 返回一个数组

标签: javascript arrays object arguments slice


【解决方案1】:

const res = Object.fromEntries(Object.entries(my_object).slice(0,4));

【讨论】:

    【解决方案2】:

    我试图使用Array.prototype 对对象进行切片,但它返回一个空数组

    那是因为它没有 .length 属性。它将尝试访问它,获取undefined,将其转换为一个数字,获取0,并从对象中切出最多那么多属性。为了达到预期的结果,您必须为它分配一个length,或者手动通过对象的迭代器:

    var my_object = {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'};
    
    my_object.length = 5;
    console.log(Array.prototype.slice.call(my_object, 4));
    
    var sliced = [];
    for (var i=0; i<4; i++)
        sliced[i] = my_object[i];
    console.log(sliced);

    【讨论】:

    • 所以我想除了手动修改对象、添加长度或迭代器之外别无他法......
    • 别被愚弄了,继续往下看吧,@trad 现在有最好的答案,还有其他几个聪明的答案。
    【解决方案3】:

    最好的现代解决方案是 Object.fromEntriesObject.entries 的组合。

    const foo = {
        one: 'ONE',
        two: 'TWO',
        three: 'THRE',
        four: 'FOUR',
    }
    
    const sliced = Object.fromEntries(
        Object.entries(foo).slice(1, 3)
    )
    
    console.log(sliced)

    【讨论】:

    • 我很好奇,您是否将其与其他方法进行了基准测试?本能地似乎很慢,但我可能错了。这绝对是最优雅的解决方案恕我直言。
    • 我没有测试过。我的猜测是我的解决方案有点慢,但接受的答案没有返回密钥,而且在我看来不是很干净。
    【解决方案4】:

    你可以reduceObject.keys函数的结果

    const myObject = {
     0: 'zero',
     1: 'one',
     2: 'two',
     3: 'three',
     4: 'four'
    };
    
    const sliced = Object.keys(myObject).slice(0, 2).reduce((result, key) => {
                        result[key] = myObject[key];
    
                        return result;
                    }, {});
    
    console.log(sliced);

    【讨论】:

    • 最好的!喜欢它。
    【解决方案5】:

    尝试将“长度”属性添加到 my_object,然后您的代码应该可以工作:

        var my_object = {
         0: 'zero',
         1: 'one',
         2: 'two',
         3: 'three',
         4: 'four',
         length: 5
        };
        
        var sliced = Array.prototype.slice.call(my_object, 4);
        console.log(sliced);

    【讨论】:

      【解决方案6】:
      var obj = {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four'};
      var result = Object.keys(obj).slice(0,2).map(key => ({[key]:obj[key]}));
      
      console.log(result);
      

      [ { '0': '零' }, { '1': '一' } ]

      【讨论】:

        【解决方案7】:

        还没有人提到Object.entries(),这可能是最灵活的方式。此方法在枚举属性时使用与for..in 相同的顺序,即属性最初输入对象的顺序。您还可以获得具有属性和值的子数组,因此您可以使用其中任何一个或两者都使用。最后,您不必担心属性是数字或设置额外长度属性(就像使用 Array.prototype.slice.call() 时所做的那样)。
        这是一个例子:

        const obj = {'prop1': 'foo', 'prop2': 'bar', 'prop3': 'baz', 'prop4': {'prop': 'buzz'}};
        

        您想要对前两个值进行切片:

        Object.entries(obj).slice(0,2).map(entry => entry[1]);
        //["foo", "bar"]
        

        所有的键?

        Object.entries(obj).slice(0).map(entry => entry[0]);
        //["prop1", "prop2", "prop3", "prop4"]
        

        最后一个键值对?

        Object.entries(obj).slice(-1)
        //[ ['prop4', {'prop': 'buzz'}] ]
        

        【讨论】:

        • Object.entries 肯定是一种有用的了解方法(显然是 ECMA 262 的新方法)......但它似乎只是产生一个数组数组,这并不是 OP 的真正含义要求。
        • Object.entries 在 IE 中不受支持。
        • 不幸的是,这个解决方案将产生一个新的数组而不是一个新的对象。当我们想要对一个对象进行切片时,我们期望的是一个切片的对象,而不是一个切片的数组。
        • 我爱你这个答案@Trad
        【解决方案8】:

        // Works, but acts weird when things get serious
        // Avoids screwing with the properties of my_object
        // You don't get Object.create() until ES5.1
        function lazySlice(obj, idx) {
          var newObj = Object.create(obj, { length: {value: Object.keys(obj).length} }),
          idx = idx || 0;
        
          return Array.prototype.slice.call(newObj, idx);
        }
        
        // Only gives you own enumerable properties with keys "0" to n
        // Preserves element order (based on key number)
        // Ignores non-numbered keys
        // You don't get Object.keys() until ES5
        function enumSlice(obj, idx) {
          var arr = [], 
            keys = Object.keys(obj),
            idx = idx || 0;
        
          for (var i = 0; i <= keys.length - 1; i++)
            if (keys[i] >= idx && keys[i] % 1 === 0 && keys[i] >= 0 && keys[i].indexOf('e') < 0) 
              arr.push(obj[keys[i]]);
        
          return arr;
        }
        
        var my_object = {
          0: 'zero',
          1: 'one',
          2: 'two',
          3: 'three',
          4: 'four'
        }; 
        console.log(lazySlice(my_object, 3));      // [ 'three', 'four' ]
        console.log(enumSlice(my_object, 3));      // [ 'three', 'four' ]
        
        var mixed_object = {
           "9": 'nine',
           "2": 'two',
           "1": 'one',
           "7": 'seven',
           "7.5": 'seven point five',
           "1e4": 'sneaky',
           "-4": 'negative four',
           "0": 'zero',
           "length": 35
        };
        console.log(lazySlice(mixed_object));      // [ 'zero', 'one', 'two', , , , , 'seven',  ]
        console.log(enumSlice(mixed_object));      // [ 'zero', 'one', 'two', 'seven', 'nine' ]

        【讨论】:

          【解决方案9】:

          除非它有一个 [Symbol.iterator] 生成器函数并且 length 属性存在,否则你不能。比如;

          var my_object = { 0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', length:5 },
                 sliced;
          
          my_object[Symbol.iterator] = function* (){
                                                    var oks = Object.keys(this);
                                                    for (var key of oks) yield this[key];
                                                   };
          
          sliced = Array.prototype.slice.call(my_object, 2);
          console.log(sliced);

          【讨论】:

          • 一个迭代器一个长度就足够了,你不需要两者。
          • @Bergi 这就是我想到的只有一个迭代器......我刚刚用一个迭代器进行了测试,但它不起作用..我不确定只有 length 属性它不过会好的。不只是一个迭代器不会削减。可能是我错过了什么。
          • slice 不关心迭代器(它只关心长度),Array.from(my_object).slice(4) 会。我以为你在谈论迭代时想到了Array.from……
          • @Bergi 试试.slice(2)
          • @Bergi 好的,你是对的,只有length 属性很好。必须纠正。
          【解决方案10】:

          你没有在你的问题中提到它,但这看起来非常像一个参数对象。

          使用Array.from() 将其转换为数组,然后像使用任何其他数组一样使用它。只要是可枚举的对象。

          有关旧浏览器的 polyfill,请参阅 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

          【讨论】:

            【解决方案11】:

            我认为它可以帮助你:

            var my_object = { 0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four' };
            
            var sliced = Object.keys(my_object).map(function(key) { return my_object[key] }).slice(4);
            
            console.log(sliced);
            

            【讨论】:

            • 缺点是 keys() 不能保证以任何特定顺序返回对象的键。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-12-10
            • 2021-08-15
            • 2020-08-07
            • 2010-12-17
            • 2010-11-23
            相关资源
            最近更新 更多