Skip to content

Transitioning from Underscore.js

Sammy Jelin edited this page Jan 11, 2014 · 11 revisions

We do not use underscore.js. Instead, we use built in JavaScript functions and write a small handful of our own. In this page, we describe our alternatives to using underscore.js

Why not use underscore.js though?

A major design goal in underscore.js was that it not extend any existing JavaScript objects. This makes sense for underscore.js, because it is used by many developers in many different contexts, and some of those developers might not be OK with extending the existing JavaScript classes. However, it has some nasty consequences.

For instance, underscore.js has a function _.bind, which is basically identical to the built in function Function.prototype.bind. underscore.js has to write a version of the .bind function because old browsers don't have native support. And if can't simply detect if native support already exists and gracefully upgrade to the native implementation if possible, because that would be extending existing JavaScript objects. The result is that with underscore.js you have to write _.bind(f, obj) instead of the more modern (and more efficient) f.bind(obj).

Since we are only writing code for ourselves, we do not need to worry about the dangers of extending existing objects.

underscore.js functions and their alternatives

Note: Not every underscore.js function has a direct alternative in our style. In these cases, the alternatives is generally just a combination of two functions. If you feel that some function from underscore.js was extremely useful, and we are not currently providing a direct alternative, feel free to make the alternative yourself (preferably by extending existing JavaScript object). In the mean time, we provide code for how the the alternatives can be created.

Collection Functions

Use Array.prototype.each, which is equivalent to the native function Array.prototype.forEach, or $.each.

So _.each(array, fun) becomes array.each(fun)

Use the native function Array.prototype.map.

So _.map(array, fun) becomes array.map(fun)

Use the native function Array.prototype.reduce.

So _.reduce(array, fun, init) becomes array.reduce(fun, init)

Use the native function Array.prototype.reduceRight.

So _.reduceRight(array, fun, init) becomes array.reduceRight(fun, init)

No direct alternative. Use array.filter(fun)[0] instead of _.find(array, fun)

Use the native function Array.prototype.filter.

So _.filter(array, fun) becomes array.filter(fun)

No direct alternative. Use Array.prototype.filter and just create an anonymous function to check the desired properties.

See the alternative to _.where and _.find

No direct alternative. Use array.filter(op.not.o(fun)) instead of _.reject(array, fun)

Use the native function Array.prototype.every.

So _.every(array, fun) becomes array.every(fun)

Use the native function Array.prototype.some.

So _.some(array, fun) becomes array.some(fun)

No direct alternative. Use Array.prototype.map

So _.invoke(list, funName) becomes list.map(eval(funName))

No direct alternative. Use array.map(op.get.C($, 'prop')) instead of _.pluck(array, 'prop')

Use Array.prototype.max.

So _.max(array) becomes array.max()

Use Array.prototype.min.

So _.min(array) becomes array.min()

Use the native function Array.prototype.sort, though it is not quite the same thing.

No direct alternative.

No direct alternative.

No direct alternative.

No direct alternative.

No direct alternative.

Use $.makeArray

So _.toArray(obj) becomes $.makeArray(obj)

No direct alternative, but Object.keys(obj).length is roughly equivalent

Array Functions

Please use array[0] instead of _.first(array)

Please use Array.prototype.slice.

So _.initial(array, n) becomes array.slice(0, n)

Please use array[array.length-1] instead of _.last(array)

Please use Array.prototype.slice.

So _.rest(array) becomes array.slice(1)

Please use Array.prototype.filter.

So _.compact(array) becomes array.filter(op.id)

No direct alternative

No direct alternative. Please use Array.prototype.filter.

No direct alternative. Use $.merge, though it is not quite the same thing.

No direct alternative

No direct alternative

No direct alternative

No direct alternative

No direct alternative

Please use Array.prototype.indexOf or $.inArray

So _.indexOf(array, x) becomes array.indexOf(x)

Please use Array.prototype.lastIndexOf.

So _.lastIndexOf(array, x) becomes array.lastIndexOf(x)

No direct alternative

Not really the same thing, but you could use Array.tabulate

Function Functions

Use the native function Function.prototype.bind.

So _.bind(fun, x) becomes fun.bind(x)

No direct alternative

Use Function.prototype.c

So _.partial(fun, x) becomes fun.c(x)

No direct alternative

Use the native function setTimeout

So _.delay(fun, wait) becomes setTimeout(fun, wait)

Use the native function setTimeout with a wait of 0

So _.defer(fun) becomes setTimeout(fun, 0)

No direct alternative

No direct alternative

No direct alternative

No direct alternative

No direct alternative. Use f.c(g) instead of _.wrap(f, g)

Use Function.prototype.o

So _.compose(f, g) becomes f.o(g)

Object Functions

Use the native function Object.keys

So _.keys(obj) becomes Object.keys(obj)

No direct alternative. Use Object.keys(obj).map(op.get.c(obj) instead of _.values(obj)

No direct alternative.

No direct alternative.

No direct alternative. Use Object.keys(obj).filter(function(k) {return obj[k] instanceof Function;}) instead of _.functions(obj)

Use $.extend

So obj1 = _.extend(obj1, obj2) becomes $.extend(obj1, obj2)

No direct alternative.

No direct alternative.

Use $.extend, but reverse the order

No direct alternative. Use $.extend(Array.isArray(obj) ? [] : {}, obj) instead of _.clone(obj)

Not applicable.

Use the native function Object.prototype.hasOwnProperty

So _.has(obj, prop) becomes obj.hasOwnProperty(prop)

No direct alternative.

Use $.isEmptyObject

So _.isEmpty(obj) becomes $.isEmptyObject(obj)

No direct alternative.

Use the native method Array.isArray

So _.isArray(array) becomes Array.isArray(array)

Use the typeof operator.

So _.isObject(x) becomes typeof x == "object"

No direct alternative. Use x.toString() == [object Arguments] instead of _.isArguments(x)

Use $.isFunction

So _.isFunction(obj) becomes $.isFunction(obj)

Use $.type

So _.isString(x) becomes $.type(x) == "string"

Use $.isNumeric

So _.isNumber(x) becomes $.isNumeric(x)

No direct alternative.

Use the typeof operator.

So _.isBoolean(x) becomes typeof x == "boolean"

Use $.type

So _.isDate(x) becomes $.type(x) == "date"

Use $.type

So _.isRegExp(x) becomes $.type(x) == "regexp"

Use the native function isNaN, though it is not quite the same thing. In the future, you might be able to use Number.isNaN, which is more similar.

So _.isNaN(x) becomes isNaN(x)

Use the native operator ===.

So _.isNull(x) becomes x === null

Use the native operator ===.

So _.isUndefined(x) becomes x === undedined

Utility Functions

Not applicable.

Use op.id

So _.identity(x) becomes op.id(x)

No direct alternative.

Use Math.random

So _.random(min, max) becomes Math.random()*(max-min+1)|0 + min

Not applicable.

No direct alternative.

Use the native function encodeURI

So _.escape(str) becomes encodeURI(str)

Use the native function decodeURI

So _.unescape(str) becomes decodeURI(str)

No direct alternative.

We have our own internal templating engine.