Side-effect while extending the Array class

JavaScript No Comments »

Let us assume, that you wrote some code to extend the Array class to a method. In this case we will add the min() method, which will return the lowest numeric value of all elements inside the array:

Array.prototype.min = function min(){
 
  var returnValue = Number.MAX_VALUE;
 
  if(this.length === 0){
    return false;
  }
 
  for(var i = 0; i < this.length; i++){
    if(this[i] < returnValue){
      returnValue = this[i];
    }
  }
 
  return returnValue;
 
};

This methods work fine, but you will notice a strange behavior if you cycle through all array elements using a for loop construct.

var list = [1, 2, 3];
for(var i in list){
  console.log(list[i]);
}

The code will produce this output:

1
2
3
min()

It seems that the for loop also iterates over the recently added method.

The method can only be removed from the Array class, not from an instance of it:

delete Array.prototype.min;

It can not be removed, but overwritten by assigning a value to it:

list.min = 0;

So, if you still want to use the for loop to iterate over the entries, you have to check the type of each entry:

for(var i in list){
  if(typeof(list[i]) != 'function'){
    console.log(list[i]);
  }
}

Documenting private methods with JSDoc

JavaScript No Comments »

The best way to comment directly in the source code is using JSDoc, the JavaScript equivalent of JavaDoc.

To comment on the code, just insert specially formatted comment lines (starting with /** instead of /*) containing a description text and tags before each class, attribute or method. As in JavaDoc, there a several tags to describe the source code: @param, @return, @version and many more.
If you have included this comments, you have to run a perl script over the javascript files which creates a bunch of HTML files containing the information from your sources.

But be careful if you are commenting on private methods! In this example there will be no comment for _privateMethod():

/**
 * Description for this MyObject..
*/
function MyObject(){
 
/**
 * @param {object} myElement Description for myElement
 * @private
*/
  var _privateMethod = function(myElement){
    ;
  }
 
/**
 * @return {number} Answer to Life, the Universe, and Everything
*/
  this.publicMethod = function(){
    return 42;
  }
 
}

JSDoc does not support this way of defining private methods. You have to use this scheme:

 
function MyObject(){
  function _privateMethod(){
    ;
  }
}

Reading custom HTML attributes

HTML, JavaScript No Comments »

Sometimes you need to store some extra information for an HTML element, which provides additional data to your scripts. The best way to store this information is to use it as an attribute value on the element itself.
You could use a special CSS class name for a group of elements which should be handled identically, but you might lose the flexibility of CSS if these elements have completely different styles. Another possibility is to use custom (proprietary) attributes. The Dojo Toolkit makes massively use of this method. Please note that your document will not be valid (X)HTML, if you do so. Anyway, this can be quite useful but you have to be careful how to set and read the attributes.

At runtime an HTML element is presented as a DOM element object. You can add attributes by assigning them to the object.

var myElement = document.getElementById('testDiv');
myElement.mood = 'happy';

What happens if you are dealing with custom attributes that are not assigned at runtime but on the sever side? You will notice two characteristics: at first, all attribute names are lowercased by the browser and secondly this will not work as you expect.

Imagine you have this HTML element:

 
<div id="testDiv" foo="bar"></div>
 

and this script:

var myElement = document.getElementById('testDiv');
alert(myElement.foo);

This alert box will show undefined. It seems that only HTML attributes which are described in the HTML specification (such as id, lang or title) are applied as attributes to the DOM element object. Of course, there are exceptions for this rule: the Internet Explorer applies all attributes to the object.

I made a comparision sheet showing which browser supports which behavior.


Firefox 2

Opera 9

Safari 3

IE 7
attribute set by assigning
element.attributeName yes yes yes yes
element.getAttribute() null null null yes
attribute set by setAttribute()
element.attributeName undefined undefined undefined yes
element.getAttribute() yes yes yes yes
attribute set on server side
element.attributeName undefined undefined undefined yes
element.getAttribute() yes yes yes yes

So, if you want to use custom attributes while having HTML elements which are created on runtime and on the server side, there is only one possibility: use setAttribute() and getAttribute(). This combination works in every case and in every browser.

How to get the actual style value of an element

HTML, JavaScript No Comments »

Golo asked me some time ago how to retrieve the actual style property value of an element. It is easy to get the value applied by the element's style attribute or the CSS class name. But the actual value is affected by many CSS rules which are applied to the element: element type, element's parents, class name(s) and style attribute (which can, of course, be modified by JavaScript through runtime).

CSS rules
An example of different CSS rules overwriting each other.

Luckily we do not have to worry about this — it is the browser's job to apply all rules correctly. There are two ways of retrieving the actual style information. Those on the dark side use element.currentStyle[style property] to get the actual property value. All others use the WC3 method window.getComputedStyle() to get a CSSStyleDecoration object which can be accesed via getPropertyValue(style property).

Note, that the proprietary currentStyle() method has the same syntax as in your CSS files (e.g. background-color) while W3C DOM method uses the syntax you know from JavaScript (e.g. backgroundColor).


WordPress Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in