这两个关于 JavaScript 作用域链的例子有什么区别?


var a = 1;
function x() {
    a = 2
    console.log(a) // 2
}
x();
console.log(a); // 2 

和:

var a = 1;
function x(p) {
    p = 2
    console.log(p) // 2
}
x(a);
console.log(a); // 1 

为什么第二个示例的输出是 1 而不是 2?

这是因为您的p变量仅存在于function x(p) 中。因此,您在内存中有一个新空间,一个复制变量a。在第一个示例中,它是指向变量 a 的内存地址的指针。

另一方面,对象具有"按引用传递",因此,如果您这样做:

var obj = { foo: 1 };
function x(paramObj) {
    paramObj.foo = "2";
}
x(obj);
alert(obj.foo);

您将看到"2"而不是"1"。

因为函数参数是在执行函数时"创建"的。

var a = 1;
function x(p) {
    p = 2
    console.log(p) // 2
};

在这一段代码中,您将创建全局变量 a = 1;然后将其传递给 x 函数。在函数中,您将给定参数设置为 2 并控制台.log它;但真正发生的事情是这样的:

var a = 1;

function x(given_argument) {
    var p = given_argument;
    p = 2; // global a variable still equals 1;
    console.log(p) // 2
};

这是因为Javascript中有2种类型的变量。数字、字符串、布尔值等值只是值和引用类型,如数组、对象。

如果你知道C++那么这应该会减轻一点。这相当于用C++编写的Javascript中发生的事情:

// javascript
var a = 1; // plain value
// c++
int a = 1; // plain value
// javascript
var a = {}; // referential type, this is a pointer behind the scenes
// or
var a = new Object(); // if you prefer it this way
// c++
Object* a = new Object(); // this is a pointer to the object, but in C++ you make it a pointer explicitly, in Javascript this happens 'automagically'.

Javascript中的引用类型是指针,这意味着如果作为参数传递,则可以从函数内部更改它们。但是,如果您传递像数字或布尔值这样的正常值,则会在函数内部声明,并且它会隐式发生。

我希望它澄清了问题。

最新更新