JS-Tricks.com

Override JavaScript functions

It‘s very easy to override functions in JavaScript. You simply assign another function to the function name.

var myFunction = function() {
	// do something...
};

myFunction = function() {
	// do something different...
};

But it’s also possible to extend the existing function in order to execute something before or after the existing function.

myFunction = (function() {
	var oldMyFunction = myFunction;
	return function() {
		// do something before...
		oldMyFunction.apply(this, arguments);
		// ...and after
	}
})();

The new variable oldMyFunction is required as the function would call itself over and over again otherwise. By using apply() and the arguments array, you don’t have to worry about the parameters as all passed parameters will be looped through.

This code definitely won’t win any beauty contests and may not be simple to understand, but may be useful for extending module code.

Multi-line strings in JavaScript

When working with templates in JavaScript, you might need a simple way to work with multi-line strings. While there are several ways to achieve this, not every solution makes 100% sense. If you just need multi-lines within your code but not within the string itself, you may be familiar with the following way.

var example = 'Lorem ipsum dolor sit amet' +
	'consetetur sadipscing elitr' +
	'sed diam nonumy eirmod tempor invidunt';

However, string upon string of concatenated JavaScript grows messy and ugly pretty quickly and is also a slow way to achieve the goal. The same goes for creating an array and joining it.

var example = [
	'Lorem ipsum dolor sit amet',
	'consetetur sadipscing elitr',
	'sed diam nonumy eirmod tempor invidunt'
].join();

A solution many novice JavaScript developers aren‘t aware of is the following one.

var example = 'Lorem ipsum dolor sit amet\
	consetetur sadipscing elitr\
	sed diam nonumy eirmod tempor invidunt';

Adding a backslash at the end of each line tells the JavaScript engine that the string will continue to the next line. Furthermore this second solution creates a string including line breaks within the string itself. But be warned: not every browser will insert line breaks at the continuance, while others will. Google’s JavaScript style guide recommends to use string concatenation instead of escaping newlines because the latter isn’t part of ECMAScript. However, all of the above won’t bring you multi-line strings at all. It’s actually just line-continuation. Adjusting the solutions above by adding line-break characters does the job but makes the solutions even more messy and ugly.

var example = 'Lorem ipsum dolor sit amet\n' +
	'consetetur sadipscing elitr\n' +
	'sed diam nonumy eirmod tempor invidunt';
var example = [
	'Lorem ipsum dolor sit amet',
	'consetetur sadipscing elitr',
	'sed diam nonumy eirmod tempor invidunt'
].join('\n');
var example = 'Lorem ipsum dolor sit amet\n\
	consetetur sadipscing elitr\n\
	sed diam nonumy eirmod tempor invidunt';

An initially confusing but working “trick” to solve this problem is wrapping the text within a block comment within an anonymous function.

var example = (function() {/*
Lorem ipsum dolor sit amet
consetetur sadipscing elitr
sed diam nonumy eirmod tempor invidunt
*/}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1].trim();

The anonymous function is converted to a string and the content of the comment is extracted. While this does indeed work fine in the browser, it’s slower than string concatenation and mainly intended for use in node.js. The last way to create legible multi-line strings in JavaScript is to use templates.

<script type="text/template" id="example">
Lorem ipsum dolor sit amet
consetetur sadipscing elitr
sed diam nonumy eirmod tempor invidunt
</script>
var example = document.getElementById('example').innerHTML;

By setting the type to text/template, the script tag isn’t a script that the browser understands and thus the browser will simply ignore it. This allows you to put anything in there, which can then be extracted (see var example) later and used as a template. Note that ECMAScript 6 will have real multi-line strings by using backticks, known as a NoSubstitutionTemplate in the spec.

var example = `Lorem ipsum dolor sit amet
consetetur sadipscing elitr
sed diam nonumy eirmod tempor invidunt`;

typeof null === “object”

An initially confusing and counter-intuitive behavior of JavaScript is that the type determination of a variable being null using typeof returns "object".

var demo = null;
typeof demo; // "object"

The reason for this is that typeof will always return "object" for native non-callable objects. Actually, this stands since the beginning of JavaScript and the operator simply returns the type string of a given reference according to the table specified in the ECMAScript language specification ECMA-262 (see page 81).

image

A fix that would have resulted in typeof null === "null" has been proposed (via an opt-in), but was rejected as it was too late to fix the “problem” as a change of typeof null would break existing code like incorrect implementations of type checks.

Default arguments/parameters in JavaScript

When designing your functions, it’s often helpful to be able to assign default values for arguments/parameters that aren’t passed later. Unlike programming languages like PHP, JavaScript doesn’t provide this functionality inherently. Undefined arguments are, well: undefined.

var sayHello = function(name) {
    console.log('Hello, ' + name);
}

By using the shortcut computation of boolean expressions, you can define a default value for each argument which is assigned if the argument is originally undefined.

var sayHello = function(name) {
    name = name || 'Nobody';
    console.log('Hello, ' + name);
}

While sayHello('Peter') still works, sayHello() (called without any arguments) would now result Hello, Nobody. Neat.

Class constructors without using “new” in JavaScript

When creating a class constructor in JavaScript, you may prefer to allow its instantiation without using the new keyword—just like jQuery does with their $() factory function. Let’s assume the following class as a simple example.

function Person(name, age) {
    this.name = name;
    this.age = age;
}

While var jack = new Person('Jack', 32) would work, var jim = Person('Jim', 34) doesn’t—so far. Actually jim would be simply undefined after the call. But even worse: if someone calls the constructor without using new, the global scope will be poluted by the two variables name and age as calling a function without specifying its context forces the browser to pass it in the global object (which is window). By checking whether the requested object is already an instance of the class, you can return a new instance if it isn’t or execute the actual constructor if it is.

function Person(name, age) {
    if (this instanceof Person) {
        this.name = name;
        this.age = age;
    } else {
        return new Person(name, age);
    }
}

Both var jack = new Person('Jack', 32) and var jim = Person('Jim', 34) would work now. The following way does exactly the same but is a bit shorter and handier.

function Person(name, age) {
    if (!(this instanceof Person)) return new Person(name, age);
    this.name = name;
    this.age = age;
}

jQuery’s .load() callback for cached images in Internet Explorer

jQuery’s .load() function is often used if a callback function is required be executed as soon as an element is completely loaded. This is gladly used for loading images completely at first and processing certain attributes of an image (e.g. its width and height) afterwards. However, Microsoft’s Internet Explorer doesn’t execute the callback if images are cached already.

While often appending a random number (to prevent caching) is recommended for this known issue, there’s a much more resource-efficient trick: simply set the src attribute of an image after the definition of its .load() function.

$('img').load(function() {
    // do something
}).attr('src', '/new-image-source.jpg');

I see some JavaScript scripts using »!0« and/or »!1« occasionally. What does that mean exactly?

Anonymous

Those are shortcuts for true and false, making use of JavaScript’s logical NOT operator (the exclamation point) and the fact that JavaScript uses weak typing, meaning that 0, false and null all mean the same in comparisons unless you force JavaScript to compare the type as well (by using ===). Using this knowledge, you can shorten true using !0 and false using !1.

Prevent links in standalone web apps to be opened in Mobile Safari under iOS

iPhones, iPads, and iPods offer the opportunity to integrate Web apps (including an icon) just like conventional, native apps on the home screen. Those Web apps are then started in a standalone mode and behave optically just like real apps. However, a bad feature of iOS for Web app development is that links in such Web apps (which actually are simply websites that are displayed in full screen mode) automatically open in Mobile Safari — that is, the standalone app closes and switches to the Safari app. Annoying. You can use the following snippet of JavaScript (include it at the bottom of your HTML site) to prevent this.

var a = document.getElementsByTagName('a');
for (var i = 0; i < a.length; i++) {
    a[i].onclick = function() {
        window.location = this.getAttribute('href');
        return false;
    }
}

If you’re using jQuery in your Web app, you can use the following, much-shorter version of the snippet.

$(document).on('click', 'a[href]', function(event) {
    event.preventDefault();
    window.location = $(this).attr('href');
});

Detect Touch devices using JavaScript

The following function allows the detection of touch devices (smartphones, tablets, …) using JavaScript. As an example, this allows you to offer certain actions on a website or web application only for appropriate devices like disabling hover effects for touch devices.

function isTouchDevice() {
    return ('ontouchstart' in window);
}