重新定义javascript类/对象构造函数以分配全局变量

时间:2018-11-12 00:05:24

标签: javascript

我需要对Youtube的iFrame API进行钩子,以将结果播放器分配给全局变量(我无法触摸实际调用API的代码)。

API的调用方式如下:

player = new YT.Player('player', {
          height: '390',
          width: '640',
          videoId: 'M7lc1UVf-VE',
          events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
          }
        });

我想做的是这样的:

YT.OldPlayer = YT.Player
YT.Player = function() {
    window.YTPlayer = new YT.OldPlayer(arguments)
    return window.YTPlayer
}
YT.Player.prototype = YT.OldPlayer.prototype

但是由于某种原因,对new YT.Player()的调用在我进行了修改后会导致原始调用无法调用的错误。我知道正在调用新的构造函数,但是对YT.OldPlayer()的调用中的某些内容会导致错误,因为window.YTPlayer是未定义的。我在做什么错了?

3 个答案:

答案 0 :(得分:2)

这可能不是您要寻找的答案,而是PSA:

  

我在做什么错了?

我认为这里的主要问题是您尝试monkey-patch的外部库功能。

这不是一个好主意,不仅因为它可能无法按您认为的那样起作用,而且还因为将来可能会在没有任何警告的情况下中断。

  • 您正在修改库可能在内部使用的功能上的功能
    库中可能还有其他功能可以进行假设并取决于此功能的特定行为,除非您阅读了整个库,否则您没有太多的可见性。

  • 即使有效,图书馆也可能随时更改其假设,而不会发出警告
    请记住,您可能不会测试该功能的所有用例,并且库的作者对内部功能的工作方式不做任何承诺。他们可以更改其代码以使用或停止使用所涉及的功能,更改功能工作原理的内部方式等,而无需真正地公布更改。几乎可以肯定,这将以不可预见的方式破坏您的代码,因此您应尽可能远离这种模式。

结论:如果可以的话,找到一种解决问题的方法而又不触及您无法控制的库的内部结构,这将为您省去很多麻烦。


如果您仍然需要这样做

如果您仍然绝对需要这样做,那么您的问题似乎在于,您正在将参数作为类似于数组的对象传递,而这并不是在调用构造函数时得到的。

如果可以使用ES6 rest parametersspread syntax,则可以执行以下操作:

YT.OldPlayer = YT.Player
YT.Player = function(...args) {
    window.YTPlayer = new YT.OldPlayer(...args)
    return window.YTPlayer
}
YT.Player.prototype = YT.OldPlayer.prototype

例如,如果您need to support IE且没有任何转换设置,则无法使用任何一种,则需要找到解决方法:

YT.OldPlayer = YT.Player
YT.Player = function() {
    window.YTPlayer = new (YT.OldPlayer.bind.apply(YT,arguments))
    return window.YTPlayer
}
YT.Player.prototype = YT.OldPlayer.prototype

答案 1 :(得分:0)

尝试应用参数:window.YTPlayer = new YT.OldPlayer.apply(this, arguments)

答案 2 :(得分:0)

我最终得到的解决方案是

YT.OldPlayer = YT.Player
YT.Player = function() {
    window.YTPlayer = new YT.OldPlayer(...arguments)
    return window.YTPlayer
}
YT.Player.prototype = YT.OldPlayer.prototype