Update: I can't answer the question, since it's locked, but I have my own solution to this problem at the bottom, working with 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: ƒ}
)
Is there a way to make this
or any variable return a reference to the base-object? document.body
in this case?
Я пробовал несколько вариантов, например
HTMLElement.prototype.MyNameSpace = (function() {
let that = this
let obj = Object.defineProperties({}, {GetThis: {
value: function() {
console.log(that)
},
enumerable: false}})
return obj;
})()
но это не удается по вполне понятным причинам. Функция запускается только один раз и возвращает ссылку на window
Я провел несколько экспериментов с .bind()
, но ни один из них не дал желаемого результата по предсказуемым причинам.
My Solution
Что мне не понравилось в ответе Джонаса, так это то, что он в основном такой же, как 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;
}
}