Skip to content

Instantly share code, notes, and snippets.

@HenrikJoreteg
Created October 22, 2010 21:20
Show Gist options
  • Star 74 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save HenrikJoreteg/641397 to your computer and use it in GitHub Desktop.
Save HenrikJoreteg/641397 to your computer and use it in GitHub Desktop.
Rather than creating some other util global, just extend underscore.js with any additional methods you want.
// If you don't use underscore.js, use it (http://documentcloud.github.com/underscore/)
// Then, use underscore's mixin method to extend it with all your other utility methods
// like so:
_.mixin({
escapeHtml: function () {
return this.replace(/&/g,'&')
.replace(/>/g,'>')
.replace(/</g,'&lt;')
.replace(/"/g,'&quot;')
.replace(/'/g,'&#39;');
},
otherFunc: function () {
// etc, etc.
}
});
// simple. but. handy.
@mattd
Copy link

mattd commented Oct 27, 2010

This is a flipping great idea.

@HenrikJoreteg
Copy link
Author

Thanks matt!

@ssoroka
Copy link

ssoroka commented Oct 30, 2010

I don't think replace is the right method there? It doesn't seem to work for me.

Also, that only lets you use the _.escapeHtml('<tag>') style, not the _('<tag>').escapeHtml() object style. To do that, you need to call:

_.mixin(_);

@HenrikJoreteg
Copy link
Author

Ah... good call. I should be using 'mixin' instead of 'extend'. That way it supports the OOP style. Will fix that.

@millermedeiros
Copy link

what if someone else inherits the project after a couple months? what if underscore.js add new methods with the same names but works differently? what if you need the same functions on another project that doesn't use underscore.js?

I would avoid extending any object that I don't own: http://blog.millermedeiros.com/2010/08/stop-writing-plugins-start-writing-components/

cheers.

@HenrikJoreteg
Copy link
Author

What I'm proposing in this gist is using underscore as the tool for storing and using utility methods and using _ as the global accessor to these methods. Obviously if you decide not to use underscore, then this approach is completely irrelevant. That seems like a self-evident observation, don't you think?

I prefer a unified api for accessing and using utility methods and this gives me that. So I don't have to have track a bunch of independent little modules. I don't want to "own" every piece of code I use because then I have to million little modules, all in the name of reuse. In my opinion the end goal is to save time. Maintaining too much code is not efficient use of time as a developer. My approach is to find the best tool for the job and use it until it's no longer the best tool for the job.

Not to mention, say I have a bunch of code that expects the _ character to store utility methods. That doesn't mean I'm stuck using underscore.js. All I'd have to do is change the first line from: _.mixin(_, { to var _ = { ... done! Why is that a problem?

@millermedeiros
Copy link

the problem is that you are adding functionalities that aren't present on underscore.js by default and that could lead to confusion and incompatible code. modules should be self-contained and depend as less as possible on external code.

I'm just saying that since I got to this gist coming from your article about backbone.js as a good way to structure the code, and I don't think that extending an object you don't own is a good idea for scalable/maintainable applications (not that it is a big deal in most of the cases).

presentation about maintanable JavaScript (special detail to slide 16) and scalable JavaScript application

cheers.

@muescha
Copy link

muescha commented Nov 20, 2010

maybe a seperate namespace for extensions would be nicer (and better to maintenence after an update) like MM mentioned:

_.ext.myname.myfunction()

_.com.mydomainname.myfunction()

@HenrikJoreteg
Copy link
Author

@muescha, you're missing the point, my friend. The whole reason I like doing it with underscore is that it keeps your code clean. Obviously you could store your utility functions wherever you want and generally namespacing an app is a good idea. However, the whole point is I can use a simple utility function by doing something like this:

_.myFunction()

Instead of the Java class naming you suggest (which frankly, gives me a headache).

Also, underscore lets you use the OOP style so you can also call it like this:

_({my: 'object'}).myFunction(my, other, args);

Which would look downright ugly with big namespaces.

@ssoroka
Copy link

ssoroka commented Nov 22, 2010

Maybe all you need is an easy way to add the OOP style to your own namespaces.

@mordendk
Copy link

There's absolutely nothing wrong with this approach. As HenrikJoreteg already mentions, you can still keep you own code structured and namespaced anyway you like. For instance if your namespacing your code using object literals a simple line could extend methods to underscore.js for convenience - ie.

_.mixin( MY.Namespace.Utils );
or whatever.

It's also common approach to jQuerys prototype to

$.fn.extend({ // something.. });
so you can utilize
$(obj).myFunction().chaining().forInstance();

@millermedeiros
Copy link

It is very easy to create chaining in JavaScript, be it for an existing object or creating it from scratch (gist), that is not a valid reason for polluting a namespace you don't own, if you want a detailed explanation read this blog post.

I really believe that extending underscore/jQuery/etc is the wrong approach in most cases, if you don't agree read Zackas post again..

You don't need to follow the Java namespacing approach to avoid collisions, if you use a module loader like RequireJS you don't even need to create global variables in most cases (not even for your helper modules) and your code can be organized on a sane structure.

PS: each Object/Class/Function should have a single responsibility and this approach defeats this principle.

@stephenhandley
Copy link

__.myFunction()

@findzen
Copy link

findzen commented May 1, 2012

+1 for __.myFunction()

@millermedeiros
Copy link

BTW, I created a library with many utility functions (similar to the ones present on underscore) but instead of adding every single method inside the same "namespace" we have individual modules for each method - so you can load only what you need or a full package at once - and since it's written in the AMD format it doesn't pollute the global namespace. IMHO that is a better approach and also way more scalable since we can add more methods to the lib without worrying about file size... The era of a single global namespace is definitely over to me, AMD is the future.

@krunkosaurus
Copy link

This is an old post, but just an fyi that backbone uses underscore and has an escape feature. I checked the backbone source and it uses the escape function from underscore:

_.escape = function(string) {
return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(///g,'/');
};

So this mixin is no longer needed.

Also what's this nonsense from @millermedeiros on not extending objects you don't own? I understand why its horrible to extend the native DOM, but libraries like underscore and jQuery were made to be extended. In your uncompressed javascript source files you actually place the additional plugins or "mixins" under to signify that they are additions. Even as a new developer on a project, it makes complete sense.

@jdalton
Copy link

jdalton commented Sep 15, 2012

Yap, @krunkasaurus (lol, I love the name) is right, Underscore already has _.escape and the edge version has _.unescape too.

You can also use Lo-Dash, a drop-in replacement for Underscore delivering performance, bug fixes, and additional features to make a custom build and embed it directly in your project like (BonsaiJS)[http://bonsaijs.org/].

@kjantzer
Copy link

perfect! just what I was looking for. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment