如何在 Javascript 中对对象进行切片?
Posted
技术标签:
【中文标题】如何在 Javascript 中对对象进行切片?【英文标题】:How can I slice an object in 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
返回一个数组
【参考方案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.fromEntries 和 Object.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】:你可以reduce
Object.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()
不能保证以任何特定顺序返回对象的键。以上是关于如何在 Javascript 中对对象进行切片?的主要内容,如果未能解决你的问题,请参考以下文章