【笔试题】请听题。。。

125 阅读4分钟

1. 请听题

(function () { var a = b = 5 })()
console.log(a);
console.log(b);

答案

Uncaught ReferenceError: a is not defined

解析

本题考察变量提升。 在闭包中,用var关键字声明了局部变量a,而b没有声明,在非严格模式下,默认是全局变量。执行console.log(a)时,闭包函数已经执行完毕,局部变量a已销毁,所以console.log(a)直接报错,后面的console.log(b)不再执行。所以答案是a is not defined

变形一

刚才提到了这个是在非严格模式下,如果是在严格模式下呢?

'use strict'; (function () { var a = b = 5 })()
console.log(a);
console.log(b);

执行一下结果是:

Uncaught ReferenceError: b is not defined

2. 请听题

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

答案

2,1

解析

本题考察局部变量和传参。

红宝书里写到:** ECMAScript中所有参数传递都是值,不可能通过引用传递参数。**

参数分为基本类型和引用类型,此题是基本类型的参数传递,把全局变量a传给方法b这时是全局参数a把值复制给了方法barguments里的a。这样方法b里的a是方法b的局部变量。它是不影响全局变量a的,所以输出是2, 1

变形一

前面提到了参数还有个引用类型,那如果传引用类型,结果又是什么样子呢?

var a = {}
function b (a) {
	a.name = 'fish'
    console.log(a)
}
b(a)
console.log(a)

执行一下结果:

{name: "fish"}
{name: "fish"}

这么一看,像是引用传递呀,里面的对象添加了属性name,并且影响到了外面的对象。那我们再来看下面这段代码:

var a = {}
function b (a) {
	a.name = "fish"
    a = new Object()
    a.name = 'pig'
    console.log(a)
}
b(a)
console.log(a)

执行结果为:

{ name: "pig" }
{ name: "fish" }

如果是引用传递的话,两次结果应该都是{ name: "pig" }的呀?

其实,引用类型也是值传递,只是这个值指的是引用对象的地址,这个地址指向存放在堆里的对象。在把参数传进来时,是把这个参数对象的地址,复制了一份给参数a, 这样它们都是指向同一个堆中的对象。后来,新创建一个对象,赋值给了参数a,也就是把新创建的对象的地址给了a,这样就把之前的地址覆盖了,参数a指向了新的对象,就不再影响全局对象a了。

3. 请听题

var a = new Boolean(false)
if (a) {
	console.log(1)
}
var b = Boolean(0)
if (b) {
	console.log(2)
}

答案

1

解析

这里的a其实是Boolean对象,** 任何对象转为布尔值,都是true。** 在js中,只有0, -0,NaN, "", null, undefined这6个转为Boolean时为false

而第二段代码,注意是Boolean不是new Boolean,是显式类型转换,所以结果为false

4. 请听题

const a = 12;
a = 13;
console.log(a);

const g = { b:3 };
console.log(g.b);
g.b = 12;
console.log(g.b);

let [head, ...tail] = [1,2,3,4];
console.log(tail);

答案

Uncaught TypeError: Assignment to constant variable.

3, 12

[2,3,4]

解析

const 声明的变量不可以北重写,但定义对象的属性可以被修改。

解构赋值

5. 请听题

var k = 0;
for (var i = 0, j = 0; i < 10, j < 6; i++,j++) {
	k += i + j;
}
console.log(k);

答案

30

解析

for循环第二项的布尔值决定了循环是否继续。如果i < 10i < 6互换,结果就不一样了。

6. 请听题

var x = 0;
switch (++x) {
	case 0: console.log('a'); ++x;
    case 1: console.log('b'); ++x;
    case 2: console.log('c'); ++x;
}

答案

b
c
3

解析 这里没有break,所以执行到最后。

i++ 返回原来的值,++i返回加1后的值。i++不能作为左值,而++i可以。

变形一

var x = 0;
switch (x++) {
	case 0: console.log('a'); ++x;
    case 1: console.log('b'); ++x;
    case 2: console.log('c'); ++x;
}

执行结果:

a
b
c
4

变形二

var x = 0;
switch (x++) {
	case 0: console.log('a'); x++;
    case 1: console.log('b'); x++;
    case 2: console.log('c'); x++;
}

执行结果:

a
b
c
3

7. 请听题

function Foo () {
	var i = 0;
    return function () {
    	document.write(i++);
    }
}

var f1 = Foo();
f2 = Foo();
f1();
f1();
f2();

8. 请听题

var a = 10
(function a () {
    a = 20
    console.log(a)
})()

答案

download-1.png

解析

download-1.png

报错位置时在执行方法a,报错内容是10 is not a function。也就是说此时的a已经被复制为10了。

我们分析下执行顺序:

执行代码之前,会先解析声明和变量,首先声明一个名为afunction,这是因为存在function a,所以不会再声明一个a的变量。

开始执行时,10复制给a,其实就是10赋值给function a,这样a就是10,不再是方法,所以在执行时报错。

变形一

var a
(function a () {
    a = 20
    console.log(a)
})()

答案

ƒ a () {
    a = 20
    console.log(a)
}

思考:为何a = 20 没生效呢?