Let me give a somewhat more technical explanation. When you access a variable in Javascript, the interpreter looks for the value of the variable in what's known as the scope stack. You can think of it as a stack of Objects. The interpreter will look first at the top of the stack. If the variable isn't defined in that scope object, it will look at the object beneath it. If it's not there, the interpreter looks another level down until it hits the bottom of the stack.
Initially, the only scope object in the stack is the global object. A variable is either there or not. When you call a function, the interpreter pushes a new object onto the scope stack--to be used for storing local variables. When you access var1, the interpreter will first look in the local scope object. If it's there, then it'll use the value stored there. If it's not, it moves on to the scope object further down the stack--which happens to be the global scope.
When you create a function within a function, something interesting happens. The interpreter will create what's known as an "activation object". It's basically a snapshot of the local scope object of the outer function. This activation object becomes associated with the inner function. When the inner function is called, the activation object is push onto the scope stack before the local scope (i.e. the local scope would still be at the top). Access of a variable in the inner function means the interpreter will first check the local scope object, then the activation object, then the global scope object.
By definition, the this variable always exists in the local scope of a function. It always refers to the implicit first argument. When you call a plain-o function, the compiler passes null as this. The variable exists, but points to null. A search for this would never look beyond the local scope object.
The purpose of the assignment to self is basically to fool the interpreter, so that it would look beyond the local scope of the inner function. When you access self in the inner function, the interpreter wouldn't find it in the local scope. So it checks the activation object. Provided that the self = this statement occurs before the creation of the inner function, self would exist in the activation scope object, pointing to the this object seen by the outer function.