【发布时间】:2021-07-13 17:15:10
【问题描述】:
更新:我无法回答这个问题,因为它已被锁定,但我在底部有自己的解决方案,与 Jonas' answer 合作
假设我在原型中添加了这个。我将以 HTMLElement 为例。
HTMLElement.prototype.MyNamespaceGetThis = function() {
return this;
}
document.body.MyNamespaceGetThis() 将返回 document.body
但是如果我想将它嵌套在一个对象中
HTMLElement.prototype.MyNamespace = {};
HTMLElement.prototype.MyNamespace.GetThis = function() {
return this;
}
document.body.MyNameSpace.GetThis() 将返回document.body 的MyNameSpace ({GetThis: ƒ})
有没有办法让this 或任何变量返回对基础对象的引用? document.body 在这种情况下?
我尝试了一些变体,例如
HTMLElement.prototype.MyNameSpace = (function() {
let that = this
let obj = Object.defineProperties({}, {GetThis: {
value: function() {
console.log(that)
},
enumerable: false}})
return obj;
})()
但由于完全可以理解的原因,这失败了。该函数只运行一次并返回对window的引用
我已经用.bind() 进行了一些实验,但由于可以预见的原因,没有一个能返回预期的结果。
我的解决方案
我不喜欢 Jonas 的回答,它与 MyNamespace().method 基本相同,MyNamespace 返回一组方法。
持久成员也是不可能的。如果我想存储成员数据,我需要一个单独的对象来执行此操作,我不喜欢那样。
我的解决方案是使用class,然后以一种特殊的内存轻量方式调用它。
class MyNamespace {
constructor(parent) {
this.parent = parent;
}
GetThis() {
return this.parent;
}
}
然后,对于本示例,您可以像这样将其添加到 HTMLElement 原型中
Object.defineProperties(HTMLElement.prototype, {
MyNamespace: {
enumerable: false, writeable: true,
get: function() {
let ret = new MyNamespace(this);
Object.defineProperty(this, 'MyNamespace', {
enumerable: false,
writeable: false, // note about this
value: ret
});
return ret;
},
enumerable: false, writeable: false
},
})
第一次调用document.body.MyNamespace.GetThis() 将返回类MyNamespace 的新实例,然后从中调用GetThis()。它还将更改document.body 的MyNamespace 以直接引用创建的实例,而不是每次都创建一个新实例。这意味着持久数据。
我喜欢这个的另一点是,每个元素都没有携带完整的 MyNamespace 实例,除非它在文档的生命周期中被调用。
引用更新后,我将其设置为冻结它以使其不能被覆盖,但很容易想象一个人可能需要destroy 方法的地方。您可以将 writable 更改为 true 之类的。
class MyNamespace {
constructor(parent) {
this.parent = parent;
}
GetThis() {
return this.parent;
}
destroy() {
Object.defineProperties(HTMLElement.prototype, {
MyNamespace: {
enumerable: false, writeable: true,
get: MyNamespace.factory(this, true),
enumerable: false, writeable: false
},
})
}
renew() {
this.parent.MyNamespace = MyNamespace.factory(this.parent, true)
// HTMLElement.prototype.MyNamespace can also be set
// to MyNamespace.factory(this)
}
static factory(parent, writeable) {
return Object.defineProperty(parent, 'MyNamespace', {
enumerable: false, writeable: writeable,
value: new MyNamespace(parent)
}).MyNamespace;
}
}
【问题讨论】:
标签: javascript prototype-programming