If all JavaScript types are objects, then why are numbers be passed by value?
In articles about closures, you will often see closures being created inside of loops using self-invoking functions to pass the iterator variable to a returned function expression in order to create a closure around the value of the iterator variable at the time the self-invoking function was invoked, rather than its value after the loop finishes. Here is an example:
var func = [];
for (var i = 0; i < 3; i++)
{
func.push((function(j){ return function(){ console.log(j); }; })(i));
}
// Logs
// 0
// 1
// 2
// to the console
for (var i = 0; i < func.length; i++)
{
func[i]();
}
This technique works with both numbers and strings, based on my simple experiments. However, the same technique does not work with plain JavaScript objects. If an object is passed to a self-invoking function and referenced in a function expression, changes to the enclosed object are visible in the function expression because the value passed to the self-invoking function was a reference to an object and not a copy of the object, as is the case with numbers and strings.
I can understand why this technique would not work with a variable that stores an object, but I don't understand why this technique should work with numbers and strings, whose prototype chains terminate with Object.
Does this mean that strings and numbers are just special cases of objects that are handled differently by the interpreter, or am I suffering from a fundamental misconception?
First, it is not true that "all JavaScript types are objects". Primitive strings, numbers, and boolean values are not objects.
Second, everything in JavaScript is pass-by-value. It's important to understand what "pass-by-value" means. It means that when a function is called, like this:
var someVariable = something;
someFunction(someVariable); // <--- this is the function call
then what the language does is copy the value of someVariable
and pass that copy to the function. What a "pass-by-reference" language would do is pass a reference to that variable to the function. Because a copy of the value of the variable is passed to the function in a pass-by-value world, the function has absolutely no way to modify the value of someVariable
. In a "pass-by-reference" language, it does.
To some extent, C++ lets you employ either parameter passing scheme. JavaScript does not.
The fact that in JavaScript variables have object references as values sometimes does not mean the language is pass-by-reference. I know that that seems like a silly pedantic distinction, but it's important to understand that "pass-by-value" and "pass-by-reference" are precise terms used to describe language semantics. If they don't have precise meanings, they're useless for that purpose.
One more thing: JavaScript implicitly wraps string, number, and boolean primitive values in wrappers of the corresponding String, Number, and Boolean types when the primitive values are used as if they're objects. That's what happens when you do something as common as:
var five = "hello".length
The left-side operand of the .
operator has to be an object, so there's no special-case here: there's an implicit promotion of the primitive string value to a String instance. (What the runtime really does under the covers, well, we can't tell and we shouldn't care. Conceptually, a temporary wrapper object is created, used, and thrown away.)
In javascript there are 6 primitive types: string,number,boolean,null,undefined,symbol - new in ECMAScript 2015. However there are Object
wrapper classes for these primitives. All 6 except null
and undefined
have wrapper classes. Reference These primitive types are passed by value not by reference per the javascript design.