기본값이있는 옵션에 대한 자바 스크립트 디자인 패턴?
// opt_options is optional
function foo(a, b, opt_options) {
// opt_c, opt_d, and opt_e are read from 'opt_options', only c and d have defaults
var opt_c = 'default_for_c';
var opt_d = 'default_for_d';
var opt_e; // e has no default
if (opt_options) {
opt_c = opt_options.c || opt_c;
opt_d = opt_options.d || opt_d;
opt_e = opt_options.e;
}
}
위의 내용은 매우 장황 해 보입니다. 기본 매개 변수로 인수 옵션을 처리하는 더 좋은 방법은 무엇입니까?
이것은 jQuery.extend를 사용 하지만 선택한 라이브러리의 객체 병합 또는 ES6의 Object.assign과 교환 될 수 있습니다.
function Module(options){
var defaults = {
color: 'red',
};
var actual = $.extend({}, defaults, options || {});
console.info( actual.color );
}
var a = new Module();
// Red
var b = new Module( { color: 'blue' } );
// Blue
편집 : 이제 underscore
또는 lodash
!
function Module(options){
var actual = _.defaults(options || {}, {
color: 'red',
});
console.info( actual.color );
}
var a = new Module();
// Red
var b = new Module( { color: 'blue' } );
// Blue
Javascript ES6에서는 Object.assign 을 사용할 수 있습니다 .
function Module(options = {}){
let defaults = {
color: 'red',
};
let actual = Object.assign({}, defaults, options);
console.info( actual.color );
}
ES6 / ES2015에는 몇 가지 새로운 방법이 있습니다. 사용 Object.assign
:
options = Object.assign({}, defaults, options);
비 구조화 할당 사용 :
const { a = 1, b = 2 } = options;
비 구조화 함수 매개 변수를 사용할 수도 있습니다.
const ƒ = ({a = 1, b = 2, c = 3} = {}) => {
console.log({ a, b, c });
};
종속성이 없습니다!
추가 종속성없이 기본 옵션을 얻으려면 다음 패턴을 사용합니다.
var my_function = function (arg1, arg2, options) {
options = options || {};
options.opt_a = options.hasOwnProperty('opt_a') ? options.opt_a : 'default_opt_a';
options.opt_b = options.hasOwnProperty('opt_b') ? options.opt_b : 'default_opt_b';
options.opt_c = options.hasOwnProperty('opt_c') ? options.opt_c : 'default_opt_b';
// perform operation using options.opt_a, options.opt_b, etc.
};
약간 장황하지만 읽기, 옵션 추가 / 제거 및 기본값 추가가 쉽습니다. 옵션이 많을 때 약간 더 간결한 버전은 다음과 같습니다.
var my_function = function (arg1, arg2, options) {
var default_options = {
opt_a: 'default_opt_a',
opt_b: 'default_opt_b',
opt_c: 'default_opt_c'};
options = options || {};
for (var opt in default_options)
if (default_options.hasOwnProperty(opt) && !options.hasOwnProperty(opt))
options[opt] = default_options[opt];
// perform operation using options.opt_a, options.opt_b, etc.
};
그리고 더 컴팩트 한 jQuery 버전 :
function func(opts) {
opts = $.extend({
a: 1,
b: 2
}, opts);
console.log(opts);
}
func(); // Object {a: 1, b: 2}
func({b: 'new'}); // Object {a: 1, b: "new"}
여러 연속 함수에서이 작업을 수행해야하는 경우 프로세스를 표준화하고 속도를 높이는 방법은 다음과 같습니다.
function setOpts (standard, user) {
if (typeof user === 'object' {
for (var key in user) {
standard[key] = user[key];
}
}
}
그런 다음 다음과 같이 간단히 함수를 정의 할 수 있습니다.
var example = function (options) {
var opts = {
a: 1,
b: 2,
c:3
};
setOpts(opts, options);
}
이렇게하면 기본값을 포함하는 함수 내에 하나의 옵션 개체 만 정의됩니다.
프로토 타입 상속 을 피하기 위해 추가 검사를 하려면 첫 번째 함수는 다음과 같습니다.
function setOpts (standard, user) {
if (typeof user === 'object') {
Object.keys(user).forEach(function (key) {
standard[key] = user[key];
});
}
}
후자의 경우는 IE <9, Chrome <5, Firefox <4, Safari <5에서는 지원되지 않습니다.
마지막으로 ECMAScript 6 은이를 수행하는 가장 좋은 방법 인 기본 매개 변수를 제공 합니다.
브라우저에서 널리 지원 되려면 몇 달이 걸립니다.
Object.assign 은 옵션을 기본값과 병합하는 매우 직접적인 방법 이지만 몇 가지 단점이 있습니다.
삼항 연산자로 조건부 옵션을 설정하려면 값에 대해서도 기본값을 덮어 씁니다
undefined
.const options = { logging: isProduction ? 'none' : undefined }; const defaults = { logging: 'verbose' } Object.assign({}, defaults, options); // {logging: undefined} !
잘못된 옵션 이름을 제공하면 경고가 표시되지 않습니다.
const options = { loging: 'none' // typo }; const defaults = { logging: 'verbose' } Object.assign({}, defaults, options); // {logging: 'verbose', loging: 'none'} !
이러한 경우를 다루기 위해 저는 작은 플랫 옵션 패키지를 만들었습니다 . 값의
기본값을 덮어 쓰지 않습니다 undefined
.
const options = {
logging: isProduction ? 'none' : undefined
};
const defaults = {
logging: 'verbose'
}
flatOptions(options, defaults); // {logging: 'verbose'}
잘못된 옵션 이름에 대해 경고합니다.
const options = {
loging: 'none' // typo
};
const defaults = {
logging: 'verbose'
}
flatOptions(options, defaults); // throws "Unknown option: loging."
도움이 되었기를 바랍니다!
If you have access to ES6 with a stage 4 proposal (such as with Babel) you can accomplish this with spread and destructuring assignment.
const defaultPrintOptions = {
fontName: "times",
fontStyle: "normal",
fontSize: 10,
align: "left"
};
// Setting the null default isn't necessary but
// makes it clear that the parameter is optional.
// Could use {} but would create a new object
// each time the function is called.
function print(text, options = null) {
let {
fontName,
fontStyle,
fontSize,
align
} = {
...defaultPrintOptions,
...options
};
console.log(text, fontName, fontStyle, fontSize, align);
}
print("All defaults:");
print("Override some:", {
fontStyle: "italic",
align: "center"
});
print("Override all:", {
fontName: "courier",
fontStyle: "italic",
fontSize: 24,
align: "right"
});
This also works (but may create more objects):
function myFunction({
text = "",
line = 0,
truncate = 100
} = {}) {
console.log(text, line, truncate);
}
(latter example from David Walsh - @wprl's answer also mentions this)
var mergeOptions = function mergeOptions(userOptions) {
// Default options
var options = {
height: "100px",
width: "100px" ,
color: "blue"
}
if (userOptions) {
Object.keys(userOptions).forEach(function (key) {
options[key] = userOptions[key]
})
}
return options;
}
I think you're looking for something like this (sorry for the late reply):
function foo(a, b, options) {
this.defaults = {
x: 48,
y: 72,
z: 35
};
for (var i in this.defaults) {
if (options[i] != "undefined") { this.defaults[i] = options[i]; }
}
// more code...
}
edit: apologies, grabbed this from some old code... You should make sure to use the hasOwnProperty() method to make sure you don't iterate over everything on function.prototype
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
Now that I think about it, I kind of like this:
function foo(a, b, opt_options) {
// Force opt_options to be an object
opt_options = opt_options || {};
// opt_c, opt_d, and opt_e are read from 'opt_options', only c and d have defaults
var opt_c = 'default_for_c' || opt_options.c;
var opt_d = 'default_for_d' || opt_options.d;
var opt_e = opt_options.e; // e has no default
}
'Development Tip' 카테고리의 다른 글
Xcode 7의 기존 프로젝트에 단위 및 UI 테스트 추가 (0) | 2020.11.21 |
---|---|
java.util.ArrayList에 해당하는 Scala (0) | 2020.11.20 |
TSV 파일을 읽고 구문 분석 한 다음 CSV로 저장하기 위해 조작 (* 효율적으로 *) (0) | 2020.11.20 |
C #은 왜 케이스 뒤에 문을 허용하지만 그 전에는 허용하지 않습니까? (0) | 2020.11.20 |
EC2에서 인스턴스를 삭제하는 방법은 무엇입니까? (0) | 2020.11.20 |