Skip to Content


Introduction

One could say that JavaScript is an easy programming language (from now on language) to start playing with but difficult to master. I would say that mastering any language is not needed, you just have to be productive with your tools. That’s where I think understanding the core features, may they be good or bad, of any language is more important that knowing how to use all it’s features. With JavaScript understanding the core features can be difficult for developers who are used to other languages, such as Java or C++, even if the syntax is similar. That is why I’ve tried to gather the most common gotchas of the language in one place. I also try to give examples which are SAPUI5 relevant, when possible. But first little info about JavaScript itself.


JavaScript

JavaScript is defined as a prototype-based scripting language with dynamic typing. Prototype based means that in inheritance reuse is achieved by cloning existing objects which serve as prototypes. Dynamic typing means that there are no pre-defined (or pre-compiled) types for variables but types are interpreted at runtime and type of a variable can also change, say from String to Object. JavaScript also has first-class functions meaning, for example, that functions can be passed between functions, they can be referenced same way as variables, and also returned from functions. One could argue that especially it’s dynamic typing and first-class functions are beautiful features that allow flexible development. Prototypal inheritance is also an elegant way for inheritance but it’s sadly de-emphasized by JavaScript’s simultaneous implementation of class based inheritance. This provides partially overlapping language features for the developer who now has to choose which inheritance type to use.

JavaScript also has some really bad parts of which the worst is dependency on global variables. Yes, global variables do make it easier to learn JavaScript and also provide an easy way to make demo apps. But the bad part is that they make it harder to develop and maintain large-scale applications (see. business applications). Bugs may surface at weird places, because of implied global scope for variables without var or variables could be accidentally be overwritten. Other bad parts in JavaScript include missing block scope and ability to accidentally replace language methods, such as undefined and hasOwnProperty.


Even with all it’s quirk, JavaScript is still a proficient programming language which is easy to start with and fun to develop applications with, given that the developer has an understanding of its gotchas. Also JavaScript is becoming more and more of an all-around language that is used in web browsers and mobile apps, but also more in server side applications (see node.js ), so understanding it can be vital for tomorrow’s developer.


Gotchas


1. Incorrect references to “this”


Language feature “this” in JavaScript may be a difficult concept to grasp, especially for someone with object-oriented background. Value of “this” differs depending on how a function is called. This refers to the object to whom the function belongs to. If there is no object then this refers to global object (you see: dependency on global objects here).


Example 1:


Gotcha “this”.



sap.ui.controller("sample.Button", {
     delay: 1000,
     // function is called from view when button is pressed
     onPress: function (evt) {
          
var that = this;
setTimeout(function() {
                //console.log(this.delay); // would produce error because setTimeout scope is global
                console.log(that.delay); //works
                jQuery.sap.require("sap.m.MessageToast");
       sap.m.MessageToast.show(evt.getSource().getId() + " Pressed");
       }, this.delay);
      
}
});








Example 2:


Gotcha when developing SAPUI5 Custom Utilities.


   


sample.Formatter.whoAmI = {    
    console.log(this === window ? "window" : "SAPUI5");    
};
var obj = sample.Formatter;
var whoAmI = obj.whoAmI;
obj.whoAmI();  // outputs "SAPUI5"
whoAmI();  // outputs "window" because this inside the function refers to the global object.








2. Thinking there is block-level scope



function doSomething() {
     // no block scope for for loop
     for (var i = 0; i < someObject.length; i++) {
          var objectToHandle = this.byId("someViewComponent");
     }
     console.log(objectToHandle.getText()); // One would expect it throws an error but it works fine.
}
console.log(objectToHandle.getText()); //objectToHandle is undefined so error is thrown








3. Creating memory leaks (garbage collection)


Example 1:


Global variable is never garbage collected. For example:

someVariable = sap.ui.getCore().getView(); // someVariable is defined without preceeding var so it is added into global object and thus never GCed.


Example 2:

Event handlers in controllers. Remember to unbind click handlers added to view controls programmatically. Otherwise those controls cannot be garbage collected.


MyControl.prototype.onAfterRendering = function() {
  this.$().bind("click", jQuery.proxy(this.handleClick, this));
  }
  MyControl.prototype.onBeforeRendering = function() {
  this.$().unbind("click", this.handleClick);
  }
  MyControl.prototype.exit = function() {
  this.$().unbind("click", this.handleClick);
  }
  MyControl.prototype.handleClick = function(oEvent) {
  // do something...
  }







4. Using == equality check instead of ===


Triple equals === should always be used instead of double equals ==. Double equals does type conversion and trying to find a non provocative way of describing conversion rules, I would say that they are interesting (and impossible to memorize).

Example from A Collection of JavaScript Gotchas – CodeProject

== 0 //true – empty string is coerced to Number 0.
0 == 0″ //true – Number 0 is coerced to String “0”
== 0″ //false – operands are both String so no coercion is done.



5. Inefficient DOM manipulation


Adding dom elements is inefficient. First construct the elements and only once they are ready attach them. In SAPUI5 terms:



6. Functions inside for loops


Or creating closures in loops. In the below example there is 10 closures created but they all share the same environment. This means that when the click handler on the button is activated, variable i always refers to the last value in the loop, that is 10.


Bad implementation:

var listItems = getListItems(); // gets sap.m.List items
var n = listItems.length;  // assume we have 10 elements for this example
for (var i = 1; i <= n; i++) {
  listItems[i].onclick = function() {
   console.log("This is listItem #" + i); // outputs 10 no matter which button is clicked
  };
}


Good implementation:



var listItems = getListItems(); // gets sap.m.List items
var n = listItems.length;  // assume we have 10 elements for this example
var makeHandler = function(num) {  // outer function
return function() {   // inner function
console.log("This is element #" + num); // outputs value between 1-10 depending on which button is clicked
};
for (var i = 1; i <= n; i++) {
  listItems[i].onclick = makeHandler(i+1);
}







7. Checking for null/undefined

Javascript outputs a special value “undefined” when getting attribute values from object attributes that do not exists. As was previously mentioned, JavaScript is a dynamic language, so you sure can set or in other words “create” new attributes on objects with object.newAttribute or object[“newAttribute”].


var object = {};
var attributeValue = object.anyAttibute; // attributeValue is undefined






null is a attribute value explicitly set. We can for example:


var object = {"key", null}
var attributeValue = object.key; // key is null






Things start to become interesting when checking whether there is any value in an attribute. For example, in Java you would just check whether value is null by attribute == null. This is not enough in JavaScript. This is thanks to that, that there are both null and undefined, but also thanks to double vs. triple equals (See 4. Using == equality check instead of ===).

Lets start with an example. One could check whether there is value using:

Bad implementation:


if (object.anyAttibute) {... // false for undefined and null but also for empty string "", number 0 and boolean false






This does guards against null and undefined, both which produce false on the check. BUT, it also provides false for empty string “”, number 0 and boolean false. This might be OK, but in case it is not, following comparison should be used:

Good implementation:


if (typeof object.anyAttibute !== "undefined" && object.anyAttibute !== null) {... // false for undefined and null







Summary

As we have noticed JavaScript has it’s own share of quirks. But once you know how to avoid those, you surely will be more prepared to develop large single-page applications.

If you find any mistakes (I’m no JavaScript guru) or have any other input (e.g. feel something relevant is missing), please leave a comment.

References

http://www.codeproject.com/Articles/182416/A-Collection-of-JavaScript-Gotchas

http://book.mixu.net/node/ch4.html

JavaScript: The Good Parts by Douglas Crockford http://shop.oreilly.com/product/9780596517748.do

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

Leave a Reply