Hi,
TW macros are relatively simple. eg:
\define test(parm1) this is param1 $param1$
Where param1 is a "text substitution". Javascript macros have a more low level access to $tw. functions, but they are just "text substitutions".
widgets have much more possibilities in their livecycle. eg. init(), execute(), render(), refresh() and a lot more.
Macros have to be parsed every time they are executed, widgets only refresh elements / children that really changed.
This is not 100% correct, but it should give you a hint.
-m