gpt4 book ai didi

JavaScript 函数作用于自身以用另一个对象扩展自身

转载 作者:行者123 更新时间:2023-11-28 12:11:49 26 4
gpt4 key购买 nike

我确信我正在尝试做的事情有一个名称,并且我确信以前已经有人问过这个问题,但我正在努力寻找现有的答案 - 可能是因为我没有寻找正确的术语。我有一个名为 extend() 的 JavaScript 函数,它类似于 Object.assign() 将对象合并在一起 - 我无权访问 Object.assign 在我当前的实现中。

function extend(target) {
for (var i = 1; i < arguments.length; ++i) {
if (typeof arguments[i] !== 'object') {
continue;
}
for (var j in arguments[i]) {
if (arguments[i].hasOwnProperty(j)) {
if (typeof arguments[i][j] === 'object') {
target[j] = extend({}, target[j], arguments[i][j]);
}
else if (!target.hasOwnProperty(j)) {
target[j] = arguments[i][j];
}
}
}
}
return target;
}

如果我使用 extend(target, defaults) 调用它,效果很好,它会将 defaults 的内容合并到 target 中,而不覆盖任何内容target 中的现有键(除非它们是对象,然后将它们合并)。

我正在寻找一种使用 target.extend(defaults) 实际调用它的方法,因此 extend 的第一个 target 参数是实际上隐含为 this。我尝试通过将 target 替换为 this 来重写该函数,但它没有达到预期的结果(我认为我更改递归的方式是错误的)。

target.extend = function() {
...
this[j] = this.extend(this[j], arguments[i][j]);
...
return this;
};

任何指示(或对现有答案的引用)将不胜感激。

最佳答案

您可以将该函数分配给Object.prototype来实现您正在寻找的功能:

Object.defineProperty(
Object.prototype,
'extend',
{
enumerable: false,
value: function() {
const target = this;
for (var i = 0; i < arguments.length; ++i) {
if (typeof arguments[i] !== 'object') {
continue;
}
for (var j in arguments[i]) {
if (arguments[i].hasOwnProperty(j)) {
if (typeof arguments[i][j] === 'object') {
target[j] = extend({}, target[j], arguments[i][j]);
}
else if (!target.hasOwnProperty(j)) {
target[j] = arguments[i][j];
}
}
}
}
return target;
}
}
);


const obj = { foo: 'foo' };
obj.extend({ bar: 'bar' });
console.log(obj);

或者,清理一堆代码:

Object.defineProperty(
Object.prototype,
'extend',
{
enumerable: false,
value: function(...args) {
const target = this;
for (const arg of args) {
for (const [key, val] of Object.entries(arg)) {
if (typeof val === 'object') extend(target[key], val);
else target[key] = val;
}
}
}
}
);


const obj = { foo: 'foo' };
obj.extend({ bar: 'bar' });
console.log(obj);

但是这是一个坏主意,因为它可能导致名称冲突和困惑的代码。如果有一个像这样的对象怎么办?

const obj = { extend: true };

那么obj.extend会做什么呢? (它会引用自己的属性,但这不是脚本编写者应该担心的事情。最好有一个独立的函数。)

这与许多对象辅助方法存在于 Object 构造函数 上而不是 Object.prototype 上的原因完全相同。例如,您调用 Object.assignObject.defineProperty不是 obj.assign obj.defineProperty.

如果您只想在某些对象上使用此功能,则可以通过在这些对象上调用 Object.defineProperty 来避免原型(prototype)污染:

const addExtend = obj => {
Object.defineProperty(
obj,
'extend',
{
enumerable: false,
value: function(...args) {
const target = this;
for (const arg of args) {
for (const [key, val] of Object.entries(arg)) {
if (typeof val === 'object') extend(target[key], val);
else target[key] = val;
}
}
}
}
);
};

const obj = { foo: 'foo' };
addExtend(obj);
obj.extend({ bar: 'bar' });
console.log(obj);

或者,如果您可以控制创建对象的位置,则可以使用 Object.create ,以便 extend 是从原型(prototype)继承的方法:

const objExtendProto = {};
Object.defineProperty(
objExtendProto,
'extend',
{
enumerable: false,
value: function(...args) {
const target = this;
for (const arg of args) {
for (const [key, val] of Object.entries(arg)) {
if (typeof val === 'object') extend(target[key], val);
else target[key] = val;
}
}
}
}
);

const obj = Object.create(objExtendProto);
obj.foo = 'foo';
obj.extend({ bar: 'bar' });
console.log(obj);

关于JavaScript 函数作用于自身以用另一个对象扩展自身,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60562506/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com