Archive

Archive for the ‘JavaScript’ Category

Don’t use this in JavaScript

April 28, 2012 7 comments

this JavaScript:

var o = {
    f1: function() {
        console.log('hi');
    },
    f2: function() {
        this.f1();
    }
};

o.f2.prototype.f1 = function() {
    console.log('bye');
}

var k = {
    f1: function() {
        console.log('pfff');
    }
}

new o.f2();
o.f2.apply(k);
o.f2();
var x = o.f2;
x();

There. That’s why I never use the this keyword in JavaScript.
And that’s why I think you should stop using it too.
Can you figure out what’s the output of this code?

Read more…

Testing events on jQuery objects with Jasmine

January 10, 2011 5 comments

Recently we had a piece of JavaScript code that looked roughly like this:

myApp.buttonBinder = {
  bind: function(button) {
    if (myApp.shouldChangeButtonAction()) {
      button.unbind("click").click(function() {
        button.closest("form").submit();
      });
    }
  }
}

So we wanted to test this using Jasmine.
Our main goal was to test that when the button was clicked the form that contains it was being submitted.
It would be cool if we could use Jasmine’s spies:

describe("myApp.buttonBinder", function() {
  it("should bind form submit to button", function() {
    var form = $("<form/>");
    var button = $("<input/>");
    form.append(button);
    spyOn(form, 'submit');

    myApp.buttonBinder.bind(button);
    button.click();

    expect(form.submit).toHaveBeenCalled();
  });
});

But unfortunately this does not work. I didn’t look too much into it, but I suspect it is due to the fact that when the actual code runs, the jQuery ‘closest’ selector creates a new form object that represents the same DOM element. But as it is a different object the spy can’t recognize that the function submit has been called.
One idea is to instead add a listener to the form’s submit event and check if this listener has been called:

describe("myApp.buttonBinder", function() {
  it("should bind form submit to button", function() {
    var form = $("<form/>");
    var button = $("<input/>");
    form.append(button);
    var formHasBeenSubmitted = false;
    form.submit(function() {
      formHasBeenSubmitted = true;
    });

    myApp.buttonBinder.bind(button);
    button.click();

    expect(formHasBeenSubmitted).toBeTruthy();
  });
});

And voilá! This works!
But it looks terrible, doesn’t it?
Good thing Jasmine lets us extend itself, so we can create a new spy function and a new custom matchers:

// SpecHelper.js
var jasmineExtensions = {
  jQuerySpies: {},
  spyOnEvent: function(element, eventName) {
    var control = {
      triggered: false
    };
    element.bind(eventName, function() {
      control.triggered = true;
    });
    jasmineExtensions.jQuerySpies[element[eventName]] = control;
  };
};

var spyOnEvent = jasmineExtensions.spyOnEvent;

beforeEach(function() {
  this.addMatchers({
    toHaveBeenTriggered: function() {
      var control = jasmineExtensions.jQuerySpies[this.actual];
      return control.triggered;
    }
  });
});

And now our test looks like this:

describe("myApp.buttonBinder", function() {
  it("should bind form submit to button", function() {
    var form = $("<form/>");
    var button = $("<input/>");
    form.append(button);
    spyOnEvent(form, 'submit');

    myApp.buttonBinder.bind(button);
    button.click();

    expect(form.submit).toHaveBeenTriggered();
  });
});

Much better \o/

Go learn JavaScript!

December 8, 2010 14 comments


This post comes late, as I have realized this late myself.
But it is not late enough to be useless, because most developers out there still haven’t learned JavaScript.

If you work with development of some sort, big chances are you work with web development.
If you work with web development, regardless of the technology stack – be it Java, .NET, Ruby, Python, Perl or Brainfuck – your application runs on a browser, and all browsers run JavaScript, so you can’t escape from it. *

That said, once you have learned JavaScript, you will find out that programming in JavaScript is actually fun!
I have gone through this myself as I have seen colleagues going through this too.
Not only you will find out it is fun, you will see how JavaScript is a powerful language that has lots of good things that you will start to wish other languages also had.

Most important of all: your JavaScript code will start to look good.
And once all developers in your team have learned that learning JavaScript is not only important, but necessary, your project’s JavaScript codebase will stop looking horrendous as it does nowadays. It will look good, modularized and testable. And you won’t ever again go “Oh crap, I have to touch JavaScript in this story…”.

Wait, did I say testable? Yes, I did! You can actually TDD your JavaScript code as well as you can TDD your <favorite language> code.
For that I recommend Jasmine, have been using it in our project, love it.
You can even combine Jasmine with Rhino or WebDriver and add your JavaScript tests to your Continuous Integration pipeline. (Your project has a CI server, right?!)

And you know what? Learning JavaScript is EASY!
I believe most developers familiar with any OO language wouldn’t need more than a couple of days to start writing more than decent JavaScript code.
There’s plenty of good websites and books out there for you to learn it, so go on and have fun!

* Ok, actually, you can escape from writing JavaScript.
You could go with GWT for instance. And I remember there were other frameworks that let you develop the whole fancy UI on Java on the server side, sending only few instructions to the client – I can’t recall any names right now.
The thing is: is it worth it?
I worked with GWT for a considerable time in 2009 and, now that I have had more JavaScript experience, I definitely wouldn’t go back to GWT. It just seems like a lot more work to do, not to mention the messy HTML and CSSs it generates.
If you’d like to have your JavaScript compiled from something else, take a look at CoffeeScript ;)

Follow

Get every new post delivered to your Inbox.