Friday, 28 December 2012

Using .apply or .call methods in JavaScript constructors and functions

This is by no means an authoritative article on the apply and call methods, however I wanted to highlight their basic usage because I could not find any simple examples online; and I like simplicity.

In essence, the  apply and call methods are:
  1. Available to all functions, to help you load in parameters into a function
  2. The methods themselves take two parameters: (1) an object and (2) a set of parameters
  3. apply takes an ['array', 'of','parameters'] whereas call takes a 'comma', 'separated', 'list'
Let's start with an example of a standard constructor function:

Simple Constructor

function construct(prop1, prop2, prop3) { this.prop1 = prop1; this.prop2 = prop2; this.prop3 = prop3; } var _1 = new construct(); var _2 = new construct(); construct.apply(_1, ['one', 'two', 'three']); construct.call(_2, 'one', 'two', 'three'); console.log(_1); console.log(_2);

In this example we:
  • First create the constructor construct
  • Create two instances of the constructor using variables var _1 and var _2, which then each become an object
  • apply an array to var _1 and call a set of parameters to var _2
  • Log the variables using console.log
What's important to note is that the constructor instance first had to be initialized to a variable before the apply or call methods could be used on it. This is because the methods require an object as their first argument.

So once the objects have been created, we now have two objects based upon our blueprint construct. These objects by themselves are empty. If we were to do a console.log on them we would see that they have properties without values. Values will just show as undefined.

Then we apply the methods onto the objects and automagically the properties of the object now have values! Don't you just LOVE JavaScript? (OK, maybe not like I do ;D)

Function

Here is how to use these methods in a standard function. The only caution I would give is over performance, since the apply and call methods are much slower than just directly calling the function('with', 'parameters');. So, use it only if you really need to! Here goes:

function do_something(a, b, c) { return console.log(a + b + c); } do_something.apply(this, [' one ', ' two ', ' three ']); do_something.call(this, ' one ', ' two ', ' three ');


Constructor with args

Back to constructors, but this time an example without using the apply method, just to show you that its not all that magical. The same effect can be achieved with a simple for loop.

function construct_args(prop1, args) { this.prop1 = prop1; var num = 2; for (var prop = 0; prop < args.length; prop++) { this['prop' + num] = args[prop]; ++num; } return console.log(this); } var _3 = new construct_args('one', ['two', 'three']);


Anonymous Constructor with .apply()

I have no idea why you would want to use the following pattern but it uses an anonymous constructor function which is self-initialized with the apply method:

var args = ['one', 'two', 'three']; var _4 = new $constructor; (function(prop1, prop2, prop3) { this.prop1 = prop1; this.prop2 = prop2; this.prop3 = prop3; return console.log(this); }).apply(_4, args);

You can see and test all these code examples here: http://jsfiddle.net/jasdeepkhalsa/5TysW/

Any questions, comments, additions, please leave a comment.

Thursday, 25 October 2012

CSS Specific for Internet Explorer

As much as we don't like to deal with the IE bugs, we still have to face it because your boss and visitors are still using Explorer. It gets frustrating when different versions of Explorer displays web pages differently due to the inconsistent rendering engine. We typically use IE conditional comments to fix the IE issues. But there are more ways than the conditional comments...

#1 IE Conditional Comments

IE conditional comment is probably the most commonly used to fix the IE bugs for specific versions (IE6, IE7, IE8). Below are some sample code to target different versions of Internet Explorer:
  • <!--[if IE 8]> = IE8
  • <!--[if lt IE 8]> = IE7 or below
  • <!--[if gte IE 8]> = greater than or equal to IE8
<!--[if IE 8]>
<style type="text/css">
 /* css for IE 8 */
</style>
<![endif]-->

<!--[if lt IE 8]>
 <link href="ie7.css" rel="stylesheet" type="text/css" />
<![endif]-->

#2 CSS Rules Specific to Explorer (IE CSS hacks)

Another option is to declare CSS rules that can only be read by Explorer. For example, add an asterisk (*) before the CSS property will target IE7 or add an underscore before the property will target IE6. However, this method is not recommended because they are not valid CSS syntax.
  • IE8 or below: to write CSS rules specificially to IE8 or below, add a backslash and 9 (\9) at the end before the semicolon.
  • IE7 or below: add an asterisk (*) before the CSS property.
  • IE6: add an underscore (_) before the property.
.box {
 
 background: gray; /* standard */

 background: pink\9; /* IE 8 and below */

 *background: green; /* IE 7 and below */

 _background: blue; /* IE 6 */

}

#3 Conditional HTML Class

The third option, which was founded by Paul Irish, is to add an CSS class with the IE version to the HTML tag by using IE conditional comments. Basicially, it checks if it is IE, then add a class to the html tag. So to target specific IE version, simply use the IE class as the parent selector (eg. .ie6 .box). This is a clever way and it doesn't cause any validation errors.
<!--[if lt IE 7 ]> <html class="ie6"> <![endif]-->
<!--[if IE 7 ]> <html class="ie7"> <![endif]-->
<!--[if IE 8 ]> <html class="ie8"> <![endif]-->
<!--[if IE 9 ]> <html class="ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html> <!--<![endif]-->