自定义元素原型中的重写函数会更改 this 对象
Overriding function in prototype of custom element changes the this object
我制作了一个自定义元素 class,然后尝试在原型级别包装其中一个函数,以便每个实例都使用包装器。但是,当我这样做时, this
的值在函数内部发生了变化。如何更改原型函数并访问新函数内部的实例 this
?
在此示例中,每次我在 MyClass2
中记录 this
时,我希望它打印 <my-class-2></my-class-2>
,就像我在 [=19= 中记录 this
时一样] 它打印 <my-class></my-class>
.
class MyClass extends HTMLElement {
connectedCallback() {
console.log('Inside MyClass:')
console.log(this)
}
}
customElements.define('my-class', MyClass)
class MyClass2 extends HTMLElement {
connectedCallback() {
console.log('Inside MyClass2:')
console.log(this)
}
}
let connectedCallback = MyClass.prototype.connectedCallback
MyClass2.prototype.connectedCallback = () => {
console.log('Outside MyClass2')
console.log(this)
connectedCallback()
}
customElements.define('my-class-2', MyClass2)
<my-class></my-class>
<my-class-2></my-class-2>
控制台输出:
Inside MyClass:
<my-class></my-class>
Outside MyClass2
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: global, …}
Inside MyClass:
undefined
首先,当你重新定义connectedCallback()
方法时,你不能使用箭头函数,因为箭头函数调用不会设置[=16的值=] 到对象的引用。
这通常是一个优势,但在这里不是。而是使用经典的 function ()
表示法:
MyClass2.prototype.connectedCallback = function() {
console.log(this)
}
其次,当您编写 let connectedCallback = MyClass.prototype.connectedCallback
时,实际上您断开了引用函数与对象的连接。
因此,this
不会从调用它的地方引用对象,而是引用当前上下文 window
。
相反,您可以使用 bind()
在调用方法之前使用对象的值设置 this
:
MyClass2.prototype.connectedCallback = function() {
connectedCallback.bind(this)()
}
或者,您可以将函数定义为当前对象的方法。
MyClass2.prototype.connectedCallback_old = MyClass.prototype.connectedCallback
MyClass2.prototype.connectedCallback = function() {
this.connectedCallback_old()
}
class MyClass extends HTMLElement {
connectedCallback() {
console.log('Inside MyClass:')
console.log(this)
}
}
customElements.define('my-class', MyClass)
class MyClass2 extends HTMLElement {
connectedCallback() {
console.log('Inside MyClass2:')
console.log(this)
}
}
let connectedCallback = MyClass.prototype.connectedCallback
MyClass2.prototype.connectedCallback = function () {
console.log('Outside MyClass2')
console.log(this)
connectedCallback.bind(this)()
}
customElements.define('my-class-2', MyClass2)
<my-class></my-class>
<my-class-2></my-class-2>
我制作了一个自定义元素 class,然后尝试在原型级别包装其中一个函数,以便每个实例都使用包装器。但是,当我这样做时, this
的值在函数内部发生了变化。如何更改原型函数并访问新函数内部的实例 this
?
在此示例中,每次我在 MyClass2
中记录 this
时,我希望它打印 <my-class-2></my-class-2>
,就像我在 [=19= 中记录 this
时一样] 它打印 <my-class></my-class>
.
class MyClass extends HTMLElement {
connectedCallback() {
console.log('Inside MyClass:')
console.log(this)
}
}
customElements.define('my-class', MyClass)
class MyClass2 extends HTMLElement {
connectedCallback() {
console.log('Inside MyClass2:')
console.log(this)
}
}
let connectedCallback = MyClass.prototype.connectedCallback
MyClass2.prototype.connectedCallback = () => {
console.log('Outside MyClass2')
console.log(this)
connectedCallback()
}
customElements.define('my-class-2', MyClass2)
<my-class></my-class>
<my-class-2></my-class-2>
控制台输出:
Inside MyClass:
<my-class></my-class>
Outside MyClass2
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: global, …}
Inside MyClass:
undefined
首先,当你重新定义connectedCallback()
方法时,你不能使用箭头函数,因为箭头函数调用不会设置[=16的值=] 到对象的引用。
这通常是一个优势,但在这里不是。而是使用经典的 function ()
表示法:
MyClass2.prototype.connectedCallback = function() {
console.log(this)
}
其次,当您编写 let connectedCallback = MyClass.prototype.connectedCallback
时,实际上您断开了引用函数与对象的连接。
因此,this
不会从调用它的地方引用对象,而是引用当前上下文 window
。
相反,您可以使用 bind()
在调用方法之前使用对象的值设置 this
:
MyClass2.prototype.connectedCallback = function() {
connectedCallback.bind(this)()
}
或者,您可以将函数定义为当前对象的方法。
MyClass2.prototype.connectedCallback_old = MyClass.prototype.connectedCallback
MyClass2.prototype.connectedCallback = function() {
this.connectedCallback_old()
}
class MyClass extends HTMLElement {
connectedCallback() {
console.log('Inside MyClass:')
console.log(this)
}
}
customElements.define('my-class', MyClass)
class MyClass2 extends HTMLElement {
connectedCallback() {
console.log('Inside MyClass2:')
console.log(this)
}
}
let connectedCallback = MyClass.prototype.connectedCallback
MyClass2.prototype.connectedCallback = function () {
console.log('Outside MyClass2')
console.log(this)
connectedCallback.bind(this)()
}
customElements.define('my-class-2', MyClass2)
<my-class></my-class>
<my-class-2></my-class-2>