问题
I was trying to slice an object using Array.prototype, but it returns an empty array, is there any method to slice objects besides passing arguments or is just my code that has something wrong? Thx!!
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);
回答1:
I was trying to slice an object using
Array.prototype
, but it returns an empty array
That's because it doesn't have a .length
property. It will try to access it, get undefined
, cast it to a number, get 0
, and slice at most that many properties out of the object. To achieve the desired result, you therefore have to assign it a length
, or iterator through the object manually:
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);
回答2:
Nobody mentioned Object.entries() yet, which might be the most flexible way to do it. This method uses the same ordering as for..in
when enumerating properties, i.e. the order that properties were originally entered in the object. You also get subarrays with both property and value so you can use whichever or both. Finally you don't have to worry about the properties being numerical or setting an extra length property (as you do when using Array.prototype.slice.call()
).
Here's an example:
const obj = {'prop1': 'foo', 'prop2': 'bar', 'prop3': 'baz', 'prop4': {'prop': 'buzz'}};
You want to slice the first two values:
Object.entries(obj).slice(0,2).map(entry => entry[1]);
//["foo", "bar"]
All of the keys?
Object.entries(obj).slice(0).map(entry => entry[0]);
//["prop1", "prop2", "prop3", "prop4"]
The last key-value pair?
Object.entries(obj).slice(-1)
//[ ['prop4', {'prop': 'buzz'}] ]
回答3:
You can reduce
the result of Object.keys
function
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);
回答4:
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': 'zero' }, { '1': 'one' } ]
回答5:
I think it can helps you:
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);
回答6:
Try adding a 'length' property to my_object
and then your code should work:
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);
回答7:
You don't mention it in your question, but that looks awfully a lot like an arguments object.
Convert it to an array using Array.from()
then use it like any other array. As long as it is an enumerable object.
For a polyfill for older browsers, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
回答8:
You can't unless it has a [Symbol.iterator]
generator function andlength
property exists. Such as;
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);
回答9:
// 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' ]
来源:https://stackoverflow.com/questions/39336556/how-can-i-slice-an-object-in-javascript