Quantcast
Channel: User Ben Aston - Stack Overflow
Viewing all articles
Browse latest Browse all 56

Answer by Ben Aston for Function works only in Safari, other browsers throw `Uncaught TypeError: X is not a function`. Where's the problem?

$
0
0

window.changeLabel === 'undefined' will return false regardless of browser because you are comparing a property value with the string 'undefined' and not the value undefined.

In Safari's sloppy mode the following will "leak" the function declaration outside of the block within which is was declared.

if(false) { function foo() {} }console.log(foo) // function foo() {} in Safari, undefined in Chrome-based browsers

Chrome's sloppy mode behaves differently due to a different interpretation of the spec (the Web Compatibility Annex IIRC), meaning the function does not "leak", and remains undeclared.

[More details at the end 👇]

And so in Safari your code accidentally works by leaking the function declaration, making it visible outside the block.

Two things to do:

  1. Use strict mode in all production-facing code
  2. Use typeof for its intended purpose of checking for undeclared identifiers
if (typeof changeLabel !== 'function') {  window.changeLabel = function() {    // Do something.  }}// Now you can always use changeLabel...

More details

The reason for all this faffing is that the scope of function declarations inside blocks was never really properly specified in early versions of JavaScript (it was exclusively a function-scoped language back then), and so browser vendors did their own different things. When TC-39 finally decided to standardise this behavior in ES2015, the "Don't Break The Web" requirement meant that the sloppy mode specification for this edge case ended-up being insanely complicated and counterintuitive, leading to two different implementations (only one of which is correct).


Viewing all articles
Browse latest Browse all 56

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>