在C++中。int a=3
,编译器将编译变量名 a
到内存地址,就像 int 0x0001=3
.
我对JavaScript变量名如何链接到内存地址感兴趣,也许可以使用 Environment Record
? 但是... Environment Record
看起来不存储内存地址。
作为一个(有些简化的)心理模型,你可以假设JavaScript引擎维护了一组字典对象来实现作用域链。每个变量的名称都是这样一个字典中的一个键。范围字典有一个父级的外域。
例如,如果你有。
// Global code.
var a = 1;
function f1() {
var b = 2;
}
那么在引擎内部的某个地方就有(概念上)这样的元数据。
global_scope = {
local_variables: {
"a": 1,
},
parent: null,
}
f1_scope = {
local_variables: {
"b": 2,
},
parent: global_scope,
}
而当在引擎内部解析一个变量引用时 f1
,它将使用一个类似于查找函数的函数。
function lookup(variable_name, current_scope) {
if (variable_name in current_scope.local_variables) {
return current_scope.local_variables[variable_name];
}
if (current_scope.parent === null) return undefined; // or ReferenceError.
return lookup(variable_name, current_scope.parent);
}
在现实中,它是相当复杂的,因为例如,为了性能的原因,要区分堆栈分配和作用域分配的变量,优化编译器和解释器做的事情是不同的。let
-绑定变量和 with
-范围和 eval
都需要特殊的处理等等,但这就是大意。
正如@Bergi在评论中指出的,在C++中,实际情况也相当复杂。int a = 3
通常会把 3
变成一个寄存器。int* a = new int[1]
编译成 malloc
调用,它返回一个地址,所以编译器不知道这个数组将被分配的地址,这只是在运行时决定的。