jQuery의 extend 메소드에 해당하는 JavaScript
배경
config객체를 인수로 취하는 함수가 있습니다. 함수 내에도 default객체가 있습니다. 이러한 각 개체에는 기본적으로 함수 내의 나머지 코드에 대한 설정으로 작동하는 속성이 포함되어 있습니다. config객체 내의 모든 설정을 지정할 필요가 없도록하기 위해 jQuery의 extend메서드를 사용 settings하여 default객체에 지정되지 않은 경우 객체의 기본값으로 새 객체를 채 웁니다 config.
var config = {key1: value1};
var default = {key1: default1, key2: default2, key 3: default 3};
var settings = $.extend(default, config);
//resulting properties of settings:
settings = {key1: value1, key2: default2, key 3: default 3};
문제
이것은 훌륭하게 작동하지만 jQuery 없이도이 기능을 재현하고 싶습니다. 평범한 자바 스크립트로 이것을 수행하는 똑같이 우아한 (또는 가까운) 수단이 있습니까?
편집 : 중복되지 않은 사유
이 질문은 " 어떻게 두 JavaScript 객체의 속성을 동적으로 병합 할 수 있습니까? "질문과 중복되지 않습니다 . 이 질문은 단순히 두 개의 개별 객체에서 모든 키와 값을 포함하는 객체를 생성하려는 반면, 두 객체가 일부 키를 공유하지만 모든 키를 공유하지 않고 어떤 객체가 우선 순위를 가질 경우이를 수행하는 방법을 구체적으로 설명하고 싶습니다 ( 중복 키가있는 경우 결과 개체에 대해 기본값입니다. 그리고 더 구체적으로, 나는 이것을 달성하기 위해 jQuery의 방법을 사용하고 jQuery없이 그렇게 할 수있는 다른 방법을 찾고 싶었다. 두 질문에 대한 많은 답변이 겹치지 만 그렇다고 질문 자체가 동일하다는 의미는 아닙니다.
코드에서 결과를 얻으려면 다음을 수행하십시오.
function extend(a, b){
for(var key in b)
if(b.hasOwnProperty(key))
a[key] = b[key];
return a;
}
사용한 방법이 기본 개체를 수정한다는 점을 명심하십시오. 원하지 않으면
$.extend({}, default, config)
jQuery의 기능을 모방하는보다 강력한 솔루션은 다음과 같습니다.
function extend(){
for(var i=1; i<arguments.length; i++)
for(var key in arguments[i])
if(arguments[i].hasOwnProperty(key))
arguments[0][key] = arguments[i][key];
return arguments[0];
}
Object.assign을 사용할 수 있습니다.
var defaults = {key1: "default1", key2: "default2", key3: "defaults3"};
var config = {key1: "value1"};
var settings = Object.assign({}, defaults, config); // values in config override values in defaults
console.log(settings); // Object {key1: "value1", key2: "default2", key3: "defaults3"}
하나 이상의 소스 개체에서 모든 열거 가능한 고유 속성의 값을 대상 개체로 복사하고 대상 개체를 반환합니다.
Object.assign(target, ...sources)
IE를 제외한 모든 데스크톱 브라우저에서 작동합니다 (Edge 포함). 모바일 지원이 완화되었습니다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign 에서 직접 확인하십시오.
딥 카피 정보
그러나 Object.assign에는 jQuery의 extend 메소드에있는 딥 옵션이 없습니다.
참고 : 일반적으로 유사한 효과를 위해 JSON을 사용할 수 있습니다.
var config = {key1: "value1"};
var defaults = {key1: "default1", key2: "default2", keyDeep: {
kd1: "default3",
kd2: "default4"
}};
var settings = JSON.parse(JSON.stringify(Object.assign({}, defaults, config)));
console.log(settings.keyDeep); // Object {kd1: "default3", kd2: "default4"}
객체 리터럴에서 ECMA 2018 스프레드 연산자를 사용할 수 있습니다 .
var config = {key1: value1};
var default = {key1: default1, key2: default2, key 3: default 3};
var settings = {...default, ...config}
//resulting properties of settings:
settings = {key1: value1, key2: default2, key 3: default 3};
for문을 사용하여 Object의 속성을 반복 할 수 있습니다 .
var settings = extend(default, config);
function extend(a, b){
var c = {};
for(var p in a)
c[p] = (b[p] == null) ? a[p] : b[p];
return c;
}
이것은 jQuery 종속성을 제거하려고 시도하면서 내놓은 딥 카피를 사용한 약간 다른 접근 방식입니다. 대부분 작게 설계되었으므로 예상하는 모든 기능이 없을 수도 있습니다. ES5와 완전히 호환되어야합니다 ( Object.keys 사용으로 인해 IE9부터 시작 ) :
function extend(obj1, obj2) {
var keys = Object.keys(obj2);
for (var i = 0; i < keys.length; i += 1) {
var val = obj2[keys[i]];
obj1[keys[i]] = ['string', 'number', 'array', 'boolean'].indexOf(typeof val) === -1 ? extend(obj1[keys[i]] || {}, val) : val;
}
return obj1;
}
다섯 번째 줄이 정확히 무엇을하는지 궁금 할 것입니다. obj2.key가 객체 리터럴이면 (즉, 일반 유형이 아닌 경우) 우리는 그것에 대해 재귀 적으로 extend를 호출합니다. 해당 이름의 속성이 obj1에 아직 존재하지 않는 경우 먼저 빈 객체로 초기화합니다. 그렇지 않으면 단순히 obj1.key를 obj2.key로 설정합니다.
여기에서 작동하는 일반적인 사례를 증명해야하는 몇 가지 mocha / chai 테스트는 다음과 같습니다.
it('should extend a given flat object with another flat object', () => {
const obj1 = {
prop1: 'val1',
prop2: 42,
prop3: true,
prop4: 20.16,
};
const obj2 = {
prop4: 77.123,
propNew1: 'newVal1',
propNew2: 71,
};
assert.deepEqual(utils.extend(obj1, obj2), {
prop1: 'val1',
prop2: 42,
prop3: true,
prop4: 77.123,
propNew1: 'newVal1',
propNew2: 71,
});
});
it('should deep-extend a given flat object with a nested object', () => {
const obj1 = {
prop1: 'val1',
prop2: 'val2',
};
const obj2 = {
propNew1: 'newVal1',
propNew2: {
propNewDeep1: 'newDeepVal1',
propNewDeep2: 42,
propNewDeep3: true,
propNewDeep4: 20.16,
},
};
assert.deepEqual(utils.extend(obj1, obj2), {
prop1: 'val1',
prop2: 'val2',
propNew1: 'newVal1',
propNew2: {
propNewDeep1: 'newDeepVal1',
propNewDeep2: 42,
propNewDeep3: true,
propNewDeep4: 20.16,
},
});
});
it('should deep-extend a given nested object with another nested object and deep-overwrite members', () => {
const obj1 = {
prop1: 'val1',
prop2: {
propDeep1: 'deepVal1',
propDeep2: 42,
propDeep3: true,
propDeep4: {
propDeeper1: 'deeperVal1',
propDeeper2: 777,
propDeeper3: 'I will survive',
},
},
prop3: 'lone survivor',
};
const obj2 = {
prop1: 'newVal1',
prop2: {
propDeep1: 'newDeepVal1',
propDeep2: 84,
propDeep3: false,
propDeep4: {
propDeeper1: 'newDeeperVal1',
propDeeper2: 888,
},
},
};
assert.deepEqual(utils.extend(obj1, obj2), {
prop1: 'newVal1',
prop2: {
propDeep1: 'newDeepVal1',
propDeep2: 84,
propDeep3: false,
propDeep4: {
propDeeper1: 'newDeeperVal1',
propDeeper2: 888,
propDeeper3: 'I will survive',
},
},
prop3: 'lone survivor',
});
});
I'd be happy about feedback or comments on this implementation. Thanks in advance!
I prefer this code that uses my generic forEachIn, and does not mangle the first object:
function forEachIn(obj, fn) {
var index = 0;
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
fn(obj[key], key, index++);
}
}
}
function extend() {
var result = {};
for (var i = 0; i < arguments.length; i++) {
forEachIn(arguments[i],
function(obj, key) {
result[key] = obj;
});
}
return result;
}
If you really do want to merge stuff into the first object, you can do:
obj1 = extend(obj1, obj2);
It helps me a lot when I develop with pure javascript.
function extends(defaults, selfConfig){
selfConfig = JSON.parse(JSON.stringify(defaults));
for (var item in config) {
if (config.hasOwnProperty(item)) {
selfConfig[item] = config[item];
}
}
return selfConfig;
}
The approach of Ivan Kuckir's can also be adapted to create a new object prototype:
Object.prototype.extend = function(b){
for(var key in b)
if(b.hasOwnProperty(key))
this[key] = b[key];
return this;
}
var settings = default.extend(config);
참고URL : https://stackoverflow.com/questions/11197247/javascript-equivalent-of-jquerys-extend-method
'developer tip' 카테고리의 다른 글
| WPF에서 GridViewColumn 데이터를 자동 크기 조정하고 오른쪽 정렬하는 방법은 무엇입니까? (0) | 2020.09.24 |
|---|---|
| Xcode-모든 파일에서 텍스트 검색 (0) | 2020.09.24 |
| JavaScript \ HTML에서 소켓을 사용하는 방법? (0) | 2020.09.24 |
| 업로드하기 전에 파일 크기 가져 오기 (0) | 2020.09.24 |
| Chrome 개발자 도구를 사용하여 자바 스크립트 편집 (0) | 2020.09.24 |