Archive for July, 2013

It’s common for developers to want to run angular’s compilation over some piece of html inside a directive. However, if you are not careful, you can easily cause memory leaks.

Here is an example of code that may leave behind unneeded child scopes:
// in your directive's link function, you do something like this
var content = $compile(template)(scope); // compile and link to the current scope
element.append(content); // add to the DOM

// ... the later, we want to update the content of the element ...

var newContent = $compile(template2)(scope);
content.replaceWith(newContent);

// While replaceWith does remove the old html, it does not remove any of the scopes that may have been added the first time we did compile/link on the old template.
This is a better way to do it:
var newScope = scope.$new(); // create a new scope from the current scope
var content = $compile(template)(newScope); // compile and link to the new scope
element.append(content); // add to the DOM

// .. then later, we want to update the content of the element ...

newScope.$destroy(); // destroy the scope and all child scopes
var newScope2 = scope.$new(); // create a new scope
var content2 = $compile(template2)(newScope2); // compile and link
content.replaceWith(content2); // replace the html content with the new content
Also, note that if you want to know when a directive is destroyed to do any kind of additional cleanup, you can add a destroy listener to the element the directive’s link function is called with:
element.on('$destroy', function() {
 .. unhook whatever ..
});

Just remember that you won’t need to unhook jquery events that have been attached on or below the target element, since angular calls .remove() on it, thereby removing all listeners.

Guard and default operators in Javascript

Most programmers are familiar with the ‘&&’ and ‘||’ logical operators. What many do not know is how these operators behave in Javascript.

Quick review

In Javascript, the following values are considered falsy:

  • false
  • 0 (zero)
  • “” (empty string)
  • null
  • undefined
  • NaN (a special Number value meaning Not-a-Number!)
All other values are considered truthy.

Guard operator

Let’s say you want to access an attribute deep inside an object:

var name = data.person.name;

It’s entirely possible that not all objects in that chain are defined. So, to write safe code, we may want to do something like this:

var name;
if(data.person) {
  name = data.person.name;
}

To avoid nesting, which can sometimes make the code seem bulkier and more difficult to read, we can write the same code without the ‘if’ statement while still GUARD ourselves against possibly referencing an undefined object in the chain:

var name = data.person && data.person.name;

The reason why we can do this is because the ‘&&’ operator behaves in the following way:

  • If the value on the left is falsy, return it
  • If the value on the left is truthy, continue the evaluation of the value to the right recursively
  • If the last value is reached, return it no matter if it is falsy or truthy

var obj0;

// obj0 is undefined, so is falsy and is returned
// val0 is set to obj0, so is set to undefined
var val0 = obj0 && obj0.foo && obj0.foo.name;
var obj1 = {};

// obj1 is truthy, so continue
// obj1.foo is undefined (falsy), so return it
// val1 is therefore set to undefined
var val1 = obj1 && obj1.foo && obj1.foo.val;
var obj2 = {
  foo: {}
};

// obj2 is truthy, so continue
// obj2.foo is truthy, so continue
// obj2.foo.name is the last value, return it
// val2 is set to obj2.foo.name, which is undefined
var val2 = obj2 && obj2.foo && obj2.foo.name;
var obj3 = {
  foo: {
    name: 'Joe'
  }
};

// obj3 is truthy, continue
// obj3.foo is truthy, continue
// obj3.foo.name is the last value, return it
// val3 is set to obj3.foo.name, which is 'Joe'
var val3 = obj3 && obj3.foo && obj3.foo.name;

Since the ‘&&’ operator can be used to GUARD against errors when retrieving members of an object, it is commonly referred to as the ‘guard operator’.

Note that the ‘&&’ operator can be used in other scenarios as well:

var a = 1;
var b = 0;
var c = a && b;  // c is now set to 0, since b was the last value returned by the expression

Default operator

Where the ‘||’, on the other hand, returns the first truthy value in the expression.

var a = 0;
var b = 1;
var c = a || b; // c is set to 1, since b is the first truthy value in the expression

The ‘||’ operator is commonly referred to as the ‘Default operator’, because it is often used to assign a default value.

function myFunc(node, params) {
  
  // if params was an object that was passed in (is truthy), assign it to 'settings'
  // if params is not passed in (is falsy), assign a default object to 'settings'
  var settings = params || {isAwesome: true}; 
  
  if(settings.isAwesome)
    node.innerHTML = "Awesome";
}

Javascript ‘this’ scoping

The keyword ‘this’ refers to the context in which a given function is running.

Default context

If a function belongs to an object, it is generally called using the dot notation:

var obj = {
  func: function() {
    alert(this === obj); // alerts 'true'
  }
};

obj.func(); // run 'func' in the context of 'obj'

Therefore, by calling obj.func(), we are saying: “Run ‘func’ in the context of ‘obj’, such that the ‘this’ keyword in ‘func’ refers to ‘obj'”

This kind of behavior allows us to do things like this:

var obj = {
  name: 'Joe',
  func: function() {
    alert(this.name); // 'this' is referring to obj, so obj.name gives us 'Joe'
  }
};
obj.func(); // func runs in the context of obj

So far so good, right?

Context coercion

In javascript, we have the power to tell any function to run in the context of absolutely any object we want…not just the one it belongs to, using the magic ‘apply’ and ‘call’ functions:

var obj = {
  name: 'Joe',
  func: function() {
    alert(this.name);
  }
};

var obj2 = {
  name: 'Mike'
};

var obj3 = {
  name: 'Bill'
};

obj.func.apply(obj2); // run 'func' in the context of 'obj2', alerts "Mike"
obj.func.call(obj3); // run 'func' in the context of 'obj3', alerts "Bill"
Both the ‘call’ and ‘apply’ functions give us the ability to specify context. The two are a bit different in that if you wanted to pass arguments to the called function, using ‘apply’ you would pass the arguments as an array while with ‘call’ you would pass individual arguments:
var obj = {
  name: 'Joe',
  func: function(age, weight) {
    alert(this.name+" with age of "+age+" and height of "+weight);
  }
};

var obj2 = {
  name: 'Mike'
};

var obj3 = {
  name: 'Bill'
};

obj.func.apply(obj2, [23, 155]); // run 'func' in the context of 'obj2', alerts "Mike"
obj.func.call(obj3, 43, 176); // run 'func' in the context of 'obj3', alerts "Bill"

So, to review:

  1. Functions that belong to objects can be called using dot notation and run in the context of those objects
  2. Any function can be coerced to run in the context of any other object using the ‘call’ and ‘apply’ methods
  3. Just a reminder, the context of a function is whatever the ‘this’ keyword refers to

Anonymous functions

An anonymous function is one that does not belong to any object. In other words, you can’t call it using dot notation (e.g. someObj.yourFunc() ). Anonymous functions, unless coerced via the ‘call’ or ‘apply’ methods, run in the context of the global scope (usually the ‘window’ object).

var obj = {
  func: function() {
    var anonFunc = function() {
      alert(this === obj); // alerts 'false'
      alert(this === window); // alerts 'true', running in the context of the global object
    };
    anonFunc(); // run anonFunc in...well...no context specified...
  }
};

obj.func(); // run 'func' in the context of 'obj'

So how can we refer to ‘obj’ from the anonFunc? One way is to change the code like so:

var obj = {
  func: function() {
    var anonFunc = function() {
      alert(this === obj); // alerts 'false'
      alert(this === window); // alerts 'true', running in the context of the global object
    };
    anonFunc.call(this); // run anonFunc in the context of 'this', where 'this' is 'obj'
  }
};

obj.func(); // run 'func' in the context of 'obj'

However, a much more common way of fixing this issue is by assigning a variable ‘self’ to the target ‘this’, then just using the ‘self’ variable everywhere.

var obj = {
  func: function() {
    var self = this;
    var anonFunc = function() {
      alert(self === obj); // alerts 'true', since 'self' is set to the 'this' that is the 'obj'
      alert(self === window); // alerts 'false'
    };
    anonFunc(); // run anonFunc in the context of 'this', where 'this' is 'obj'
  }
};

obj.func(); // run 'func' in the context of 'obj'

Here is a more practical example:

var obj = {
  name: "John Doe",
  id: "82384349",
  func: function() {
    var self = this;
    $.get('ajax/getAge', {id: self.id}).done(function(data) {
      alert(self.name+" is "+data+" years old" );
    });
  }
};

obj.func(); // run 'func' in the context of 'obj'

Notice how I declared ‘self’ at the top of the ‘func’ function and then used it everywhere. This has the advantage of making our code less error-prone. Also, if you run your javascript through a minimizer, the ‘self’ variable will be compressed and you will end up with a slightly smaller file then you would if you used ‘this’ everywhere (which does not compress, since it is a keyword in javascript).

Happy Hacking!

Generating a parser

An important feature of Anzo on the Web is the ability to specify custom equations, similar to the ones you see in Excel, to do various analytics.  The language is similar to what you see in Excel, except the values are specified by RDF paths, rather than regions.  The editor has the formula editing region at the top, a place to select value fields on the bottom-left and a function selector on the bottom-right:

formulaEditor

For fast validation of formulas, I needed to build a parser for the language that would run in the browser (in javascript).  To do so, I used the awesome LALR(1) parser and lexical analyzer generator for JavaScript, which is itself written in javascript.

The installed version can be found here: JS/CC

To create a parser, you need to tell it about the language you want to parse.  You do this using aBackus-Naur-Form-based meta language , and it generates the javascript parser for you!  A good way to get started is to study the Calculator example, which can be loaded by clicking on the dropdown at the top, selecting it and clicking the ‘load’ button.