Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Wednesday, April 1, 2015

JavaScript tricks

Duck typing

You can invoke an object's method on another object, as long as the latter has everything the method needs to operate properly. Example:
function foo() {
  // the last element of arguments is popped
  Array.prototype.forEach.pop.bind(arguments)();
  // this works as if arguments had a "forEach" method
  Array.prototype.forEach.bind(arguments)(function(a){ console.log(a) }); 
}

Dynamic scoping

The easiest way to archive dynamic scoping in JavaScript is to use eval:
var x = 1;
function g() {
  console.log(x);
  x = 2;
}
function f() {
  // create a new local copy of `g` bound to the current scope
  var x = 3;
  eval(String(g));
  g();
}
f();             // prints 3
console.log(x);  // prints 1
Perhaps this is one of the few valid reasons to use eval in JavaScript.

Loose augmentation

Suppose that you have several module files that share a MODULE variable. Then it is preferable to let organize each module file like
var MODULE = MODULE || {}; // MODULE is always declared due to hoisting
(function() { 
  var private_var;         // only accessible to myFunction
  MODULE.myFunction = ...  // augment the module with a new function 
})();
In this way, you can load all of your module files asynchronously without the need to block, given that the functions defined in the module don't depend on each other.

Call-site memorization

The word memoization refers to function-level caching for repeating values. Suppose we have a function G such that G(f) will compute an expensive function f many times. If f is pure, then we can cache the results of f without modifying G or introducing global variables. Instead of calling G(f) directly, we pass to G a closure of f as follows:
var memorize = function(f) {
  var cache = {};
  return function(x) {
    if(!cache.hasOwnProperty(x))
      cache[x] = f(x);
    return cache[x];
  };
};
G(memorize(f));
The use of cache here is totally transparent from the view of G. Note: You may want to use an LRU/LFU cache to avoid running out of memory.

Friday, June 27, 2014

Using Promises Instead of Callbacks

Stop using nested callbacks for async function calls in JavaScript!
https://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-promises-are-functional-nodes-biggest-missed-opportunity/

A detailed comparison between various implementations of Promise:
http://complexitymaze.com/2014/03/03/javascript-promises-a-comparison-of-libraries/

Bluebird is albeit the fastest Promise implementation in the market.
https://github.com/petkaantonov/bluebird

JQuery already uses Promise in its async operations, e.g., get, post, ajax, etc.

Scala also has Promise, aka Future:
http://docs.scala-lang.org/overviews/core/futures.html

Tuesday, March 25, 2014

JavaScript Design Pattern Examples

Factory

function ObjectFactory(ctor) {
  var obj = {};
  return function() {
    if(typeof ctor.prototype === 'number')
      obj.__proto__ =  Object.prototype;
    else
      obj.__proto__ =  ctor.prototype;
    var ret = ctor.apply(obj, arguments);
    return typeof ret == 'object' ? ret : obj;
  }
}
function Point(x, y) { this.x = x; this.y = y }
// The following is equivalent to: var p1 = new Point(0, 0);
var p1 = ObjectFactory(Point)(0, 0);

Singleton

var createSingletonOf = function(ctor) {
  var singleton; 
  return function() {
    return singleton || (singleton = ObjectFactory(ctor).apply(null, arguments))
  }
}
var point = createSingletonOf(Point);
var p2 = point(1,2);
var p3 = point(3,4); // p3 === p2

Observer

var Observer = (function() {
  var listeners = [];
  return {
    listen: function(callback) { listeners.push(callback) },
    trigger: function(res) { listeners.forEach(function(fn) { fn(res) }) },
    observe: function(act) { this.trigger(act()) },
  };
})();

Adaptor

// ThermometerFahr is an adapter of ThermometerCels
var ThermometerFahr = function() {
  var thermoC = new ThermometerCels();
  this.setTemperature(tempF) { thermoC.setTemperature((tempF?32)/1.8) } 
  this.getTemperature(tempF) { return thermoC.getTemperature()*1.8+32 } 
}
var thermoF = new ThermometerFahr();

Decorator

Function.prototype.bind = function (scope) { // a helper function
    var fn = this;
    return function () {
        return fn.apply(scope);
    };
}
/* MethodProfiler class */
var MethodProfiler = function(obj) {
  this.obj = obj;
  this.timers = {};
  for(var key in obj) {
    if(typeof obj[key] !== 'function') continue;
    (function(method) {
      this[method] = function() {
        this.tick(method);
        var ret = obj[method].apply(obj, arguments);
        this.log(method, this.getElapsedTime(method));
        return ret;
      }.bind(this);
    }.bind(this))(key); 
  }
};
MethodProfiler.prototype = {
  tick: function(method) {
    this.timers[method] = (new Date()).getTime();
  },
  getElapsedTime: function(method) {
    return (new Date()).getTime() - this.timers[method];
  },
  log: function(method, time) {
    console.log('Elapsed time of executing ' + method + ' is ' + time + ' ms');
  }
};

// Demonstration of usage
var test_target = { foo:function() { alert('hi there') } };
var profiler = new MethodProfiler(test_target);
// profiler is a decorator of test_target
profiler.foo();


Monday, February 3, 2014

Functional JavaScript

How experiences in Haskell help writing functional and reusable JavaScript code:
http://seanhess.github.io/2012/02/20/functional_javascript.html

PureScript: writing JavaScript like a Haskell maniac
https://github.com/purescript

Implementing and explaining notions in category theory using JavaScript:
https://jscategory.wordpress.com/


Sunday, December 8, 2013

Object-Oriented Programming in JavaScript

Access Modifiers

It is a convention in JavaScript that a class member whose name starting with an underscore is "private", that is, it is intended for internal use and should not be considered part of the public API of the class. However, one can in fact define a de facto private members using closures. In the following example, new MyClass will return an object with only the properties assigned to this object and in the prototype object of the class.
var MyClass = (function () {
    // private static field
    var counter = 0;

    // constructor
    var ctor = function (_name) {
        // private instance field
        var _id = ++counter;
        // public instance method
        // Private instance members can only be accessed this way
        this.getName = function () { return _name }; // readonly
        this.getID = function () { return _id }; // readonly
    };
    // public instance method (shared across instances)
    // Note that class methods cannot access instance members.
    ctor.prototype.toString = function () {
        return 'Hi! My my name is ' + this.getName()
        + ', my id is ' + this.getID()
        + ' and there are ' + counter + ' instances in total.'
    };
    // public static method
    ctor.getNumInstances = function () { return counter };
    return ctor;
})();
// Error: cannot access id outside ctor
MyClass.prototype.setID = function(id){ this.id = id; }

Inheritance

Javascript doesn't exactly have subclass objects, but prototype is a useful workaround to make a "base class" object of certain functions that act as objects. For example:
/* Definition of class Person */
var Person = function(name) {
    this.name = name;    
    this.canTalk = true;
    this.greet = function() {
        if (this.canTalk) console.log("Hi, I'm " + this.name);        
    };
};
/* Definition of subclass Employee */
var Employee = (function() {
    var ctor = function(name, title) {
        // call parent constructor
        Person.call(this, name);
        // initializations for Emplyee        
        this.title = title;
    };
    // store the method before overriding it
    var _greet = ctor.greet || Person.prototype.greet;

    // overriding parent's method
    ctor.prototype.greet = function() {
        // call the original method
        _greet.apply(this, arguments); 
        console.log("I'm a " + this.title);        
    };
    // setup the prototype chain
    ctor.prototype = Object.create(Person.prototype);
    ctor.prototype.constructor = ctor; // repair the inherited constructor
    return ctor;
})();

References and Resources

1. Introduction to Object-Oriented JavaScript
2. Prototypes Are Not Classes
3. Constructors in JavaScript objects
4. Douglas Crockford: Advanced JavaScript (Video)
5. Constructors Considered Mildly Confusing
JavaScript The Definitive Guide, 6th Edition,  Chapter 9
(http://js-bits.blogspot.com.au/2010/08/javascript-inheritance-done-right.html)

Friday, December 6, 2013

CoffeeScript and LiveScript

I am familiar with JavaScript, and I am interested in CoffeeScript and LiveScript. I really need some good tutorials before I get enough brevity to use them in my projects.

Functional Programming in JavaScript using LiveScript and prelude.ls

Tuesday, November 26, 2013

Pitfalls for JavaScript beginners

Eval. According to ES5, indirect calls to eval like var a = eval; a(code) or (0, eval)(code) or window.eval(code) are treated as a global evals, i.e., they can't access or declare variables in the lexical scope. For example,
var x=1; (function(){ var x=0; (eval)("console.log(x)"); })();   // prints 0
var x=1; (function(){ var x=0; (0,eval)("console.log(x)"); })(); // prints 1
You can check this post by Juriy Zaytsev for more information about global eval. According to another post of the same author, which examines the delete operator and eval, you can also delete a variable declared in eval:
(function (){ var x = 10; return delete x; })()          // false
(function (){ eval('var x = 10;'); return delete x; })() // true
In words, eval-introduced bindings do not have the DontDelete property set on them, so they can be deleted unlike proper lexical variables. Note that the behaviours of eval will change if strict mode is used.

Variable scope. In JavaScript, variables declared by var are scoped by closures, not by blocks. In particular, variables declared in a block can overwrite a global variable. This feature may confuse programmers familiar with languages such as C++ and Java, where variables are scoped by blocks.
var name = "Joe";
if(true) { var name = "Jack" }        // name is "Jack" now
(function() { var name = "Joe" })()  // name is still "Jack"
One therefore has to use a closure to declare a genuine local variable. The let keyword introduced in ECMA 6 declares block-scoped variables and helps avoid this pitfall.

Binding vs assignment. In most imperative languages including JavaScript, variable declaration creates a reference to a mutable value. In the following example, variable i enclosed in the anonymous function points to a value which is mutated by further iterations of the loop.
for (var i=0; i<3; ++i) {
  if(i==1) setTimeout(function (){ console.log(i) }, 1000);
}// prints 3
To capture the value of i at creation time, we can exploit a feature of JavaScript that functions are called by value when the parameters are of primitive types. In the following, the value of i is copied to parameter j when the anonymous function is created. Thus the value of i is captured as expected.
for (var i=0; i<3; ++i) {
  if(i==1) setTimeout((function (j){ 
      return function (){ console.log(j) }
  })(i), 1000);
}// prints 1
In general, binding creates a new variable within the current context, while assignment changes the value of an existing variable within the narrowest scope. In languages such as SML and Go, you can use different syntactic rules to choose between binding and assignment. In JavaScript, the "=" symbol always denotes an assignment. One however can bind a variable through a call-by-value function parameter, as is shown in above example.

Function declaration. When a JavaScript program executes, it runs with context (variable bindings, call stack, etc) and process (statements to be invoked in sequence). Declarations contribute to the context when the execution scope is entered. They are different from statements and are not subject to the order in which statements are invoked. In the following example, function foo is returned even though the code that defines it is unreachable at runtime:
(function (){
  return foo; function foo(){} 
})();
In ES5, function declarations are forbidden within non-function blocks (such as an if block). However, all browsers allow them and interpret them in different ways. For example, consider
(function (){
  if(false) { function foo(){} } return foo;
})();
In Firefox, the function declaration is interpreted as a statement. Thus foo is not defined when it is returned, which would cause a runtime error. In IE, Chrome and Safari, however, the function is returned as expected with standard function declarations.

Declaration hoist. In JavaScript, declarations of functions and variables are hoisted (moved) to the beginning of their innermost enclosing scope. Note that it is the declaration that got hoisted, not the assignment expressions. In the following example, the global variable x is shadowed by the local one due to declaration hoist.
var x = 0;
(function (){ 
  console.log(x);
  var x = 1;
})() // prints "undefined"
equals
to
var x = 0;
(function (){
  var x;
  console.log(x);
  x = 1;
})() // prints "undefined" 
When a function declaration is hoisted, the entire function definition is lifted with it. The following example shows an interested consequence of the difference between hoisting variable declaration and function declaration:
(function (){
  function foo() { return 0 }
  return foo();
  function foo() { return 1 }
})(); // returns 1
(function (){
  var foo = function (){ return 0 }
  return foo();
  var foo = function (){ return 1 }
})(); // returns 0
In the left snippet, the definition of the second foo is hoisted and thus shadows that of the first foo. In the right snippet, only the declaration of the second foo is hoisted, and this doesn't change the result of the first assignment. See also the "function declaration" paragraph.

Array allocation. JavaScript arrays should be treated as a special hash table. When you initialize an array with a statement like var a = new Array(10), you don't allocate a memory of 10 cells as you do in Java and C++. Instead, you create an Array object with length property of value 10. You can use any type of keys to store any type of values in an array, e.g., a[-1] = 1, a["fruit"] = "apple", etc. The length property of an array is updated automatically to accommodate the largest non-negative integer key of its contained values. Whatever the keys are, an array traversal only visit the values with non-negative integer keys explicitly assigned, as is shown in this code: (see this thread for more details)
var a = new Array();
a[-1] = a["a"] = a[11] = 1;
console.log(a.length); // prints 12
// Map traversal: visit all keys ever set
for(var key in a) { if(a.hasOwnProperty(key) console.log(key + ': ' + a[key]) }
// Array traversal: visit all valid array indices
a.forEach(function (val, index){ console.log(index + ': ' + val) }) // prints "11: 1"
To actual allocate a memory block of 10 cells, use Array.apply(null, Array(10)). To assign initial values to an array, use either this trick or utility functions such as _.range of underscore.js.

Trailing comma. ES3 does not allow a trailing comma when defining an object literal. For example, we should write {foo1:"bar1",foo2:"bar2"} instead of {foo1:"bar1",foo2:"bar2",}. However, most browsers (except IE) go against the spec and allow both usages. ES5 resolved this issue by going with the majority and legitimizing the trailing comma in the spec. Note that a trailing comma is still not allowed in JSON according to ES5. Thus '{foo:"bar",}' does not represent a valid JSON object.

Non-commutative operators. Check this table for a detailed list of the surprising behaviors of operators +, *, == and ===. These behaviors result from JavaScript's eccentric type coercion rules. One can make use of these coercion rules to write extremely puzzling code, see this script for instance. If you are not that familiar with these rules, be extremely careful when you have to do arithmetic operations over objects of different types.

Discrete floating point. Numbers in JavaScript are internally stored in double-precision floating-point format. Hence, not all numbers can be exactly represented, even for those falling in the seeming reasonable range. For example,
var x = 9999999999999999;   // x == 10000000000000000
var eq = (.3 == .1 + .2);   // eq is false because .1 + .2 == .30000000000000004
If you need to check equality between numbers, you have to take relative error into account, e.g.:
function eq(x, y) { // x and y are numbers
  return (x==y) || (!(x>0)^(y>0) && Math.abs(x - y) < Number.EPSILON) 
}

(more to come in the future)

Wednesday, November 13, 2013

ECMAScript 5.1 Spec

The official specification: the HTML version

Some annotated versions: Version 1, Version 2 (in the same format as above)

JavaScript: The Definitive Guide: PDF

Thursday, October 31, 2013

The OOP Enssences in JavaScript

Instantization

// The following code shows how Firefox implements the "new" operator
function Point(x, y){ 
    this.x = x; this.y = y;
}
function ObjectFactory(){
    var obj = {};
    var Constructor = Array.prototype.shift.call( arguments );
    if(typeof Constructor.prototype === 'number')
        obj.__proto__ =  Object.prototype;
    else
        obj.__proto__ =  Constructor.prototype;
    var ret = Constructor.apply(obj, arguments);
    return typeof ret === 'object' ? ret : obj;
}

// This is equivalent to: var p = new Point(0, 0);
var p = ObjectFactory(Point, 0, 0);

Inheritance

// The following code is generated by CoffeeScript to 
// implement subclass inheritance
var __extends = function(child, parent) {
    for (var key in parent) {
      if (Object.prototype.hasOwnProperty.call(parent, key)) {
        child[key] = parent[key];
      }
    }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
};

// Our code
var Person = function(name) {
    console.log('Hi, I am ' + name + '!'); 
    this.name = function(){ return name };
};
var Student = function() {
    Student.__super__.constructor.apply(this, arguments);
};
__extends(Student, Person);    // make Student a subclass of Person
var me = new Student('Eric');  // "Hi, I am Eric!"
console.log(me.name());        // "Eric"

Wednesday, October 30, 2013

Seeded PRNG in JavaScript

Below is a multiply-with-carry (MWC) random generator with a pretty long period, adapted from wikipedia Random Number Generators:
// Takes any integer
Math.seed = function(s) {
    var m_w = s;
    var m_z = 987654321;
    var mask = 0xffffffff;
    return function() 
    // Returns number between 0 (inclusive) and 1.0 (exclusive),
    // just like Math.random().
    {
        m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;
        m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;
        var result = ((m_z << 16) + m_w) & mask;
        result /= 4294967296;
        return result + 0.5;
    }
}
Another fast and simple PRNG, without magic numbers:
Math.seed = function(s) {
    return function() {
        s = Math.sin(s) * 10000;
        return s - Math.floor(s);
    };
};
You can replace the default PRNG of JavaScript by, e.g.,
Math.random = Math.seed(Math.round(Math.seed(42)*10000));

Reference

1. http://stackoverflow.com/questions/521295/javascript-random-seeds/521323
2. https://github.com/davidbau/seedrandom

Monday, October 28, 2013

Lo-Dash v.s. Underscore

A breakdown of the advantages of Lo-Dash over Underscore:
http://kitcambridge.be/blog/say-hello-to-lo-dash/

The creator of Lo-Dash explain why it is a superior choice to Underscore:
http://stackoverflow.com/questions/13789618/differences-between-lodash-and-underscore

Lo-Dash v.s. Underscore benchmarks: http://jsperf.com/lodash-underscore

One may wonder that, since Lo-Dash is intended to be a superset compatible to Underscore from the beginning of design, why not contribute to Underscore directly, e.g. by merging the new features back into Underscore, instead of developing a new library? This thread in GitHub may serve as an answer to the question.