如果所有JavaScript类型都是对象,那么为什么数字会按值传递?

Dan*_*ant 2 javascript closures loops

在关于闭包的文章中,您经常会看到在循环内部创建闭包,使用自调用函数将迭代器变量传递给返回的函数表达式,以便在自调用时围绕迭代器变量的值创建闭包.调用函数,而不是循环结束后的值.这是一个例子:

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]();
}
Run Code Online (Sandbox Code Playgroud)

基于我的简单实验,这种技术适用于数字和字符串.但是,相同的技术不适用于纯JavaScript对象.如果将对象传递给自调用函数并在函数表达式中引用,则在函数表达式中可以看到对所包含对象的更改,因为传递给自调用函数的值是对对象的引用而不是对象的副本对象,就像数字和字符串一样.

我可以理解为什么这种技术不适用于存储对象的变量,但我不明白为什么这种技术应该使用数字和字符串,其原型链以Object结尾.

这是否意味着字符串和数字只是解释器处理不同的对象的特殊情况,或者我是否遭受了根本的误解?

Poi*_*nty 8

首先,"所有JavaScript类型都是对象"并不是真的.原始字符串,数字和布尔值不是对象.

其次,JavaScript中的所有内容都是按值传递的.了解"按值传递"的含义非常重要.这意味着当调用函数时,如下所示:

var someVariable = something;
someFunction(someVariable); // <--- this is the function call
Run Code Online (Sandbox Code Playgroud)

那么语言的作用是复制someVariable并将该副本传递给函数."传递引用"语言的作用是将对该变量的引用传递给函数.因为变量值的副本在按值传递的世界中传递给函数,所以函数绝对无法修改值someVariable.在"传递参考"语言中,它确实如此.

在某种程度上,C++允许您使用任一参数传递方案.JavaScript没有.

在JavaScript变量中将对象引用作为值的事实有时并不意味着该语言是通过引用传递的.我知道这似乎是一个愚蠢的迂腐区别,但重要的是要理解"传值"和"传递参考"是用于描述语言语义的精确术语.如果它们没有精确的含义,那么它们就没用了.


还有一件事:当原始值被用作对象时,JavaScript隐式地将字符串,数字和布尔原语值包装在相应的String,Number和Boolean类型的包装中.这就是当你做一些常见的事情时会发生的事情:

var five = "hello".length
Run Code Online (Sandbox Code Playgroud)

.运算符的左侧操作数必须是一个对象,因此这里没有特殊情况:将原始字符串值隐式提升为String实例.(运行时真正做的是什么,好吧,我们无法分辨,我们不应该关心.从概念上讲,创建,使用和丢弃临时包装器对象.)