You might notice that I’m working my way down vertically from the top of the code. When I get to the bottom with no more refactorings (which is restructuring the code without needing to change any tests (which would be a redesign instead), we’ll be done with this lot of refactoring.
The next thing to refactor is the addPlayer() function.
Here’s how it’s called:
function onYouTubeIframeAPIReady() {
...
config.player = addPlayer(frameContainer, videoIds);
}
and here’s what the addPlayer() function does.
function addPlayer(video, videoIds) {
const videoId = getVideoId(video, videoIds);
const options = createOptions(videoIds || videoId);
config.player = new YT.Player(video, options);
const iframe = getIframe(config.player);
const eventHandler = config.eventHandlers.afterPlayerReady;
iframe.addEventListener("afterPlayerReady", eventHandler);
return config.player;
}
You’ll notice that the addPlayer() function does things with config.player, but that is also being assigned by the code that called the addPlayer() function. That means that there is no need to use config.player in the addPlayer() function at all.
We can’t improve that yet because the getIframe() function still relies on a global access to config.player. Note: globals are bad and to be avoided if possible.
So, improving the getIframe() function is what next needs to be done, after which improving the addPlayer() function can then occur.
The call to the getIframe() function is called with an argument. That is all good.
const iframe = getIframe(config.player);
The getIframe() function itself though doesn’t do anything with that argument. Instead the function ignores it by having zero function parameters, and instead reaches out to the config.player global once again.
function getIframe() {
const player = config.player;
return Object.values(player).find(
(item) => item.nodeName === "IFRAME"
);
}
We need to update the getIframe() function so that it uses a function parameter called player
, letting us remove that top line in the function.