我正在做一个带有默认选项对象的小型JavaScript模块,它看起来像这样:
var myModule = function() {
// Define option defaults
var defaults = {
foo: 'bar',
fooObject: {
option1: [],
option2:true,
option3: false,
}
}
// Create options by extending defaults with the passed in arugments
if (arguments[0] && typeof arguments[0] === "object") {
this.options = extendDefaults(defaults, arguments[0]);
}
}
所以当我像那样打电话给我的模块时
var moduleInstance = new myModule({
foo: 'some value',
fooObject: {
option1: [1, 2, 3]
}
});
moduleInstance.options.foo; //will retrurn an array [1, 2, 3]
但是
moduleInstance.options.fooObject; //will only contain option1
我理解为什么在创建对象时没有定义option2和option3,但我无法解决如何解决这个问题。 我发现在另一个框架上使用jQuery的所有片段。
编辑:
抱歉,这里缺少extendDefault(),它是:
function extendDefaults(source, properties) {
var property;
for (property in properties) {
if (properties.hasOwnProperty(property)) {
source[property] = properties[property];
}
}
return source;
}
编辑:可以解决
我最终这样做了 http://jsfiddle.net/optionsit/sgmme5dy/
在检查hasOwnProperty
的循环中我把那个if语句
if(typeof properties[property] === 'object' && typeof properties[property].nodeType === 'undefined' )
所以我可以检查该值是否是一个对象而不是一个DOM元素(因为我也在顶级值中传递了一些DOM元素)
如果它是一个JavaScript对象,我会通过它的子进行迭代,看看它们是否在参数中设置并仅在它们被替换时替换它们。
它可能不是很漂亮,但它适用于我的用例,如果你有更好的选择,请随时评论我会接受更漂亮的答案。
感谢您的帮助
答案 0 :(得分:1)
您的代码替换了可能不是您的意图的整个fooObject
。根据您的要求,有多种方法可以解决这个问题。例如,你可以添加一个额外的方法,以防你想要"添加" fooObject
的新内容,而不是使用"构造函数"。
function extendDefaults(source, properties) {
var property;
for (property in properties) {
if (properties.hasOwnProperty(property)) {
source[property] = properties[property];
}
}
return source;
}
var myModule = function () {
// Define option defaults
var defaults = {
foo: 'bar',
fooObject: {
option1: [],
option2: true,
option3: false,
}
}
this.options = extendDefaults({}, defaults);
// Create options by extending defaults with the passed in arugments
if (arguments[0] && typeof arguments[0] === "object") {
this.options = extendDefaults(this.options, arguments[0]);
}
}
var moduleInstance = new myModule({
foo: 'some value',
});
moduleInstance.options.fooObject.option1 = [1, 2, 3];
console.log(moduleInstance.options.fooObject);
console.log(moduleInstance.options.foo);
答案 1 :(得分:1)
您只需递归调用extendDefaults
:
function extendDefaults(source, properties) {
var property;
for (property in properties) {
if (properties.hasOwnProperty(property)) {
if (typeof properties[property] === 'object' && typeof properties[property].nodeType === 'undefined') {
extendDefaults(source[property], properties[property]);
} else {
source[property] = properties[property];
}
}
}
return source;
}
这是一个更新的小提琴:http://jsfiddle.net/sgmme5dy/3/
请注意,此功能会在null
值和Date
属性中断,因为:typeof null === 'object'
和typeof new Date === 'object'
。
要处理这些,只需将其添加到if:
if (typeof properties[property] === 'object' && properties[property] !== null && !(properties[property] instanceof Date) && typeof properties[property].nodeType === 'undefined')
编辑:完全忘记了数组,它们也是object
的类型。最后,我认为最好只依靠现有的extend
个函数中的一个。例如,如果你使用jQuery,你可以使用$.extend,或者你使用lodash / underscorejs你可以使用_.assign。如果您不使用或不想使用任何这些库,那么还有一些小型独立库,如下所示:node-deep-extend