我确信我正在尝试做的事情有一个名称,并且我确信以前有人问过这个问题,但我正在努力寻找现有的答案 - 可能是因为我没有在寻找正确的术语。我有一个 JavaScript 函数被调用extend(),它类似于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;
}
Run Code Online (Sandbox Code Playgroud)
如果我调用它 using extend(target, defaults)which 将合并defaultsinto的内容target而不覆盖任何现有的键,这很好用target(除非它们是对象,然后它们被合并)。
我正在寻找一种方法来实际调用它 using target.extend(defaults),因此第一个target参数extend实际上隐含为this. 我试图通过更换重写功能target有this,但它不具有所期望的结果(我想我已经改变了递归的方法是错误的)。
target.extend = function() {
...
this[j] = this.extend(this[j], arguments[i][j]);
...
return this;
};
Run Code Online (Sandbox Code Playgroud)
任何指针(或对现有答案的引用)将不胜感激。
您可以分配函数以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);Run Code Online (Sandbox Code Playgroud)
或者,清理一堆代码:
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);Run Code Online (Sandbox Code Playgroud)
但这是一个坏主意,因为它会导致名称冲突和混淆代码。如果有一个像
const obj = { extend: true };
Run Code Online (Sandbox Code Playgroud)
那obj.extend做什么呢?(它会引用自己的属性,但这不是脚本编写者应该担心的事情。最好有一个独立的功能。)
这与为什么许多 Object 辅助方法存在于Object 构造函数中而不是Object.prototype. 例如,您调用Object.assign, or Object.defineProperty, not obj.assign or obj.defineProperty。
如果您只想在某些对象上使用此功能,则可以通过调用Object.defineProperty这些对象来避免原型污染:
const obj = { extend: true };
Run Code Online (Sandbox Code Playgroud)
或者,如果你有创建对象,其中在控制,您可以使用Object.create,这样extend是从原型继承的方法:
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);Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
63 次 |
| 最近记录: |