Q:

Fabric.js - Unable to set properties dynamically

I am trying to set the direction dynamically but something is not working.  I do not get an error.  
function moveSelection(keyPressed) {
    var group = canvas.getActiveGroup(),
    obj = canvas.getActiveObject();

    if(!group && ! obj) {return;}

    var direction = '',
        sign = '',
        operators = {
            '+': function(a, b) { return a + b },
            '-': function(a, b) { return a - b },
        };
    switch(keyPressed) {
        case 37:
            direction = 'left';
            sign = '-';
        break;
        case 38:
            direction = 'top';
            sign = '-';
        break;
        case 39:
            direction = 'right';
            sign = '+';
        break;
        case 40:
            direction = 'bottom';
            sign = '+';
        break;
    }

    if(group){
        group.set({
            direction : operators[sign](group.get(direction), 1)
        });
        canvas.renderAll();
    } else {
      obj.set({
        direction : operators[sign]( obj.get(direction),1 )
      });
      canvas.renderAll();
    }
}

But when i change the code to the following then it works fine.. What is wrong?  Thank you:
obj.set({
    'left' : operators[sign]( obj.get(direction),1 )
});

A:

TLDR
Use obj.set(direction, ...). 
But why? 
I've been bitten by this few times myself.  Even after knowing that it's not supposed to work :)
But this is how Javascript works:
In your snippet, the "direction" in object literal is interpreted as "direction" property:
obj.set({
  direction : operators[sign]( obj.get(direction),1 )
});

just like foo in this object literal:
var foo = 'x';
var obj = { foo: 'bar' };

creates a property named "foo" rather than property named "x" (which foo variable "contains"). 
It might seem a little weird, since you're not writing:
var obj = { 'foo': 'bar' };

where foo is written as a string literal rather than an identifier.  But to Javascript (up to ECMAScript 5), it doesn't really matter.  The only difference is that using identifier notation, you can only represent properties that are also valid... identifiers. 
So these, for example, are invalid as identifiers:
{
  'foo-bar': 'baz',
  '5leafs': 123,
  'or.with': 'dots'
}

which is why we have to write them as string literals. 
This confusion might also come from the fact that bracket notation in Javascript does allow to create dynamic properties:
var foo = 'x', obj = { };
obj[foo] = 'bar';

This creates a property named "x" rather than "foo".  Whereas if we performed assignment via dot notation:
obj.foo = 'bar';

it would create a property named "foo". 
So this is, arguably, Javascript limitation, since we can't have both object literals AND dynamically-evaluated properties:
obj.foo         // does NOT evaluate
obj[foo]        // evaluates

({ foo: ... })  // does NOT evaluate
?                // evaluates

So why did I mention ECMAScript 5 before? 
Because in ECMAScript 6 (an upcoming standard), we're likely to have so-called "computed property names", where you'll be able to dynamically evaluate property name in an object literal like so:
var foo = 'x';
var obj = { [foo]: 'bar' };

obj.foo; // undefined
obj.x; // 'bar'

I'm really looking forward to this one.