Your quoted code does not behave as you've described. But trying to answer the question anyway, here's your code with some inline explanation:
var process = function (test) {
var i = test;
// Here you're creating a "closure" over the context of
// this specific call to this function. So the `i` local
// variable lives on, even after this function call
// terminates.
this.echo = function () { console.log(i); };
};
// This `test` variable is *completely and totally* unrelated to the
// `test` argument to your function above. They do not interact in
// any way.
var test = 'hai';
// Here, yu're passing the *value* of the `test` variable ("hai")
// into the function. The function has no reference to the `test`
// variable at all (er, not a relevant way; details below). From
// the function's point of view, it's *exactly* like
// `var hai = new process("hai");`
var hai = new process(test);
// This will show "hai"
hai.echo();
// This will also show "hai", because again, the `i` in the `echo`
// function is the local variable in the call to `new process` above;
// it is in no way whatsoever related to the `test` variable here.
test = 'sorry';
hai.echo();
More to explore (in my blog): Closures are not complicated
Details on my note about how the process
function doesn't have a relevant reference to the test
variable: Technically, the function you're assigning to process
does have a reference to the test
variable because it's a closure over the scope in which the test
variable is defined. But it's not using that, because it has its own test
argument and that symbol shadows (overrides) the one from the containing scope. None of which has anything to do with your passing test
into the call to the process
function, which is why it's irrelevant.