Copy all but some properties of an object in ES6

Since I started playing with ES6 about half a year ago I really came to love the new syntax, as it provides a much more python-ish feel to Javascript development.

One of the functions I like the most is the awesome Object.assign().

You can use it for all sorts of things:

const oldObject = { foo: 'bar', baz: 42 };
// (shallow) copy an object
const newObject = Object.assign({}, oldObject);
// overwrite some values
const overwritten = Object.assign({}, oldObject, { foo: 'fighters' });
// overwritten is { foo: 'fighters', baz: 42 }
// merge objects
const other = { luftballons: 99 };
const merged = Object.assign({}, oldObject, other);
// merged is { foo: 'bar', baz: 42, luftballons: 99 }

and more awesomeness that you can find, as always, on the MDN site.

One thing that I found out today that made my day better is that you can use Object.assign() to copy an object except for some of its properties.

const oldObject = { foo: 'bar', baz: 42 };
const noFoo = Object.assign({}, oldObject, { foo: undefined });
// noFoo is { baz: 42 }

As easy as that!

I find myself doing this kind of operation quite often, namely when I decorate some object generated from JSON retrieved from a server and want to send it back after changing it client-side. This syntax makes it oh-so-simple!

Fix out of sync subtitles with Angular

In what seems to be a never ending series of posts on how to fix out of sync subtitles… here’s how to do it using Angular! 🙂

First things first: here’s a link to the webpage that you can use to fix your out of sync subtitles. Just go there and follow the instructions, it’s really easy. Trust me, I’m the author 😛

A little background on why I made that page. About a year and a half ago I started toying around with AngularJS, because we decided to re-write the SketchTogether HTML client in it. Since I’m mostly taking care of the server side of the app, I spent a lot more time reading Angular code than writing it; even if I think I got the basic concepts relatively quickly, I wanted to have some first-hand experience with the library to really grasp what it means to develop an app with it, even if just a basic one.

Since back in those days I was fiddling with a toy python script to fix out of sync subtitles, I decided that it could have been fun to do the same thing in Angular. I wrote a rough implementation of the script’s functionality in about two weeks of my off time (about 10 very fragmented hours all in all, and I must say I was happy with it, considering how Angular is known for its steep learning curve), and left it there. Fast forward to 4 months ago, I decided to make it look a little prettier, and publish it on GitHub. And then, it took me 4 more months to find the time to write this blog post about it on a Sunday night 😛

My experience with Angular so far has been positive. For one thing, it’s not as hard to create a non-trivial webpage with it as most people want you to believe. Data binding can get you pretty far, and it’s relatively straightforward (one basic thing that left me wondering though is the from-dashed-to-camelCase directive name auto-conversion… that felt a bit like unneeded magic to me).

It does get a bit convoluted when your application grows and you want to add some piece of functionality that’s like 4 lines of code in jQuery, but which takes a new directive definition, changes to the HTML, and maybe a new scope, just to follow the Angular way. But then again, it could be my limited knowledge of the library (which I intend to keep expanding, because there’s so much to learn!).

As with most things Javascript, there tends to be an oversupply of sub-libraries to do pretty much anything. For subslider.js, for example, I found a lot of angular plugins to take care of pagination, with no clear winner. The same applies for drag-and-drop support (which in the end was implemented as a directive in the app). It really takes some time to simply understand which of the many plugins suits you best… just look at how many plugins are listed by ngmodules!

Oh, and one last thing. The “there should be a dot in your model” rule should be re-stated everywhere in the documentation. Once you really understand what it is about, you experience one of the major bumps in the famous “feelings about angular over time” graph from this post 🙂

Logging in Javascript and filtering by tag

I’m not a fan of loggers in general when it comes to simplicity. They all require you to spend (waste) some time on understanding their configuration syntax, maybe dealing with XML files (what am I, a caveman? :P), and they often require you to adapt to their philosophy. By that I mean, there’s plenty of questions on StackOverflow similar to this, and I definitely share this guy‘s feeling about the issue.

In Javascript, I’ve seen some libraries for logging, and they all look quite complicated to set up. Or, quite complicated considering it’s Javascript we’re talking about. JSLog doesn’t require that much configuration, but most of the times I don’t even care about log levels in JS “apps”, I just want to filter messages according to their context. So I may be interested in all ajax-related logs at some point, but not in DOM manipulation messages. At some other time, I may be interested in DOM manipulation logs, but not in ajax-related messages. These can be though of as log tags (the “DOM” tag, the “ajax” tag, the “user-input” tag, and so on).

A quick and dirty way to deal with all of this is to define some Log functions named after the “context” in which they’re called, and assign them to a no-op function when you want to filter them out.

In Chrome, these could be the log functions (let’s say they’re stored in log.js):

function Log() {
}

Log.message = function(message) {
    console.log(message);
};

Log.dom = Log.ajax = Log.message;

Then, throughout your code, you may have calls like:

Log.dom('adding sidebar');
// in some other place...
Log.ajax('new msg received from server');

All you need to do to disable e.g., all ajax logs, is just change the Log.ajax function to a no-op in log.js, like this:

Log.ajax = function(){};

you can even do it live using the Chrome Developer Tools!

So a question could be: aren’t those calls to a no-op function expensive? Javascript function calls are expensive, right? Why not add a flag like this:

if (logAjaxEnabled) {
   Log.ajax('new msg received from server');
}

to all log calls?

Well, it’s a pain to add all those checks, that’s why 🙂

And your mileage may vary, but in all browsers I’ve tested, calling a no-op is not that bad. It’s way worse than using the flag, but it’s in the same ballpark (assuming you’re not writing some very CPU intensive code), and it’s WAY less painful to use, cause you don’t need to write all those if statements.

I put together a dumb benchmark on JSPerf to see what’s the performance drawback for using this method, you can try it!

It’s also interesting to note how browser performances for something like this vary that wildly.. ah, the JS world!

I’m sure I’m not discovering anything here (I mean, just look at the first few links for a simple Google query like this), but I haven’t seen this approach being used that much (filtering by context, and not by log level). It’s something very close to what Android’s LogCat does, and I really like it!