tl;博士的工作代码在底部,可以让它更优雅。
我正在构建一个金属匠 (静态站点生成器)插件。金属匠插件总是采用如下形式:
const myPlugin = options => (files, metalsmith, done) => {
// Mutate `files` or `metalsmith` in place.
done()
}我已经用函数式(不变)风格(用Ramda.js)写了我的插件,并且希望用新的值完全覆盖files。从概念上讲,下面是我想要的,但是不能工作,因为它将files重新分配到updated,而不是在堆上操作files对象。
const myPlugin = options => (files, metalsmith, done) => {
const updated = { foo: "foo" }
files = updated
done()
}我已经实现了所需的功能,有以下功能,但它似乎不雅。
const myPlugin = options => (files, metalsmith, done) => {
const updated = { foo: "foo" }
deleteMissingKeys(old, updated)
Object.assign(old, updated)
done()
}
const deleteMissingKeys = (old, updated) => {
Object.keys(old).forEach(key => {
if (!updated.hasOwnProperty(key)) {
delete old[key]
}
})
}是否有更好的方法来达到这些目的?
发布于 2018-03-24 14:20:08
在JavaScript中没有一种非常优雅的方法可以做到这一点,但这并不是件坏事。事实上,写得很好的JavaScript不应该需要这样的行为。在JavaScript中没有“通过引用传递”这样的东西,所以像您这样的尝试是不优雅的是很自然的。
库是否需要这样的行为,而不是试图通过引用传递"hack“,而是有一种更"javascriptonic”的方法来实现它,即在所需对象的包装对象周围传递:
// instead of trying to use a "hack" to pass-by-reference
var myObj = { /* ... */ };
function myFunc(obj) {
// your hack here to modify obj, since
// obj = { /* ... */ }
// won't work, of course
}
myFunc(myObj);
// you should use a wrapper object
var myWrapper = {
myObj: { /* ... */ }
}
function myFunc(wrapper) {
wrapper.myObj = { /* ... */ };
}
myFunc(myWrapper);我强烈建议你重新考虑为什么你一开始就想这么做。
但是如果您坚持,您的解决方案并没有那么糟糕,我喜欢您如何使用Object.assign()而不是笨拙的for循环来添加字段。
不过,我应该补充一点,根据情况的不同,您还可能希望将对象的原型设置为预期的值(例如,如果旧的对象是一个instanceof,并且希望使它成为一个普通的对象,那么当然需要调用Object.setPrototypeOf(old, Object.prototype))。
https://stackoverflow.com/questions/49464953
复制相似问题