• No results found

Detecting JavaScript Properties and Methods

In document HTML5 Programming Jonathan Reid (Page 187-190)

Many of the new HTML5 JavaScript APIs are implemented as new properties or methods on existing objects such as window, document, or navigator. If you try and access these features in browsers that don’t support them, the JavaScript engine will produce an error and your script will come to a grinding halt, as demonstrated in Listing 6-1.

Listing 6-1. Invoking a Method That Doesn’t Exist

<!DOCTYPE html>

<html>

<head>

<title>The HTML5 Programmer's Reference</title>

</head>

<body>

<h1>Feature Detection</h1>

<script>

// Attempt to invoke a fake method foo() on the window object window.foo()

</script>

</body>

</html>

When you run this example, it will produce an error, which you can see if you have the browser’s JavaScript console open. If this were in the middle of a larger script, it would bring the entire script to a halt, which is a pretty catastrophic result.

When you attempt to access a property that doesn’t exist, the result is a little more subtle. Simply reading a nonexistent property will return the value of undefined but will not actually crash the script, as shown in Listing 6-2.

Listing 6-2. Accessing a Property That Doesn’t Exist

<!DOCTYPE html>

<html>

<head>

<title>The HTML5 Programmer's Reference</title>

</head>

<body>

<h1>Feature Detection</h1>

<script>

// Attempt to access a fake property bar on the window object alert(window.bar);

</script>

</body>

</html>

If you run this script it will work perfectly, and the alert pop-up will contain the text “undefined.” The script will not throw an error and will continue to run. In JavaScript, however, undefined is a specific value and its own data type, so if you attempt to manipulate it further (as you would if you were accessing a real property), the results can be surprising, as demonstrated in Listing 6-3.

Listing 6-3. What Exactly Is undefined?

<!DOCTYPE html>

<html>

<head>

<title>The HTML5 Programmer's Reference</title>

</head>

<body>

<h1>Feature Detection</h1>

<script>

// Compare undefined with basic data types alert(window.bar + 5);

alert(window.bar + ' is its own data type');

alert(window.bar == true);

alert(window.bar == false);

if (window.bar) {

alert('undefined is equal to true');

}

if (!window.bar) {

alert('undefined is equal to false');

}

if (window.bar == null) {

alert('undefined and null are equal');

}

if (!(window.bar === null)) {

alert('undefined and null are not strictly equal');

}

</script>

</body>

</html>

When you run this script you’ll see that undefined doesn’t play well with numbers; even a simple addition operation produces the value NaN (for “Not a Number”). And although undefined doesn’t exist it has a string value of “undefined.” And while undefined is not equal to either true or false, it evaluates as false for purposes of flow control. Finally, you can test how undefined and null equate to each other using both the type-converting or “weak” equality operator (==) and the strict equality operator (===). The weak equality operator automatically resolves type differences between the operands, while the strict equality operator does not. In the case of undefined and null, the two values are equal to one another when using the weak operator, but since they have different fundamental data types they fail to pass the strict equality test.

Tip undefined

vs.

null

: it’s important to remember that while these behaviors may be counterintuitive, they are in fact well defined by the eCMaScript Standard and are actual features of the language. Just remember that

undefined

as a value is meant to indicate any property that has not been assigned a value, while

null

is meant to indicate an intentional absence of value.

To fully explain these behaviors, I’d have to dive into a discussion of JavaScript data types and how the language resolves data type differences for the weak equality operator ==, which is a bit beyond the scope of this chapter. Regardless, Listing 6-3 does demonstrate a way to detect the presence of a property on a JavaScript object with predictable results. As shown in Listing 6-4, this method also works for detecting methods, and doesn’t throw an error.

Listing 6-4. Detecting Properties and Methods on JavaScript Objects

<!DOCTYPE html>

<html>

<head>

<title>The HTML5 Programmer's Reference</title>

</head>

<body>

<h1>Feature Detection</h1>

<script>

// To check for a method foo() on the window object, check to see if it is // defined

if (window.foo) {

alert('Method foo() is available');

} else {

alert('Method foo() is not available');

}

// To check for a property bar on the window object use the same test.

if (window.bar) {

alert('Property bar is available');

} else {

alert('Property bar is not available');

}

</script>

</body>

</html>

When you run Listing 6-4 it will show that neither window.foo() nor window.bar are available, and the script will throw no errors. It’s easy to use this method to detect real HTML5 features, as shown in Listing 6-5.

Listing 6-5. Detecting HTML5 JavaScript APIs

<!DOCTYPE html>

<html>

<head>

<title>The HTML5 Programmer's Reference</title>

</head>

<body>

<h1>Feature Detection</h1>

<script>

if (window.postMessage) {

alert('The postMessage feature is available on this browser!');

} else {

alert('The postMessage feature is not available on this browser');

}

if (window.localStorage) {

alert('The localStorage feature is available on this browser!');

} else {

alert('The localStorage feature is not available on this browser');

}

</script>

</body>

</html>

When you run this example you will find out whether or not the postMessage and localStorage features are available on your browser.

This same method works to detect the new HTML5 event interfaces, such as the new device motion and orientation events. Instead of checking for the presence of the event handler (e.g., ondevicemotion) directly, check to see if the event interface is present (e.g., window.DeviceMotionEvent as shown in Listing 6-6).

Listing 6-6. Detecting Support for Event Interfaces

<!DOCTYPE html>

<html>

<head>

<title>The HTML5 Programmer's Reference</title>

</head>

<body>

<h1>Feature Detection</h1>

<script>

if (window.DeviceMotionEvent) {

alert('This browser supports the device motion API!');

} else {

alert('This browser does not support the device motion API.');

}

</script>

</body>

</html>

In document HTML5 Programming Jonathan Reid (Page 187-190)