Javascript Object keys cannot be Objects

TL;DR – Javascript Object keys may be strings or symbols, and nothing else. So be careful when setting key/value pairs on an Object.

In Javascript, if you use an Object as another Object‘s key, you will have problems. You will not see an error, but you will be producing a bug. I ran this code sample in the node REPL to demonstrate what goes wrong.

First, I create two completely different Objects, obj1 and obj2:

> var obj1 = { a : "a" };

> var obj2 = { b : "b" };

> obj1
{ a: 'a' }
> obj2
{ b: 'b' }

Next, I create an empty Object:

> var obj3 = {};

Finally, I set two different properties on obj3. One is set on the key obj1, and the other is set on the key obj2. Since these two Objects are different, you might be fooled into thinking that obj3 will now have two keys. But watch!

> obj3[obj1] = "test1";
> obj3
{ '[object Object]': 'test1' }
> obj3[obj2] = "test2";
> obj3
{ '[object Object]': 'test2' }

As you can see, both the obj1 and obj2 keys have been coerced into their string values (obj1.toString() is '[object Object]', as is obj2.toString()) when the property was added. So obj3 has only one key/value pair. The first one that was added was obliterated when the second one was set.

For anyone who is more used to working with a strongly typed language, such as Java, this can be a “gotcha!” in Javascript. I certainly made this mistake, myself, when I first started coding in Javascript, years ago. If you want your keys to be less restrictive, consider using Javascript’s Map.

how to get out of a git detached head state

I got into a “detached HEAD state” in git the other day. Here’s what happened, and how I solved it.

I had fixed a bug by making a code change to a single file. I committed the change to git. Then, I decided I didn’t like my fix. I wanted to start over from the previous commit, and redo it.

There are nicer ways to do this, and I guess you could say I did the wrong thing. What I did was to checkout the previous commit, and make my changes there. Then when I committed my changes, I saw the worrisome “You are in ‘detached HEAD’ state” message from git.

I searched around the internets and found a solution at stackoverflow as usual: create a branch, checkout master, and merge your branch into master.

Here’s a very simple example of how it went (I’m in Linux, YMMV). I start with a completely new git repository for demo purposes:

mkdir /tmp/git
cd /tmp/git
echo "Initial commit" > README
git init

Initialised empty Git repository in /tmp/git/.git/

git add README
git commit -a -m "Initial commit."

[master (root-commit) 9dee938] Initial commit.
1 file changed, 1 insertion(+)
create mode 100644 README

echo "A wrong thing" >> README
git commit -a -m "This is wrong."

[master 4ec7b1a] This is wrong.
1 file changed, 1 insertion(+)

[Oops! I want to ignore this wrong change that
I just made. So I check out the previous commit.]

git checkout 9dee938

Note: checking out '9dee938bcd5b575775f5461a383e2b6f010e0866'.

You are in 'detached HEAD' state.
You can look around, make experimental
changes and commit them, and you can
discard any commits you make in this
state without impacting any branches
by performing another checkout.

If you want to create a new branch to
retain commits you create, you may
do so (now or later) by using -b with
the checkout command again. Example:

git checkout -b new_branch_name

HEAD is now at 9dee938... Initial commit.

[Now I'm thinking "oh git!"]

echo "The right thing" >> README
git commit -a -m "What I really wanted!"

[detached HEAD 1ababcd] What I really wanted!
1 file changed, 1 insertion(+)

[Search around for solution... Got it!]

git branch temp
git checkout temp
git status

On branch temp
nothing to commit, working directory clean

git checkout master
Switched to branch 'master'
git merge temp

Auto-merging README
CONFLICT (content): Merge conflict in README

[Edit README to merge the conflicts]

git commit -a -m "fixed!"
git status

On branch master
nothing to commit, working directory clean

At this point, the problem is fixed and my new commit is checked in.

You probably want to delete your temp branch, that is what I did: git branch -d temp