Javascript 在CustomElement中对self(this)的引用
我用它在JavaScript中实现了一个自定义元素。但是,Javascript 在CustomElement中对self(this)的引用,javascript,custom-element,Javascript,Custom Element,我用它在JavaScript中实现了一个自定义元素。但是,self变量在我的方法中引用窗口,除非我首先调用const self=this 有人能向我解释一下为什么会这样,并建议一种更好的方法来访问方法中的自定义元素实例吗 class DocumentPreview extends HTMLElement { constructor(self, documents) { self = super(self); self.documents = documents || [];
self
变量在我的方法中引用窗口
,除非我首先调用const self=this
有人能向我解释一下为什么会这样,并建议一种更好的方法来访问方法中的自定义元素实例吗
class DocumentPreview extends HTMLElement {
constructor(self, documents) {
self = super(self);
self.documents = documents || [];
self.innerHTML = Handlebars.templates['document_preview']();
}
connectedCallback() {
// if I don't do this first ...
const self = this; // <<----------------------------------
console.log("connected now");
document.addEventListener('mqttsub', function(event) {
// ... onMessage is undefined here:
self.onMessage(event.detail);
});
}
disconnectedCallback() {
console.log("disconnected");
}
onMessage(message) {
// Same story ...
const self = this; // <<----------------------------------
Promise.resolve(true)
.then(json("/documents/"))
.then(ds => ds
.filter(x => x.name==message.payload)
.reduce((x, y) => y, undefined)
)
.then(d => json(sprintf("/document/%d/", d.id))())
// ... here:
.then(d => self.renderDocuments(d))
.catch(console.log);
}
renderDocuments(d) {
console.log('render', d);
}
}
class DocumentPreview扩展了HtmleElement{
建造商(自身、文件){
self=超级(self);
self.documents=文档| |[];
self.innerHTML=handlebar.templates['document_preview']();
}
connectedCallback(){
//如果我不先这么做。。。
const self=this;//json(sprintf(“/document/%d/”,d.id))())
//……这里:
。然后(d=>self.renderDocuments(d))
.catch(console.log);
}
渲染文档(d){
console.log('render',d);
}
}
在JavaScript中,这个
关键字指的是当前函数的上下文
document.addEventListener('mqttsub', function(event) {
// this here corresponds to your function(event) {...} context
this.onMessage(event.detail); // Will fail
});
解决这个问题的一个简单方法是使用箭头函数。默认情况下,箭头函数使用外部上下文
document.addEventListener('mqttsub', (event) => {
// this here corresponds to the outer context = your class
this.onMessage(event.detail);
});
否则,还可以绑定上下文
document.addEventListener('mqttsub', (function(event) {
this.onMessage(event.detail);
}).bind(this)); // Set the function context to be the class context
在JavaScript中,
这个
关键字表示当前函数的上下文
document.addEventListener('mqttsub', function(event) {
// this here corresponds to your function(event) {...} context
this.onMessage(event.detail); // Will fail
});
解决这个问题的一个简单方法是使用箭头函数。默认情况下,箭头函数使用外部上下文
document.addEventListener('mqttsub', (event) => {
// this here corresponds to the outer context = your class
this.onMessage(event.detail);
});
否则,还可以绑定上下文
document.addEventListener('mqttsub', (function(event) {
this.onMessage(event.detail);
}).bind(this)); // Set the function context to be the class context
尝试使用
bind()
在构造函数中绑定方法onMessage()
和renderDocuments()
,如this.methodName=this.methodName.bind(this)
。有了它,您可以通过this
访问属性和方法
class DocumentPreview extends HTMLElement {
constructor(documents) {
super();
this.documents = documents || [];
this.innerHTML = Handlebars.templates['document_preview']();
this.onMessage = this.onMessage.bind(this);
this.renderDocuments = this.renderDocuments.bind(this);
}
connectedCallback() {
document.addEventListener('mqttsub', this.onMessage);
}
disconnectedCallback() {
console.log("disconnected");
}
onMessage(event) {
const { detail: message } = event;
Promise.resolve(true)
.then(json("/documents/"))
.then(ds => ds
.filter(x => x.name==message.payload)
.reduce((x, y) => y, undefined)
)
.then(d => json(sprintf("/document/%d/", d.id))())
// ... here:
.then(d => this.renderDocuments(d))
.catch(console.log);
}
renderDocuments(d) {
console.log('render', d);
}
}
希望这有帮助 尝试使用
bind()
在构造函数中使用this.methodName=this.methodName.bind(this)
绑定方法onMessage()
和renderDocuments()
。有了它,您可以通过this
访问属性和方法
class DocumentPreview extends HTMLElement {
constructor(documents) {
super();
this.documents = documents || [];
this.innerHTML = Handlebars.templates['document_preview']();
this.onMessage = this.onMessage.bind(this);
this.renderDocuments = this.renderDocuments.bind(this);
}
connectedCallback() {
document.addEventListener('mqttsub', this.onMessage);
}
disconnectedCallback() {
console.log("disconnected");
}
onMessage(event) {
const { detail: message } = event;
Promise.resolve(true)
.then(json("/documents/"))
.then(ds => ds
.filter(x => x.name==message.payload)
.reduce((x, y) => y, undefined)
)
.then(d => json(sprintf("/document/%d/", d.id))())
// ... here:
.then(d => this.renderDocuments(d))
.catch(console.log);
}
renderDocuments(d) {
console.log('render', d);
}
}
希望这有帮助 构造函数中的
self
参数不能被其他方法访问,这是一个基本的范围问题。如果使用的是onMessage()
中的箭头函数,则不需要self
变量,只需直接使用this
。对于事件侦听器回调中的非箭头函数,您可以执行所显示的操作,也可以使用。将(this)
与该回调绑定,然后将this
而不是回调中的self
。构造函数中的self
参数不能被其他方法访问,这是一个基本的范围问题。如果使用的是onMessage()
中的箭头函数,则不需要self
变量,只需直接使用this
。对于事件侦听器回调中的非箭头函数,您可以执行所显示的操作,也可以使用。将(this)
与该回调绑定,然后在回调中使用this
而不是self
。非常好,最重要的是,它显著提高了可读性。快速一:在JS:const{detail:message}=event中,这个构造被称为什么
这种模式匹配是否有一个特定的名称?OP的问题围绕在一个基本的层次上,不必将这个
分配给每个方法内部的变量。bind()
方法应该通过确保类方法绑定到所需的范围来帮助实现这一点@沖原ハーベスト 这在ES6中称为可用。在本例中,它使用键detail
解压变量,并为其分配消息的别名/名称。谢谢非常感谢@nnnnnn你完全正确,完全错过了。谢谢你指出这一点,我将更新它,改为调用this.renderDocuments(d)
。谢谢很好,最重要的是它显著提高了可读性。快速一:在JS:const{detail:message}=event中,这个构造被称为什么
这种模式匹配是否有一个特定的名称?OP的问题围绕在一个基本的层次上,不必将这个
分配给每个方法内部的变量。bind()
方法应该通过确保类方法绑定到所需的范围来帮助实现这一点@沖原ハーベスト 这在ES6中称为可用。在本例中,它使用键detail
解压变量,并为其分配消息的别名/名称。谢谢非常感谢@nnnnnn你完全正确,完全错过了。谢谢你指出这一点,我将更新它,改为调用this.renderDocuments(d)
。谢谢