Search

1/09/2012

The Little Book on CoffeeScript - Idioms

The Little Book on CoffeeScript - Idioms

each:
myFunction(item) for item in array

map:
result = (item.name for item in list) // Notice we're surrounding the comprehension with parens, which is absolutely critical in ensuring the comprehension returns what you'd expect, the mapped array.

select:
result = (item for item in list when item.name = 'name') //Don't forgot to include the parens, as otherwise result will be the last item in the array.

includes:
included = "test" in array

compiled to:

var included;
var __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (this[i] === item) return i;
}
return -1;
};
included = __indexOf.call(array, "test") >= 0;


Property iteration:
However, as you've seen in the previous section, CoffeeScript has already reserved in for use with arrays. Instead, the operator has been renamed of, and can be used like thus:
object = {one: 1, two: 2}
alert("#{key} = #{value}") for key, value of object


And/or:
One extremely nice addition to CoffeeScript is the 'or equals', which is a pattern Rubyists may recognize as ||=:

hash or= {}

compiled to:

hash || (hash = {});


hash ?= {}
compiled to:

if (typeof hash === "undefined" || hash === null) {
hash = {};
}


Destructuring assignments
someObject = { a: 'value for a', b: 'value for b' }
{ a, b } = someObject
console.log "a is '#{a}', b is '#{b}'"

compiled to:

var a, b, someObject;
someObject = {
a: 'value for a',
b: 'value for b'
};
a = someObject.a, b = someObject.b;
console.log("a is '" + a + "', b is '" + b + "'");


Private variables

type = do ->
type = ->

compiled to

var type;
type = (function() {})();
type = function() {};


The do keyword in CoffeeScript lets us execute functions immediately, a great way of encapsulating scope & protecting variables. In the example below, we're defining a variable classToType in the context of an anonymous function which's immediately called by do. That anonymous function returns a second anonymous function, which will be ultimate value of type. Since classToType is defined in a context that no reference is kept to, it can't be accessed outside that scope.

# Execute function immediately
type = do ->
classToType = {}
for name in "Boolean Number String Function Array Date RegExp Undefined Null".split(" ")
classToType["[object " + name + "]"] = name.toLowerCase()

# Return a function
(obj) ->
strType = Object::toString.call(obj)
classToType[strType] or "object"

compiled to:

var type;
type = (function() {
var classToType, name, _i, _len, _ref;
classToType = {};
_ref = "Boolean Number String Function Array Date RegExp Undefined Null".split(" ");
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
name = _ref[_i];
classToType["[object " + name + "]"] = name.toLowerCase();
}
return function(obj) {
var strType;
strType = Object.prototype.toString.call(obj);
return classToType[strType] || "object";
};
})();

沒有留言: