Javascript 向生命传递对象

Javascript 向生命传递对象,javascript,closures,Javascript,Closures,我正在生成一个函数,并使用IIFE将其推送到数组中,如下所示: var arr = []; var k; for(var i=0;i<3;i++) { k = {"val" : i}; arr.push( (function(j) { return function() { console.log(j) }; }(k)) ) } console.log(arr[0](), arr

我正在生成一个函数,并使用IIFE将其推送到数组中,如下所示:

var arr = [];
  var k;
  for(var i=0;i<3;i++) {
    k = {"val" : i};
    arr.push(
      (function(j) {
        return function() {
          console.log(j)
        };
      }(k))
    )
  }
console.log(arr[0](), arr[1](), arr[2]());

但是,我正在传递
k
,这是使用
I
生成的对象。由于对象是通过引用传递的,所以我希望它使用值
2,2,2
记录对象,但我得到的是
0,1,2
。当通过值传递基元类型时,这不是通常的行为吗,为什么即使在我使用按引用传递(对象)时也会发生同样的事情

k={“val”:i}
您正在创建一个新对象并将其分配给
k
。请尝试使用
var k={}
k.val=i

您得到的是0、1、2而不是3、3、3,因为
k
值被传递到函数中。
k
值是对象引用。JavaScript没有任何形式的传递引用,因此函数接收的不是对
k
变量的引用,而是调用函数时
k
中的对象引用的副本。在下一步中,创建一个新对象并将其放入
k
变量中,但这对最内层函数关闭的
j
变量的值没有任何影响

将对象引用想象成一个大数组(内存)的索引,告诉JavaScript引擎对象所在的位置
k
包含该引用(数字),而不是实际对象。将引用复制到第二个变量(或将其传递到函数)时,对象的引用有两个副本,但只有一个对象

让我们简化一下,并使用一些ASCII艺术::-)

在这些代码行之后,下面是我们的内存(省略一些不必要的细节):

……我们有:

k:REF#123−−−−−−+ | +−−−−−−−−−−−−−−−−+ +−−−−>| Object@REF#123 | | +−−−−−−−−−−−−−−−−+ j:REF#123−−−−−−+ | val: 0 | +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+ k−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| Object@REF#4 | | +−−−−−−−−−−−−−−+ | | val: 1 | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ +−>| Object@REF#2 | | | +−−−−−−−−−−−−−−+ | | | val: 0 | | | +−−−−−−−−−−−−−−+ | | | | | +−−−−−−−−−−+ | | arr−−−>| Array | | | +−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ | | | 0: REF#1 |−−−>| Function@REF#1 | | | | 1: REF#3 |−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | +−−−−−−−−−−+ | | [[Environment]] |−−>| Environment | | | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | | | j: REF#2 |−+ | | +−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−−+ | +−>| Function@REF#3 | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | [[Environment]] |−−>| Environment | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | j: REF#4 |−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ 现在我们有了一个新对象,具有不同的引用:

+−−−−−−−−−−−−−−−−+ k:REF#462−−−−−−−−−−−>| Object@REF#462 | +−−−−−−−−−−−−−−−−+ | val: 1 | +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−+ j:REF#123−−−−−−−−−−−>| Object@REF#123 | +−−−−−−−−−−−−−−−−+ | val: 0 | +−−−−−−−−−−−−−−−−++ 在中间调用每个IFIE创建一个执行环境,并附带一个环境记录。从概念上讲,环境记录是一个包含变量和参数值等函数调用的对象(您不能在代码中访问此对象,它是规范中的一个概念,不一定是JavaScript引擎中的文字)。该环境记录包含
j
参数。IIFE创建了一个新函数,它会记住对创建它的环境的引用(使用名为[[environment]]的内部插槽),并返回该引用;函数被推送到数组中

下面是第一次循环后内存的样子(再次省略一些不必要的细节):

+−−−−−−−−−−−−−−+ k−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| Object@REF#2 | | +−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | | val: 0 | arr−−−>| Array | | +−−−−−−−−−−−−−−+ +−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ | | 0: REF#1 |−−−−>| Function@REF#1 | | | 1: REF#3 |−−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | +−−−−−−−−−−+ | | [[Environment]] |−>| Environment | | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | | j: REF#2 |−+ | +−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−+ +−>| Function@REF#3 | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | [[Environment]] |−>| Environment | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | j: REF#4 | +−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+ K−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| Object@REF#2 | | +−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | | 瓦尔:0| 啊−−−>| 数组| |+−−−−−−−−−−−−−−+ +−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ | |0:REF#1|−−−−>| Function@REF#1 | | |1:参考文献3|−−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | +−−−−−−−−−−+ | | [[环境]]|−>| 环境|| | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | || j:参考文献2|−+ | +−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−+ +−>| Function@REF#3 | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ |[[环境]]|−>| 环境| +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ |j:参考文献4| +−−−−−−−−−−−−−+ 在第二个循环之后,您有:

k:REF#123−−−−−−+ | +−−−−−−−−−−−−−−−−+ +−−−−>| Object@REF#123 | | +−−−−−−−−−−−−−−−−+ j:REF#123−−−−−−+ | val: 0 | +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+ k−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| Object@REF#4 | | +−−−−−−−−−−−−−−+ | | val: 1 | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ +−>| Object@REF#2 | | | +−−−−−−−−−−−−−−+ | | | val: 0 | | | +−−−−−−−−−−−−−−+ | | | | | +−−−−−−−−−−+ | | arr−−−>| Array | | | +−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ | | | 0: REF#1 |−−−>| Function@REF#1 | | | | 1: REF#3 |−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | +−−−−−−−−−−+ | | [[Environment]] |−−>| Environment | | | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | | | j: REF#2 |−+ | | +−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−−+ | +−>| Function@REF#3 | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | [[Environment]] |−−>| Environment | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | j: REF#4 |−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+ K−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| Object@REF#4 | | +−−−−−−−−−−−−−−+ || val:1| +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ +−>| Object@REF#2 | | | +−−−−−−−−−−−−−−+ | || val:0 || | +−−−−−−−−−−−−−−+ | | | | | +−−−−−−−−? +−−−−−−−−−−−−−−−−+ k:REF#462−−−−−−−−−−−>| Object@REF#462 | +−−−−−−−−−−−−−−−−+ | val: 1 | +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−+ j:REF#123−−−−−−−−−−−>| Object@REF#123 | +−−−−−−−−−−−−−−−−+ | val: 0 | +−−−−−−−−−−−−−−−−++
var arr = [];
  var k;
  for(var i=0;i<3;i++) {
    k = {"val" : i};
    arr.push(
      (function(j) {
        return function() {
          console.log(j)
        };
      }(k))
    )
  }
console.log(arr[0](), arr[1](), arr[2]());
+−−−−−−−−−−−−−−+ k−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| Object@REF#2 | | +−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | | val: 0 | arr−−−>| Array | | +−−−−−−−−−−−−−−+ +−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ | | 0: REF#1 |−−−−>| Function@REF#1 | | | 1: REF#3 |−−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | +−−−−−−−−−−+ | | [[Environment]] |−>| Environment | | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | | j: REF#2 |−+ | +−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−+ +−>| Function@REF#3 | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | [[Environment]] |−>| Environment | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | j: REF#4 | +−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+ k−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| Object@REF#4 | | +−−−−−−−−−−−−−−+ | | val: 1 | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ +−>| Object@REF#2 | | | +−−−−−−−−−−−−−−+ | | | val: 0 | | | +−−−−−−−−−−−−−−+ | | | | | +−−−−−−−−−−+ | | arr−−−>| Array | | | +−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ | | | 0: REF#1 |−−−>| Function@REF#1 | | | | 1: REF#3 |−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | +−−−−−−−−−−+ | | [[Environment]] |−−>| Environment | | | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | | | j: REF#2 |−+ | | +−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−−+ | +−>| Function@REF#3 | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | [[Environment]] |−−>| Environment | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | j: REF#4 |−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+ k−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−>| Object@REF#6 | | +−−−−−−−−−−−−−−+ | | val: 2 | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ +−>| Object@REF#4 | | | +−−−−−−−−−−−−−−+ | | | val: 1 | | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ | +−>| Object@REF#2 | | | | +−−−−−−−−−−−−−−+ | | | | val: 0 | | | | +−−−−−−−−−−−−−−+ | | | | | | | | +−−−−−−−−−−+ | | | arr−−−>| Array | | | | +−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ | | | | 0: REF#1 |−−−−−−>| Function@REF#1 | | | | | 1: REF#3 |−−−−+ +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | | | 2: REF#5 |−−+ | | [[Environment]] |−−>| Environment | | | | +−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | | | | | j: REF#2 |−+ | | | | +−−−−−−−−−−−−−+ | | | | +−−−−−−−−−−−−−−−−−+ | | | +−>| Function@REF#3 | | | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | | | [[Environment]] |−−>| Environment | | | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | | | j: REF#4 |−−−−−−−−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−−+ | +−−−>| Function@REF#5 | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | [[Environment]] |−−>| Environment | | +−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | j: REF#6 |−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+
var arr = [];
var k;

for(var i = 0; i < 3; i++) {
    arr.push(function() {
        console.log(i)
    })
}

for(var i = 0; i < 3; i++) {
    (function(j) {
        arr.push(function() {
            console.log(j)
        })
    })(i)
}

arr[0]()
arr[1]()
arr[2]()
arr[3]()
arr[4]()
arr[5]()