前端笔试之JS闭包程序输出判断题

一、作用域链变量查找

题目1
var a = 10;
function test() {
    var a = 20;
    console.log(a);
}
test();
console.log(a);
题目2
var a = 10;
function test() {
    console.log(a);
    var a = 20;
}
test();
题目3
var a = 10;
function test() {
    a = 20;
}
test();
console.log(a);
题目4
function outer() {
    var a = 10;
    function inner() {
        console.log(a);
    }
    return inner;
}
var innerFunc = outer();
innerFunc();

二、 闭包程序输出判断

题目5
function outer() {
  var a = 1;
  function inner() {
      console.log(a);
  }
  a++;
  return inner;
}
var innerFunc = outer();
innerFunc();
题目6
var a = 1;
function outer() {
    var a = 2;
    function inner() {
        console.log(a);
    }
    return inner;
}
var innerFunc = outer();
innerFunc();
题目7
function outer() {
    var a = 1;
    function inner() {
        console.log(a);
        a++;
    }
    return inner;
}
var innerFunc = outer();
innerFunc();
innerFunc();
 题目8
function createCounter() {
    var count = 0;
    return function() {
        return ++count;
    };
}
var counter = createCounter();
console.log(counter());
console.log(counter());
 题目9
for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}
题目10
for (var i = 0; i < 3; i++) {
    (function(i) {
        setTimeout(function() {
            console.log(i);
        }, 1000);
    })(i);
}
题目11 
function outer() {
    var funcs = [];
    for (var i = 0; i < 3; i++) {
        funcs[i] = function() {
            console.log(i);
        };
    }
    return funcs;
}
var funcs = outer();
funcs[0]();
funcs[1]();
funcs[2]();
 题目12
function outer() {
    var funcs = [];
    for (var i = 0; i < 3; i++) {
        (function(i) {
            funcs[i] = function() {
                console.log(i);
            };
        })(i);
    }
    return funcs;
}
var funcs = outer();
funcs[0]();
funcs[1]();
funcs[2]();
 题目13
function outer() {
    var a = 1;
    return {
        inner: function() {
            console.log(a);
        },
        increase: function() {
            a++;
        }
    };
}
var obj = outer();
obj.inner();
obj.increase();
obj.inner();
 题目14
function outer() {
    var a = 1;
    return function() {
        a++;
        console.log(a);
    };
}
var inner1 = outer();
var inner2 = outer();
inner1();
inner1();
inner2();

答案

题目1

输出 20

 解析:

        JavaScript 使用了词法作用域(也称为静态作用域),在函数 test 内部,变量 a 是局部变量,它与全局作用域中的变量 a 是不同的。

        当你在函数 test 内部调用 console.log(a) 时,JavaScript 解释器会首先在当前的作用域(也就是 test 函数的作用域)中查找变量 a。在这个作用域中,有一个局部变量 a,所以解释器就使用了这个局部变量,而不是全局的变量 a

        所以,console.log(a) 输出的是局部变量 a 的值,也就是 20。

题目2

输出 undefined

解析:

        在 JavaScript 中,变量和函数声明会被提升到它们所在的作用域的顶部。但是,只有声明会被提升,初始化(也就是赋值操作)不会被提升。

        在代码中,函数 test 的作用域内有一个变量 a 的声明和初始化。由于变量提升,这个声明会被提升到 test 函数作用域的顶部,但是初始化(a = 20)仍然在原地。

        所以,当代码执行到 console.log(a) 时,变量 a 已经被声明了,但还没有被初始化,所以它的值是 undefined

 

题目3

输出 20

解析:

        在 test 函数内部,变量 a 没有通过 var 关键字声明,所以它引用的是全局作用域中的变量 a

        当 test 函数内部执行 a = 20 时,实际上是在修改全局变量 a 的值。所以,当 test 函数执行后调用 console.log(a),输出的是全局变量 a 的新值,也就是 20。

 

题目4

输出 10

 解析:

        相关知识点:JavaScript 的闭包(Closure)机制。

        在 JavaScript 中,当一个函数内部定义了另一个函数,内部的函数可以访问外部函数的变量,即使外部函数已经执行完毕。这种能够访问外部函数变量的内部函数,我们称之为闭包。

        在代码中,inner 函数就是一个闭包,它可以访问 outer 函数的变量 a。当 outer 函数执行完毕后,虽然它的局部变量 a 在其他地方是不可访问的,但是 inner 函数仍然可以访问到它。

        所以,当执行 innerFunc()(也就是 inner 函数)时,console.log(a) 输出的是 outer 函数的变量 a 的值,也就是 10。

        这是 JavaScript 作用域链和闭包机制的一个例子,它允许函数记住并访问它的词法作用域,即使函数在其词法作用域之外执行。

 

题目5

输出2

解析:

        在代码中,outer 函数创建了一个局部变量 a 和一个内部函数 innerinner 是一个闭包,它可以访问 outer 函数的作用域,所以它可以访问变量 a

        当 outer 函数执行时,它首先将 a 设置为 1,然后 inner 函数被创建,然后 a 的值增加 1,最后 outer 函数返回 inner 函数。

        所以,当 innerFunc(也就是 inner 函数)被调用时,它打印的是 a 的当前值,也就是 2。

题目6

输出2

 解析:

  outer 函数创建了一个局部变量 a 和一个内部函数 innerinner 是一个闭包,它可以访问 outer 函数的作用域,所以它可以访问变量 a

     当 outer 函数执行时,它首先将 a 设置为 2,然后 inner 函数被创建,最后 outer 函数返回 inner 函数。

     所以,当 innerFunc(也就是 inner 函数)被调用时,它打印的是 a 的当前值,也就是 2,而不是全局变量 a 的值。

 题目7

输出  1和2

解析:

  outer 函数创建了一个局部变量 a 和一个内部函数 innerinner 是一个闭包,它可以访问 outer 函数的作用域,所以它可以访问和修改变量 a

     当 outer 函数执行时,它首先将 a 设置为 1,然后 inner 函数被创建,最后 outer 函数返回 inner 函数。

     然后,题目调用了 innerFunc(也就是 inner 函数)两次。每次调用 innerFunc 时,它都会打印 a 的当前值,然后将 a 的值增加 1。

     所以,第一次调用 innerFunc 时,它打印的是 a 的初始值,也就是 1。然后,a 的值增加 1,变为 2。

      第二次调用 innerFunc 时,它打印的是 a 的当前值,也就是 2。

题目8

输出 :

1

2

解析:

  createCounter 函数创建了一个局部变量 count 和一个匿名函数。这个匿名函数是一个闭包,它可以访问 createCounter 函数的作用域,所以它可以访问和修改变量 count

      当 createCounter 函数执行时,它首先将 count 设置为 0,然后创建了一个匿名函数,最后返回这个匿名函数。

       然后,题目将 createCounter 函数的返回值赋值给了 counter,所以 counter 现在是一个函数,这个函数可以访问和修改 count 变量。

       题目调用了 counter 两次。每次调用 counter 时,它都会将 count 的值增加 1,然后返回 count 的新值。

       所以,第一次调用 counter 时,它返回的是 count 的初始值加 1,也就是 1。第二次调用 counter 时,它返回的是 count 的当前值加 1,也就是 2。

题目9

输出

3

3

3

解析:

        在代码中,setTimeout 函数创建了一个定时器,这个定时器在 1000 毫秒后执行一个函数。这个函数是一个闭包,它可以访问包含它的函数的作用域,所以它可以访问变量 i

        然而,当 setTimeout 函数被调用时,它不会立即执行定时器的回调函数,而是将这个回调函数放入事件队列中,等待当前的代码执行完毕后再执行。

        所以,当 for 循环执行完毕时,变量 i 的值已经是 3,然后所有的定时器的回调函数开始执行。由于这些回调函数都是闭包,它们访问的是同一个 i 变量,所以它们打印的都是 i 的当前值,也就是 3。

题目10

输出:

0

1

2

解析:

        在代码中,setTimeout 函数创建了一个定时器,这个定时器在 1000 毫秒后执行一个函数。这个函数是一个闭包,它可以访问包含它的函数的作用域,所以它可以访问变量 i

        然而,这里的关键是 (function(i) {...})(i); 这部分代码。这是一个立即执行函数表达式(IIFE),它创建了一个新的作用域,这个作用域有它自己的 i 变量,这个 i 的值是循环的当前迭代值。

        所以,当 setTimeout 的回调函数执行时,它打印的是创建定时器时的 i 值,而不是循环结束时的 i 值。

题目11

输出

3

3

3

解析:

        在代码中,outer 函数创建了一个数组 funcs 和一个 for 循环。在 for 循环中,每次迭代都创建了一个新的函数,并将这个函数赋值给 funcs 数组的一个元素。这个新的函数是一个闭包,它可以访问 outer 函数的作用域,所以它可以访问变量 i

        然而,由于 JavaScript 的变量提升机制,for 循环中的 var i 实际上是在 outer 函数的整个作用域中声明的。所以,当 for 循环执行完毕后,变量 i 的值是 3,然后所有的函数都是闭包,它们访问的是同一个 i 变量,所以它们打印的都是 i 的当前值,也就是 3。

题目12

这段代码的输出是:

0

1

2

这是因为 JavaScript 的闭包和立即执行函数表达式(IIFE)机制。

        在代码中,outer 函数创建了一个数组 funcs 和一个 for 循环。在 for 循环中,每次迭代都创建了一个新的立即执行函数表达式(IIFE)。这个 IIFE 创建了一个新的作用域,这个作用域有它自己的 i 变量,这个 i 的值是循环的当前迭代值。

        然后,这个 IIFE 创建了一个新的函数,并将这个函数赋值给 funcs 数组的一个元素。这个新的函数是一个闭包,它可以访问包含它的函数的作用域,所以它可以访问 i 变量。

        所以,当 funcs[0]()funcs[1]() 和 funcs[2]() 被调用时,它们打印的是创建函数时的 i 值,也就是 0、1 和 2。

题目13

这段代码的输出是:

0

1

2

        在代码中,outer 函数创建了一个局部变量 a 和一个对象。这个对象有两个方法:inner 和 increase。这两个方法都是闭包,它们可以访问 outer 函数的作用域,所以它们可以访问和修改变量 a

        当 outer 函数执行时,它首先将 a 设置为 1,然后创建了一个对象,最后返回这个对象。

        然后, outer 函数的返回值赋值给了 obj,所以 obj 现在是一个对象,这个对象的 inner 和 increase 方法可以访问和修改 a 变量。

        随后,代码中调用了 obj.innerobj.increase 和 obj.innerobj.inner 打印 a 的当前值,obj.increase 将 a 的值增加 1。

        所以,第一次调用 obj.inner 时,它打印的是 a 的初始值,也就是 1。然后,obj.increase 将 a 的值增加 1,变为 2。然后,第二次调用 obj.inner 时,它打印的是 a 的当前值,也就是 2。

题目14

这段代码的输出是:

2

3

2

        在代码中,outer 函数创建了一个局部变量 a 和一个匿名函数。这个匿名函数是一个闭包,它可以访问 outer 函数的作用域,所以它可以访问和修改变量 a

        当 outer 函数执行时,它首先将 a 设置为 1,然后创建了一个匿名函数,最后返回这个匿名函数。

        然后, outer 函数的返回值赋值给了 inner1 和 inner2,所以 inner1 和 inner2 现在都是函数,这两个函数可以访问和修改它们各自的 a 变量。

        随后题目调用了 inner1 和 inner2。每次调用这些函数时,它们都会将 a 的值增加 1,然后打印 a 的新值。

        所以,第一次和第二次调用 inner1 时,它打印的是 a 的值加 1,也就是 2 和 3。然后,调用 inner2 时,它打印的是 a 的值加 1,也就是 2,因为 inner2 有它自己的 a 变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值