ECMAScript 5에는 유형에 대한 filter()
프로토 타입이 Array
있지만 Object
올바르게 이해하면 유형이 아닙니다 .
JavaScript에서 filter()
for를 어떻게 구현 Object
합니까?
이 객체가 있다고 가정 해 봅시다.
var foo = {
bar: "Yes"
};
그리고 s에서 filter()
작동 하는을 작성하고 싶습니다 Object
.
Object.prototype.filter = function(predicate) {
var result = {};
for (key in this) {
if (this.hasOwnProperty(key) && !predicate(this[key])) {
result[key] = this[key];
}
}
return result;
};
이것은 다음 데모에서 사용할 때 작동하지만 jQuery 1.5 및 jQuery UI 1.8.9를 사용하는 사이트에 추가하면 FireBug에서 JavaScript 오류가 발생합니다.
답변
절대 확장하지 마십시오 Object.prototype
.
코드에 끔찍한 일이 생길 것입니다. 상황이 깨질 것입니다. 객체 리터럴을 포함하여 모든 객체 유형을 확장 하고 있습니다.
시도해 볼 수있는 간단한 예는 다음과 같습니다.
// Extend Object.prototype
Object.prototype.extended = "I'm everywhere!";
// See the result
alert( {}.extended ); // "I'm everywhere!"
alert( [].extended ); // "I'm everywhere!"
alert( new Date().extended ); // "I'm everywhere!"
alert( 3..extended ); // "I'm everywhere!"
alert( true.extended ); // "I'm everywhere!"
alert( "here?".extended ); // "I'm everywhere!"
대신 객체를 전달하는 함수를 작성하십시오.
Object.filter = function( obj, predicate) {
let result = {}, key;
for (key in obj) {
if (obj.hasOwnProperty(key) && !predicate(obj[key])) {
result[key] = obj[key];
}
}
return result;
};
답변
우선, 확장하는 것은 나쁜 습관으로 간주됩니다Object.prototype
. 대신에 유틸리티 함수로 기능을 제공하는 Object
이미있다처럼 Object.keys
, Object.assign
, Object.is
, … 등.
여기에 몇 가지 솔루션을 제공합니다.
- 사용
reduce
하여Object.keys
- (1)과 같이
Object.assign
map
대신 구문 사용 및 확산reduce
- 사용
Object.entries
하여Object.fromEntries
1. 사용 reduce
및Object.keys
로 reduce
하고 Object.keys
원하는 필터 (ES6하여 구현하는 화살표 구문 )
Object.filter = (obj, predicate) =>
Object.keys(obj)
.filter( key => predicate(obj[key]) )
.reduce( (res, key) => (res[key] = obj[key], res), {} );
// Example use:
var scores = {
John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1);
console.log(filtered);
위 코드 에서 OP가 사용한 제외 조건 과 달리 포함 조건 이 작동 방식 과 일치하도록 포함 조건 predicate
이어야 합니다.Array.prototype.filter
2. (1)과 같이 Object.assign
위의 솔루션에서 쉼표 연산자 는 reduce
부분에서 돌연변이 된 res
객체 를 반환하는 데 사용됩니다 . 이것은 물론 하나의 표현 대신 두 개의 진술로 쓰여질 수 있지만 후자는 더 간결합니다. 쉼표 연산자없이 작업을 수행하려면, 당신은 사용할 수 Object.assign
있는 대신 않는 돌연변이 개체를 반환 :
Object.filter = (obj, predicate) =>
Object.keys(obj)
.filter( key => predicate(obj[key]) )
.reduce( (res, key) => Object.assign(res, { [key]: obj[key] }), {} );
// Example use:
var scores = {
John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1);
console.log(filtered);
3. map
대신 구문 사용reduce
여기서 우리 Object.assign
는 루프 밖으로 호출 을 이동 하므로 한 번만 만들어 개별 키를 별도의 인수로 ( spread 구문 사용 ) 전달합니다.
Object.filter = (obj, predicate) =>
Object.assign(...Object.keys(obj)
.filter( key => predicate(obj[key]) )
.map( key => ({ [key]: obj[key] }) ) );
// Example use:
var scores = {
John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1);
console.log(filtered);
4. 사용 Object.entries
및Object.fromEntries
용액은 중간 어레이 객체를 변환 한 후, 일반 오브젝트에 그 위로 변환, 사용하기 위해 유용 할 것이다 Object.entries
(즉, (ES2017)과 반대 키 / 값 쌍의 어레이로부터 객체를 생성 하여) Object.fromEntries
( ES2019).
이 “한 줄짜리”방법으로 이어집니다 Object
.
Object.filter = (obj, predicate) =>
Object.fromEntries(Object.entries(obj).filter(predicate));
// Example use:
var scores = {
John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, ([name, score]) => score > 1);
console.log(filtered);
술어 함수는 여기에서 인수로 키 / 값 쌍을 가져옵니다. 이는 약간 다르지만 술어 함수의 논리에서 더 많은 가능성을 허용합니다.
답변
밑줄 또는 lodash 를 사용하려는 경우 pick
(또는 그 반대 omit
)를 사용할 수 있습니다 .
밑줄 문서의 예 :
_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age');
// {name: 'moe', age: 50}
또는 콜백 ( lodash 의 경우 pickBy 사용 )을 사용 하십시오 .
_.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
return _.isNumber(value);
});
// {age: 50}
답변
ES6 접근법 …
아래에이 객체가 있다고 상상해보십시오.
const developers = {
1: {
id: 1,
name: "Brendan",
family: "Eich"
},
2: {
id: 2,
name: "John",
family: "Resig"
},
3: {
id: 3,
name: "Alireza",
family: "Dezfoolian"
}
};
함수를 작성하십시오.
const filterObject = (obj, filter, filterValue) =>
Object.keys(obj).reduce((acc, val) =>
(obj[val][filter] === filterValue ? acc : {
...acc,
[val]: obj[val]
}
), {});
그리고 그것을 부르십시오 :
filterObject(developers, "name", "Alireza");
그리고 반환합니다 :
{
1: {
id: 1,
name: "Brendan",
family: "Eich"
},
2: {
id: 2,
name: "John",
family: "Resig"
}
}
답변
패트릭은 이미 언급했듯이 사용하기를 원하는 타사 코드를 거의 확실하게 깨뜨릴 수 있으므로 나쁜 생각입니다.
확장하면 jquery 또는 prototype과 같은 모든 라이브러리가 중단됩니다. 추가하는 함수가 반복의 일부이기 때문에 검사 Object.prototype
하지 않고 객체에 대한 지연 반복 hasOwnProperty
이 중단되기 때문입니다.
답변
어때요?
function filterObj(keys, obj) {
const newObj = {};
for (let key in obj) {
if (keys.includes(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
또는…
function filterObj(keys, obj) {
const newObj = {};
Object.keys(obj).forEach(key => {
if (keys.includes(key)) {
newObj[key] = obj[key];
}
});
return newObj;
}
답변
주어진
object = {firstname: 'abd', lastname:'tm', age:16, school:'insat'};
keys = ['firstname', 'age'];
그때 :
keys.reduce((result, key) => ({ ...result, [key]: object[key] }), {});
// {firstname:'abd', age: 16}