Objects and functions which I require only to execute once on a page load are wrapped inside an undefined
check for the object. On Chrome on Windows/Linux which I usually use, the code works perfectly i.e. code only executes once. But on Safari on both iPad and MacBook, the undefined check doesn't work i.e. as per the browser, the object/function is already declared without even the code execution reaching there!
I've simplified my code to only include an if
loop that checks if the nested function is already declared. Since it should not have been declared the first time, I've included someVariable
inside the if
that should never be undefined
.
Run the same function on Chrome and Safari and see the difference.
if (typeof anObject == 'undefined') {
function anObject(someParameter = 'someParameter') {
var someProperty = 'someProperty';
function someMethod(someParameter) {
console.log(someParameter);
}
}
console.log('Hi');
var someVariable = 404;
}
On Chrome, you can see Console logging of 'Hi'
as well someVariable
as 404. But on Safari, there's no console logging and someVariable goes undefined.
If you put breakpoints to understand what's happening - the first undefined check never works actually. The anObject
is defined even before the declaration.
I have tried searching about the differences regarding this between V8 (Chrome JS engine) and JavaScriptCore (Safari's engine) but haven't found anything solid. I assume this is something related to execution and function hoisting. It would be better if someone could explain to me the reason for this difference in execution. The behavior is the same on iPad that too even on Chrome!
Updates:
I've found a similar problem regarding different execution. Seems like this is something related to function hoisting but couldn't find any solid source yet. Javascript Hoisting in Chrome And Firefox
Looks like it is actually a hoisting behaviour now. This works by using function expression. In this case, simple replacing
function anObject()
withvar anObject = function()
. By doing this, I think, the variable doesn't get assigned the function reference even if the function is hoisted and evaluated before execution.As recommended by PhistucK, I have opened the issue on WebKit issue tracker (Bug #199823), Chromium Discuss and TC39 ECMA262 Github (Issue #1632).
This is an existing Webkit bug reported in 2016 - Bug 163209 - [ES6]. Implement Annex B.3.3 function hoisting rules for global scope. I have now summarized the research in my answer.