- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在寻找一个关于如何确定何时覆盖或扩展数组/集合的通用解决方案。
假设我们有这个对象:
let obj1 = {
rolo: 'bar',
yolo: true,
cholo: [1,2,3,4]
};
如果我打电话
let obj2 = Object.assign({}, obj1, {
cholo: [5]
});
我会得到这个:
obj2 => { rolo: 'bar', yolo: true, cholo: [ 5 ] }
但我要找的是:
obj2 => { rolo: 'bar', yolo: true, cholo: [ 1, 2, 3, 4, 5 ] }
允许扩展数组而不是覆盖的最佳模式是什么?我对在库代码的上下文中执行此操作特别感兴趣。用户可以在这里选择是扩展数组还是覆盖数组。
我知道没有简单或简单的模式可以用来做到这一点。
例如,我们可以这样做:
override: {
metadata:{
cholo: {
extend: true
}
},
value: {
cholo: [5]
}
}
添加一些元数据以配合新对象。然后我会有一些自定义函数,它不仅会调用 Object.assign,还会检查元数据属性,并手动复制属性。
像这样:
let copier = function(defaultObj, {value, metadata}){
let allKeysDupes = Object.keys(value).concat(Object.keys(defaultObj));
let allKeys = allKeysDupes.filter(i => allKeysDupes.indexOf(v === i));
let ret = {};
// manually go through all keys
// check metadata to determine whether to overwrite or extend arrays, etc.
allKeys.forEach(function(k){
if(metadata[k]{
// check the metadata and follow it's rules
}
else if(k in val){
ret[k] = val[k];
}
else {
ret[k] = defaultObj[k];
}
});
return ret;
}
最佳答案
以下是利用 ES6 Proxies 的通用解决方案(在 ECMAScript 2015 Language Specification (ES6) 中引入)对传递给它的任何普通对象执行可定制的深度合并和串联。此函数允许为遇到的每种类型的输入值轻松自定义合并过程,并且应该能够处理任何类型的输入值,只要它传递的对象通常与 Object.assign()
一起工作即可。 .
为了处理目的,轻松准确地识别输入值的类型非常重要。为此,函数利用 Object.prototype.toString
哪个(当针对任意值调用时)将返回一个类似于 [object String]
的字符串或 [object Object]
, 等。从那里我们可以去掉不必要的位,得到一个类似 String
的字符串。或 Object
等
const gettype = e => Object.prototype.toString.call(e).replace(/.*\b(\w+)./, '$1');
我们需要简化对不同数据类型的处理。您可以使用凌乱的、硬编码的 switch 语句,但我更喜欢更流畅的东西。我喜欢使用函数对象。对于我们要处理的每种类型,我们只需定义一个与 gettype
的输出直接匹配的属性名称。上面定义的函数。然后在需要的时候,我们可以根据对应的类型值查找那个函数。
在这个例子中,我创建了一组默认的处理程序,然后由函数的第一个参数中提供的处理程序覆盖。
Object.assign(h, {
"Array": (a, b) => [...a, ...b],
"Object": (a, b) => deepmerge(h, a, b),
"Set": (a, b) => new Set([...a, ...b]),
"Map": (a, b) => {
const o = new Map([...a]);
for(let [k,v] of [...b]) {
const vt = gettype(v);
o.set(k, a.has(k) && vt in h ? h[vt](a.get(k), v) : v);
}
return o;
}
}, h);
现在我们将进入代理部分。首先定义一个“out”对象。该对象是该函数最终将返回的对象,并将作为代理的目标。
const o = {};
接下来使用设置的陷阱为“out”对象创建一个代理。当设置操作发生时,设置陷阱将原始值和新值传递给适当的设置处理程序。如果没有合适的设置处理程序,它会用新值覆盖旧值。确定的值应用于“out”对象。
const p = new Proxy(o, {
set: (o, k, b) => {
const a = o[k];
const at = gettype(a);
return (o[k] = (at in h && k in o ? h[at](a, b) : b), true);
}
});
下次使用Object.assign
将对象合并到代理中,这会触发上面为每个设置操作定义的设置陷阱。
Object.assign(p, ...args);
最后返回“out”对象。
return o;
const deepmerge = (h, ...args) => {
const gettype = e => Object.prototype.toString.call(e).replace(/.*\b(\w+)./, '$1');
const o = {};
Object.assign(h, {
"Array": (a, b) => [...a, ...b],
"Object": (a, b) => deepmerge(h, a, b),
"Set": (a, b) => new Set([...a, ...b]),
"Map": (a, b) => {
const o = new Map([...a]);
for(let [k,v] of [...b]) {
const vt = gettype(v);
o.set(k, a.has(k) && vt in h ? h[vt](a.get(k), v) : v);
}
return o;
}
}, h);
const p = new Proxy(o, {
set: (o, k, b) => {
const a = o[k];
const at = gettype(a);
return (o[k] = (at in h && k in o ? h[at](a, b) : b), true);
}
});
Object.assign(p, ...args);
return o;
};
deepmerge(handlers, ...sources)
处理程序对象。处理程序对象可用于覆盖给定类型的默认处理程序,或为默认情况下未处理的类型提供处理程序。
示例:
{
"String": (a, b) => a + b,
"Number": (a, b) => a + b,
}
以下片段显示了两个示例:
const objects = [
{
string: "hello",
number: 1,
boolean: true,
array: [1,2,3],
object: { a: 1, b: 2 },
map: new Map([[1,2],[2,3],[4,2],[undefined, undefined],[null, null]]),
set: new Set([1,2,3]),
null: null,
undefined: undefined
},
{
string: " world",
number: 2,
boolean: false,
array: [4,5,6],
object: { a: 2, b: 1 },
map: new Map([[1,1],[2,0],[3,1],[undefined, null],[null, undefined]]),
set: new Set([4,5,6]),
null: undefined,
undefined: null
}
];
console.log(deepmerge({}, ...objects));
console.log(deepmerge({
"String": (a, b) => a + b,
"Number": (a, b) => a + b,
}, ...objects));
<script src="https://cdn.rawgit.com/Tiny-Giant/43cc03adf3cdc84ff935655cbebbe585/raw/754070ca8858efeff5a2c3b8bad6475842565798/deepmerge.js"></script><link rel="stylesheet" href="https://cdn.rawgit.com/Tiny-Giant/f2a53f469863baadf1b4ad48a4b4ea39/raw/b0ede74f374199abe9324334d1c0ef088a850415/deepmerge.css" type="text/css">
关于javascript - 使用 Object.assign 或类似的扩展数组而不是覆盖数组的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44739990/
在嵌入式系统的背景下,给出以下函数结构: 返回变量的条件赋值: int foo(int x) { int status; if (is_valid(x)) {
#input |--IDs-|--Value-| |--da1-|--100---| |--da2-|---80---| |--da3-|--200---| |--da4-|--300---| |--
您可以declare a list of variables and assign them some value在 Perl 6 my ($a, $b) = 33,44 # $a will be 3
在下面的代码中实现对象的浅拷贝,但是不同的输出让我很困惑: 对象.分配: var obj = { name: 'wsscat', age: 0, add: { a: 'beijin
我正在查看一位已不复存在的开发人员的一些旧代码,并注意到有时他使用 Object.assign({}, xyz) 还有他用过的其他东西 Object.assign([], abc); 两者有区别吗?
这个问题在这里已经有了答案: Why were ES5 Object methods not added to Object.prototype? (2 个答案) 关闭 4 个月前。 我正在做一个
我想知道这之间的区别: Object.assign(otherObject, { someNewProperty: '' }); 和 otherObject.someNewProperty = '
考虑以下代码: const defaultState = () => { return { profile: { id: '', displayName: '',
我刚刚偶然发现this line of TS code : const { title = item.text } = item; 这似乎是一个destructuring assigment但是大括号
我是一个没有经验的 JavaScript 用户,正在阅读这本书 CoffeeScript: Accelerated JavaScript Development ,其中作者制作了一种 Scrabble
当我查看日志文件时 D:\SAS\XXX\Lev1\SASMain\BatchServer\Logs 我看到了这两行 NOTE: Libref TESTLIB successfully assigne
我似乎不明白为什么要使用移动赋值运算符: CLASSA & operator=(CLASSA && other); //move assignment operator 结束了,复制赋值运算符: CL
在Eiffel Studio中,我一直试图访问从另一个类定义的一个类的对象的字段。但是,它不断给出我无法理解和解决的错误。以下是示例代码片段: 创建对象的类: class TEST1 feat
为什么这个片段在 Node (10.5) .then(function() { this = {...this, ...payload}; this.update();
我在我的 React 应用程序中使用以下包来生成 Recaptcha 组件:https://github.com/appleboy/react-recaptcha 组件如下所示,带有 eslint 警
我有以下代码: #include #include using std::cout; struct SomeType { SomeType() {} SomeType(const Some
我有这个代码示例: var a = 10; ({a}) = 0; 在 Google Chrome 中,它显示错误:SyntaxError:无效的解构赋值目标 在 Firefox 中,它显示错误:Ref
我有一个函数,用于对两个输入字段的输入求和并将其分配给一个。我的函数如下所示: function sum(id) { nextId = id+2 console.log
我收到这个警告 "Automatic Reference Counting Issue: Assigning retained object to unsafe_unretained variable
在使用 Shopify 的 Liquid 语言编码时,我注意到使用以下语法分配了一些变量: {%- assign variable = value -%} 和使用以下语法分配的其他变量: {% ass
我是一名优秀的程序员,十分优秀!