javascript _.assign 仅当目标对象中存在属性时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28104798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
_.assign only if property exists in target object
提问by sparty02
My need is to do something like an _.assign, but only if the target object already has the property being assigned. Think of it like the source objects may have some properties to contribute, but also some properties that I don't want to mix in.
我需要做类似 _.assign 的事情,但前提是目标对象已经分配了属性。把它想象成源对象可能有一些属性可以贡献,但也有一些我不想混入的属性。
I haven't ever used _.assign's callback mechanism, but tried the following. It 'worked', but it still assigned the property to the dest object (as undefined). I don't want it to assign at all.
我从未使用过 _.assign 的回调机制,但尝试了以下方法。它“有效”,但它仍然将该属性分配给 dest 对象(未定义)。我根本不希望它分配。
_.assign(options, defaults, initial, function (destVal, sourceVal) {
return typeof destVal == 'undefined' ? undefined : sourceVal;
});
I wrote the following function to do this, but wondering if lodash already has something baked in that is more elegant.
我写了下面的函数来做到这一点,但想知道 lodash 是否已经有一些更优雅的东西。
function softMerge (dest, source) {
return Object.keys(dest).reduce(function (dest, key) {
var sourceVal = source[key];
if (!_.isUndefined(sourceVal)) {
dest[key] = sourceVal;
}
return dest;
}, dest);
}
回答by ne8il
You could take just the keys from the first object
你可以只从第一个对象中取出钥匙
var firstKeys = _.keys(options);
Then take a subset object from the second object, taking only those keys which exist on the first object :
然后从第二个对象中获取一个子集对象,只获取第一个对象上存在的那些键:
var newDefaults = _.pick(defaults, firstKeys);
Then use that new object as your argument to _.assign
:
然后使用该新对象作为您的参数_.assign
:
_.assign(options, newDefaults);
Or in one line :
或者在一行中:
_.assign(options, _.pick(defaults, _.keys(options)));
Seemed to work when I tested it here : http://jsbin.com/yiyerosabi/1/edit?js,console
我在这里测试时似乎有效:http: //jsbin.com/yiyerosabi/1/edit?js,console
回答by Ciantic
Here is a immutable deep version, I call it "merge that retains the shape", in TypeScript that uses lodash:
这是一个不可变的深度版本,我称之为“保留形状的合并”,在使用 lodash 的 TypeScript 中:
function _mergeKeepShapeArray(dest: Array<any>, source: Array<any>) {
if (source.length != dest.length) {
return dest;
}
let ret = [];
dest.forEach((v, i) => {
ret[i] = _mergeKeepShape(v, source[i]);
});
return ret;
}
function _mergeKeepShapeObject(dest: Object, source: Object) {
let ret = {};
Object.keys(dest).forEach((key) => {
let sourceValue = source[key];
if (typeof sourceValue !== "undefined") {
ret[key] = _mergeKeepShape(dest[key], sourceValue);
} else {
ret[key] = dest[key];
}
});
return ret;
}
function _mergeKeepShape(dest, source) {
// else if order matters here, because _.isObject is true for arrays also
if (_.isArray(dest)) {
if (!_.isArray(source)) {
return dest;
}
return _mergeKeepShapeArray(dest, source);
} else if (_.isObject(dest)) {
if (!_.isObject(source)) {
return dest;
}
return _mergeKeepShapeObject(dest, source);
} else {
return source;
}
}
/**
* Immutable merge that retains the shape of the `existingValue`
*/
export const mergeKeepShape = <T>(existingValue: T, extendingValue): T => {
return _mergeKeepShape(existingValue, extendingValue);
}
And a simple test to see how I vision such merge should work:
还有一个简单的测试,看看我认为这种合并应该如何工作:
let newObject = mergeKeepShape(
{
a : 5,
// b is not here
c : 33,
d : {
e : 5,
// f is not here
g : [1,1,1],
h : [2,2,2],
i : [4,4,4],
}
},
{
a : 123,
b : 444,
// c is not here
d : {
e : 321,
f : 432,
// g is not here
h : [3,3,3],
i : [1,2],
}
}
);
expect(newObject).toEqual({
a : 123,
// b is not here
c : 33,
d : {
e : 321,
// f is not here,
g : [1,1,1],
h : [3,3,3],
i : [4,4,4]
}
});
I used seamless-immutable myself in the test, but didn't see a need to put it in this answer.
我在测试中自己使用了无缝不可变,但认为没有必要将它放在这个答案中。
I hereby place this in the Public Domain.
我在此将其置于公共领域。
回答by svarog
Another way to accomplish this is by combining _.mapObject
with _.has
实现此目的的另一种方法是结合_.mapObject
使用_.has
_.mapObject(object1, function(v, k) {
return _.has(object2, k) ? object2[k] : v;
});
Explanation:
解释:
- Traverse all key/value pairs of
object1
using_.mapObject
- Using
_.has
, check if property namek
also exists inobject2
. - If it does, copy the value assigned to key
object2
'sk
back toobject1
, else, just return the existing value of object1 (v
).
- 遍历
object1
using 的所有键/值对_.mapObject
- 使用
_.has
,检查属性名称是否k
也存在于object2
. - 如果是这样,复制分配给按键值
object2
的k
回object1
,否则,只是返回的object1现有的值(v
)。