下面是我在笔试中遇到的选择题。
代码1涉及到的知识点:var声明的变量的特点
代码2涉及到的知识点:var以及let声明的变量的特点
代码3涉及到的知识点:Symbol声明变量的特点,以及对象中的属性的特点(都会转成字符串形式)
笔试中常见的代码输出选择题
代码1:问a输出的是什么?
if (!('a' in window)) {
var a = 1;
}
console.log(a);
这里a的输出是undefind
解释:
- 所有的全局变量都是window属性,语句var a=1;等价于window.a=1;
var b;
console.log(window);
注意:这里如果将var变为const或者let,就会是另外的结果,换成let,不会将其加入到window身上,
换成const的时候必须要赋初值,不然的话会报错,而在赋初值之后,也会跟let一样不会加入到window身上 。
具体的let、const、var之间的区别,可以看我的前端面试css系列的笔记。
- var的变量声明都在范围作用域的顶部。
- 变量声明提前了,但是变量赋值没有提前。
因此这段代码就等价于:
var a;
if (!('a' in window)) {
a = 1;
}
console.log(a);
因为a已经存在window里面,所以a无法进行赋值,所以最后输出为undefined。
代码2:问执行func函数后应该输出什么
try {
let flag = true;
} catch { };
var state = false;
function func() {
if (typeof flag === 'undefined') {
console.log(1);
};
if (typeof state === 'undefined') {
var state = 20;
console.log(2);
}
};
func();
答案是:1,2
解释部分:
- 为什么会输出1?
因为let声明的是块级作用域,当try…catch执行完成之后,flag就会变成undefined。因此在调用func函数的时候,判断flag是否等于undefined的时候,会输出1。 - 为什么输出2?
为什么会输出2呢,明明前面state还是用var定义的全局变量。这里我猜想是因为在判断语句中又定于了一次var state,因为在加载这个函数的时候,var声明的变量会进行变量提升,将其放在该作用域下的最前面,而赋值操作时在执行的时候才赋值的,因此在判断的时候state是undefined,因此才会打印出2。如果把 state前面的var去掉之后,2就不会输出了。
下面这个代码可以看出,将var state =20 改成state=20之后,state就不再是undefined了,而是false。
try {
let flag = true;
} catch { };
var state = false;
function func() {
if (typeof flag === 'undefined') {
};
console.log(state);
if (typeof state === 'undefined') {
state = 20;
}
};
func();//false
代码3:这里定义了一个对象,然后往里面加属性
const obj = {
'117': 117,
[Symbol('935')]: 935
};
const num = 117;
const other1 = {};
const other2 = {};//这块也很奇怪,为啥会是这个样子
obj[num] = 711;
// const symsum = Symbol('935')
obj[Symbol('935')] = 539;
obj[other1] = 10;
obj[other2] = 20;
console.log(obj[num])//711
console.log(obj[Symbol('935')])//这里得到的是undefined,这块很奇怪
console.log(obj[{}])//这里的到的是20
console.log(obj)//最终obj对象里面有4个属性。
解释如下:
这里主要有四个输出:
- 第一个输出是711不难理解。
- 第二个输出是不是935,也不是539,而是undefined,是因为Symbol定义的是唯一的一个值,而console.log中的Symbol(‘935’)则是又重新定义了一个Symbol的值,而obj中都这个属性,肯定是undefined啦。如果将这里改为如下所示,就可以啦:
const symnum = Symbol('935');
obj[symnum ]=533
console.log(obj[symnum ])//533
- 第三个输出是20,是因为在Symbols出来之前,对象的键只能是String。如果我们尝试使用非字符串值作为对象的键,则该值将被强制转换为String。这里传入的other1还有other2都会转入String模式,因此other1就被other2挤掉了。
- 第四个输出就不用解释了,最终的属性如下图所示: