add方法在return的适时候就形成了一个闭包,包含n=4399这个值,这个n不是result和result2里的属性值n。两个不同对象的闭包是彼此独立的,不互相影响

发布时间 2023-11-16 14:22:30作者: 龙陌

在浏览器控制台中执行以下代码,输出的结果是

function test() {
    var n = 4399;
    function add(){
        n++;
        console.log(n);
    }
    return {n:n,add:add}
}
var result = test();
var result2 = test();
result.add();
result.add();
console.log(result.n);
result2.add();

A
4400 4401 4399 4400

B
4400 4401 4401 4402

C
4400 4400 4399 4400

D
4400 4401 4399 4402

E
4400 4401 4401 4400

正确答案:A

这个题其实挺有难度的不知道为啥没人写解析
test构成了一个闭包,result跟result2各自有自己的test作用域,所以最后result2.add()结果是4400
前两个没啥好说的,懵逼点在第三个,这里{n:n}是对变量n里的值进行缓存,而不是本身n这个指针变量,
这样生成add的时候n指向的值是多少{n:n}里的值就是多少

js在执行之前,会将所有带var和function的进行提前定义和声明。(带var的提前声明,function声明和定义都完成了)

首先,在全局作用域下,进行预解释:
test=xxxfff000(开辟一个堆内存,里面存的是代码字符串)
var result(声明一个变量result)
var result2(声明一个变量result2)

代码执行:
result=test() -->将test执行的返回结果赋值给result,是一个对象,再开辟一个堆内存,test执行,形成一个私有作用域A
再进行预解释和代码执行等一系列操作
result2=test() 同理

result.add() -->方法执行形成一个私有作用域

n++ 顺着作用域链向上寻找到test作用域A(A这个作用域不销毁,因为被全局变量result占用了)中的n为4399,n++ 》4400

(这时test这个作用域A下的n变成4400)

(1) console.log(n) //4400

==============================

result.add() -->方法执行形成一个新的私有作用域

n++ 顺着作用域链向上寻找到test作用域(A)中的n为4400,n++ 》4401

(2) console.log(n) //4401

===============================

(3) console.log(result.n) //4399
此时找的只是result对应的那个堆内存中的n

===============================

result2.add() -->方法执行形成一个私有作用域
n++ 顺着作用域链向上寻找到test作用域(B)中的n为4399,n++ 》4400

(3) console.log(n) //4400

形成了不同的作用域,所以访问到的n 也是不一样的 如果想要test里面的n跟着add() 一块加1 可以添加一行 this.n ++

函数每调用一次重新执行函数体中的所有代码一次,函数调用的结果是return的返回值。
在本题中函数test的返回值是一个对象,每调用一次就返回一个新的对象,所以reslut1与result2是两个不同的对象。
对象的属性和方法只有该对象自己能够使用,对象内部的方法不能够通过属性名或者方法名来使用同一对象内部的其它属性值或者方法
因此,前面reslut.add()对reslut指向的对象里面的属性'n:4399'没有影响

add方法在return的适时候就形成了一个闭包,包含n=4399这个值,这个n不是result和result2里的属性值n。两个不同对象的闭包是彼此独立的,不互相影响