2

I'm in the process of refactoring some code that someone else wrote. There is function that uses:

!!('ontouchstart' in window)

I've seen this used in other projects: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js#L40 And in a Stackoverflow answer: https://stackoverflow.com/a/4819886/1127635

But it seems like it could be slower than alternatives: http://jsperf.com/hasownproperty-vs-in-vs-undefined/12

So why use this possibly slower alternative? What browsers don't support other solutions?

Community
  • 1
  • 1
conradkleinespel
  • 6,560
  • 10
  • 51
  • 87
  • 1
    I don't really understand the main question of your post. Do you want to know why `x in y` approach is used or if it is enough to check for `ontouchstart` property in `window` object? – VisioN Sep 02 '14 at 11:57
  • Sorry about the confusion. The question is: why is it used instead of other available options? – conradkleinespel Sep 02 '14 at 12:02
  • Hm... Obviously to check if the browser supports touch event, which is essential in devices with touch screens. `x in y` is used just for better readability I guess. – VisioN Sep 02 '14 at 12:04
  • Apparently not. `x in y` seems to be used for cross browser compatibility. And it seems like it could be slower than alternatives: http://jsperf.com/hasownproperty-vs-in-vs-undefined/12 – conradkleinespel Sep 02 '14 at 12:06
  • 2
    Typically this would only be called once per page load, so I'd guess that speed isn't a concern for most. – Rich Bradshaw Sep 02 '14 at 12:10

1 Answers1

5

Both of your alternative tests are flawed in some way:

  • window.ontouchstart !== null tests for a non-null listener. Testing the value of ontouchstart is a risky approach because libraries or other code might change the value of ontouchstart. Testing the value is a bad approach; it would be much better to test for the existence of the property itself, which brings us to your next proposed test...

  • window.hasOwnProperty('ontouchstart') tests if the window object has its own ontouchstart property. In some browsers (I've just confirmed this on Chrome 37 and IE9), window doesn't have its own on-event properties; instead, they are properties of window.__proto__.

We shouldn't test for a value (because previous code may have changed the value before we run our code) and we can't test for window's own property, because browser differ in their implementation of where event listener properties exist in window's prototype chain. So, our most consistent option is to test whether the property exists (regardless of value) anywhere in window's prototype chain. This is exactly what we do with the in operator.

Of course, if someone else's code runs before our test, they could add an ontouchstart property where there originally wasn't one. Testing support for events with absolute rigor simply isn't possible and it's an awful business.

apsillers
  • 112,806
  • 17
  • 235
  • 239
  • How about `window.ontouchstart !== void 0`? – conradkleinespel Sep 02 '14 at 12:19
  • Yes, but possibly cross browser and faster. Would that be cross browser? – conradkleinespel Sep 02 '14 at 12:24
  • 1
    Are you really that concerned about speed? How many times per second are you testing whether the browser supports touch events? Human readability of code is vastly more important here. As for whether it would work consistently: maybe. It depends whether all browsers forbid setting `on`-event properties to `undefined` (which would cause `!=== void 0` to fail if it happened). – apsillers Sep 02 '14 at 12:31
  • No, I am not. I'm just curious. How it `window.ontouchstart !== undefined` less readable than `ontouchstart in window`? Also, if this allows to remove the `DocumentTouch` test that modernizr uses, that would be valuable. Do you know of browsers that disallow setting `on`-event properties to `undefined`? – conradkleinespel Sep 02 '14 at 12:33
  • 2
    @conradk That's fair; I'll concede that `=== undefined` is perfectly readable (although `void 0` is *extremely* unclear as a virtually unused language feature; please don't do that). I'm much less quick to assume that `on`-properties can not be set to `undefined` in all browsers (which, again, would mess up your test if some other code got in first). Additionally, I'm not even sure if older browsers consistently initialize `on`-properties to `null`. Maybe they do, but I don't have the browsers to test on. – apsillers Sep 02 '14 at 12:47