JavaScript 进阶问题列表
我在我的Instagram上发布了每日JavaScript
选择题,我也会在这里发布!
从基础到高级:测试您对JavaScript
的了解程度,刷新您的知识,或为您的编码面试做好准备!? ?我每周用新问题更新这个项目。
答案位于问题下方
1. 下面代码的输出是什么?
function sayHi() {
console.log(name);
console.log(age);
var name = "Lydia";
let age = 21;
}
- A:
Lydia
和undefined
- B:
Lydia
和ReferenceError
- C:
ReferenceError
和21
- D:
undefined
和ReferenceError
答案: D
在函数中,我们首先使用var
关键字声明了name
变量。 这意味着变量在创建阶段会被提升(JavaScript
会在创建变量创建阶段为其分配内存空间),默认值为undefined
,直到我们实际执行到使用该变量的行。 我们还没有为name
变量赋值,所以它仍然保持undefined
的值。
使用let
关键字(和const
)声明的变量也会存在变量提升,但与var
不同,初始化没有被提升。 在我们声明(初始化)它们之前,它们是不可访问的。 这被称为“暂时死区”。 当我们在声明变量之前尝试访问变量时,JavaScript
会抛出一个ReferenceError
。
译者注:
关于let
的是否存在变量提升,我们何以用下面的例子来验证:
let name = 'ConardLi'
{
console.log(name) // Uncaught ReferenceError: name is not defined
let name = 'code秘密花园'
}
let
变量如果不存在变量提升,console.log(name)
就会输出ConardLi
,结果却抛出了ReferenceError
,那么这很好的说明了,let
也存在变量提升,但是它存在一个“暂时死区”,在变量未初始化或赋值前不允许访问。
变量的赋值可以分为三个阶段:
- 创建变量,在内存中开辟空间
- 初始化变量,将变量初始化为
undefined
- 真正赋值
关于let
、var
和function
:
let
的「创建」过程被提升了,但是初始化没有提升。var
的「创建」和「初始化」都被提升了。function
的「创建」「初始化」和「赋值」都被提升了。
2. 下面代码的输出是什么?
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
- A:
0 1 2
and0 1 2
- B:
0 1 2
and3 3 3
- C:
3 3 3
and0 1 2
答案: C
由于JavaScript
中的事件执行机制,setTimeout
函数真正被执行时,循环已经走完。 由于第一个循环中的变量i
是使用var
关键字声明的,因此该值是全局的。 在循环期间,我们每次使用一元运算符++
都会将i
的值增加1
。 因此在第一个例子中,当调用setTimeout
函数时,i
已经被赋值为3
。
在第二个循环中,使用let
关键字声明变量i
:使用let
(和const
)关键字声明的变量是具有块作用域的(块是{}
之间的任何东西)。 在每次迭代期间,i
将被创建为一个新值,并且每个值都会存在于循环内的块级作用域。
3. 下面代码的输出是什么?
const shape = {
radius: 10,
diameter() {
return this.radius * 2;
},
perimeter: () => 2 * Math.PI * this.radius
};
shape.diameter();
shape.perimeter();
- A:
20
and62.83185307179586
- B:
20
andNaN
- C:
20
and63
- D:
NaN
and63
答案: B
请注意,diameter
是普通函数,而perimeter
是箭头函数。
对于箭头函数,this
关键字指向是它所在上下文(定义时的位置)的环境,与普通函数不同! 这意味着当我们调用perimeter
时,它不是指向shape
对象,而是指其定义时的环境(window)。没有值radius
属性,返回undefined
。
4. 下面代码的输出是什么?
+true;
!"Lydia";
- A:
1
andfalse
- B:
false
andNaN
- C:
false
andfalse
答案: A
一元加号会尝试将boolean
类型转换为数字类型。 true
被转换为1
,false
被转换为0
。
字符串'Lydia'
是一个真值。 我们实际上要问的是“这个真值是假的吗?”。 这会返回false
。
5. 哪个选项是不正确的?
const bird = {
size: "small"
};
const mouse = {
name: "Mickey",
small: true
};
- A:
mouse.bird.size
- B:
mouse[bird.size]
- C:
mouse[bird["size"]]
- D: All of them are valid
答案: A
在JavaScript
中,所有对象键都是字符串(除了Symbol
)。尽管有时我们可能不会给定字符串类型,但它们总是被转换为字符串。
JavaScript
解释语句。当我们使用方括号表示法时,它会看到第一个左括号[
,然后继续,直到找到右括号]
。只有在那个时候,它才会对这个语句求值。
mouse [bird.size]
:首先它会对bird.size
求值,得到small
。 mouse [“small”]
返回true
。
但是,使用点表示法,这不会发生。 mouse
没有名为bird
的键,这意味着mouse.bird
是undefined
。 然后,我们使用点符号来询问size
:mouse.bird.size
。 由于mouse.bird
是undefined
,我们实际上是在询问undefined.size
。 这是无效的,并将抛出Cannot read property "size" of undefined
。
6. 下面代码的输出是什么?
let c = { greeting: "Hey!" };
let d;
d = c;
c.greeting = "Hello";
console.log(d.greeting);
- A:
Hello
- B:
undefined
- C:
ReferenceError
- D:
TypeError
答案: A
在JavaScript
中,当设置它们彼此相等时,所有对象都通过引用进行交互。
首先,变量c
为对象保存一个值。 之后,我们将d
指定为c
与对象相同的引用。
更改一个对象时,可以更改所有对象。
7. 下面代码的输出是什么?
let a = 3;
let b = new Number(3);
let c = 3;
console.log(a ==