使用自定义逻辑将 HTMLVideoElement 上的 属性 覆盖为 getter/setter
Overwriting a property on a HTMLVideoElement to a getter/setter with custom logic
我想完成的事情:
我正在尝试为 chrome 编写一个扩展,为 Youtube 添加一些额外的功能。这个特殊问题与了解用户何时更改播放速率有关(这可以通过单击设置图标,然后单击速度来完成)。
我尝试过的事情:
我尝试通过将 HTMLVideoElement 上的 "playbackRate" 属性 替换为 getter/setter 对象来实现此目的,以便我可以检测何时发生这种情况。
问题:
当用户更改它时,我的所有逻辑都会运行,但是视频将不再真正改变速度。
代码:
let videoObj = document.getElementsByTagName('video')[0];
let storePlaybackRate = videoObj.playbackRate;
Object.defineProperty(videoObj,'playbackRate',{
get(){return storePlaybackRate;},
set(val){
storePlaybackRate = val;
console.log("Updated Value: ",val);
//Custom Logic that does work.
return val;
}
});
要对此进行测试,只需将代码粘贴到任何 YouTube 视频的控制台中,然后更改播放速度。 console.log 发生了,但视频不再改变速度。
我已经检查过的东西
1.That 这个 属性 还不是我要覆盖的 getter/setter 对象。这是通过以下方式检查的:
Object.getOwnPropertyDescriptor(videoObj, 'playbackRate');
2.I 以为可能是因为我没有在 setter 中返回新值,但事实并非如此。
最终总结
我知道还有其他方法可以做我想做的事情,所以如果通过这种方法无法做到,那也没关系。但我真的很想了解为什么这行不通。或者如果我犯了一个错误。
谢谢。
您正在覆盖继承的 getter/setter。
HTMLVideoElement 没有自己的 getter/setter playbackRate,而是从 HTMLMediaElement.prototype 继承了一个。这就是为什么 Object.getOwnPropertyDescriptor(video,'playbackRate')
returns undefined
要覆盖它,您必须存储原始描述符,并在您自己的描述符中调用它们。
originalDescriptor = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'playbackRate');
Object.defineProperty(HTMLVideoElement.prototype,'playbackRate',{
set:function(value){
originalDescriptor.set.call(this,value);
console.log('value changed',value);
},
get:originalDescriptor.get
});
我在此示例中使用了视频原型,可以通过将 HTMLVideoElement.prototype
替换为视频元素的参考来调整特定元素的描述符。
我想完成的事情:
我正在尝试为 chrome 编写一个扩展,为 Youtube 添加一些额外的功能。这个特殊问题与了解用户何时更改播放速率有关(这可以通过单击设置图标,然后单击速度来完成)。
我尝试过的事情:
我尝试通过将 HTMLVideoElement 上的 "playbackRate" 属性 替换为 getter/setter 对象来实现此目的,以便我可以检测何时发生这种情况。
问题:
当用户更改它时,我的所有逻辑都会运行,但是视频将不再真正改变速度。
代码:
let videoObj = document.getElementsByTagName('video')[0];
let storePlaybackRate = videoObj.playbackRate;
Object.defineProperty(videoObj,'playbackRate',{
get(){return storePlaybackRate;},
set(val){
storePlaybackRate = val;
console.log("Updated Value: ",val);
//Custom Logic that does work.
return val;
}
});
要对此进行测试,只需将代码粘贴到任何 YouTube 视频的控制台中,然后更改播放速度。 console.log 发生了,但视频不再改变速度。
我已经检查过的东西
1.That 这个 属性 还不是我要覆盖的 getter/setter 对象。这是通过以下方式检查的:
Object.getOwnPropertyDescriptor(videoObj, 'playbackRate');
2.I 以为可能是因为我没有在 setter 中返回新值,但事实并非如此。
最终总结
我知道还有其他方法可以做我想做的事情,所以如果通过这种方法无法做到,那也没关系。但我真的很想了解为什么这行不通。或者如果我犯了一个错误。
谢谢。
您正在覆盖继承的 getter/setter。
HTMLVideoElement 没有自己的 getter/setter playbackRate,而是从 HTMLMediaElement.prototype 继承了一个。这就是为什么 Object.getOwnPropertyDescriptor(video,'playbackRate')
returns undefined
要覆盖它,您必须存储原始描述符,并在您自己的描述符中调用它们。
originalDescriptor = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'playbackRate');
Object.defineProperty(HTMLVideoElement.prototype,'playbackRate',{
set:function(value){
originalDescriptor.set.call(this,value);
console.log('value changed',value);
},
get:originalDescriptor.get
});
我在此示例中使用了视频原型,可以通过将 HTMLVideoElement.prototype
替换为视频元素的参考来调整特定元素的描述符。