Basically, expression controllers are the oldest implementation, back before MAXScript was a part of the package, and are much faster than anything that uses MAXScript syntax (such as wire controllers or script controllers). However, they also have only a limited set of functions (and are also case sensitive) and you cannot make a scene object a variable and access its properties. For example, in script controller you can assign some object to obj variable and get its world position via obj.transform.pos or its position in parent space via obj.iNode.posInParent, and do advanced matrix transformations, access scene globals and so on. obj.transform.pos is generally safer as obj.transform computes a transformation matrix which includes ALL transforms including constraints. obj.pos should be okay provided you don't use constraints on the node, it functions as a direct property access, so $.pos.z += 10 will change node position, $.transform.pos.z will on the other hand only operate on the returned matrix so in order for it to work you'd have to do something like:
nodeTM = obj.transform -- get it
nodeTM.pos.z += 10 -- change it
obj.transform = nodeTM -- set it