# JS精选题集
# JS设计缺陷
- undefined 未定义成关键字(使用 void 0 替代)
- typeof 判断 null 和 Object 都是 Object(使用其他类型判断方式,如
Object.prototype.toString
) - var变量提升导致变量覆盖和变量污染(ES6引入块级作用域)
- this 不能继承外层函数的 this 值(使用箭头函数或定义self)
# 一、基础语法相关
# 运算符
- 63 自加操作
- 119 ES10可选链操作符?
# num
的值是什么?
const num = parseInt("7*6", 10);
- A:
42
- B:
"42"
- C:
7
- D:
NaN
答案
# 答案: C
只返回了字符串中第一个字母. 设定了 进制 后 (也就是第二个参数,指定需要解析的数字是什么进制: 十进制、十六机制、八进制、二进制等等……),parseInt
检查字符串中的字符是否合法. 一旦遇到一个在指定进制中不合法的字符后,立即停止解析并且忽略后面所有的字符。
*
就是不合法的数字字符。所以只解析到"7"
,并将其解析为十进制的7
. num
的值即为7
.
# 输出是什么?
const name = "Lydia";
age = 21;
console.log(delete name);
console.log(delete age);
2
3
4
5
- A:
false
,true
- B:
"Lydia"
,21
- C:
true
,true
- D:
undefined
,undefined
答案
# 答案: A
delete
操作符返回一个布尔值: true
指删除成功,否则返回false
. 但是通过 var
, const
或 let
关键字声明的变量无法用 delete
操作符来删除。
name
变量由const
关键字声明,所以删除不成功:返回 false
. 而我们设定age
等于21
时,我们实际上添加了一个名为age
的属性给全局对象。对象中的属性是可以删除的,全局对象也是如此,所以delete age
返回true
.
# 输出是什么?
const settings = {
username: "lydiahallie",
level: 19,
health: 90
};
const data = JSON.stringify(settings, ["level", "health"]);
console.log(data);
2
3
4
5
6
7
8
- A:
"{"level":19, "health":90}"
- B:
"{"username": "lydiahallie"}"
- C:
"["level", "health"]"
- D:
"{"username": "lydiahallie", "level":19, "health":90}"
答案
# 答案: A
JSON.stringify
的第二个参数是 替代者(replacer). 替代者(replacer)可以是个函数或数组,用以控制哪些值如何被转换为字符串。
如果替代者(replacer)是个 数组 ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为"level"
和 "health"
的属性被包括进来, "username"
则被排除在外。 data
就等于 "{"level":19, "health":90}"
.
而如果替代者(replacer)是个 函数,这个函数将被对象的每个属性都调用一遍。
函数返回的值会成为这个属性的值,最终体现在转化后的JSON字符串中(译者注:Chrome下,经过实验,如果所有属性均返回同一个值的时候有异常,会直接将返回值作为结果输出而不会输出JSON字符串),而如果返回值为undefined
,则该属性会被排除在外。
# 语句
- 79
for...in
for...of
- 95 js引擎自动加分号
- 99 语句错误类型: ReferenceError TypeError SyntaxError
- 144 给对象定义迭代器
# 二、类型相关
# 字符串String
- 69 字符串操作 String.prototype.padStart
- 72 字符串操作 String.raw
# 数组Array
- 74 Array.prototype.push 返回值为数组size
- 65 reduce使用
- 93 117 数组解构
- argument 类数组结构有什么特点?
# 输出是什么?
const numbers = [1, 2, 3]
numbers[10] = 11
console.log(numbers)
2
3
- A:
[1, 2, 3, 7 x null, 11]
- B:
[1, 2, 3, 11]
- C:
[1, 2, 3, 7 x empty, 11]
- D:
SyntaxError
答案
# 答案: C
当你为数组设置超过数组长度的值的时候, JavaScript 会创建名为 "empty slots" 的东西。它们的值实际上是 undefined
。你会看到以下场景:
[1, 2, 3, 7 x empty, 11]
这取决于你的运行环境(每个浏览器,以及 node 环境,都有可能不同)
# 对象Object
- 76 对象解构
- 97 Symbol不可枚举,Object.keys for...in 均不可获取
- 135 proxy的使用
- 136 Object.seal的作用
- 137 Object.freeze的作用
# 类型判断
- 68
Number(2)
和new Number(2)
和2
,Boolean(false)
和new Boolean(false)
和false
,Symbol('foo')
和Symbol.for('foo')
- 128
Number.isNaN
和isNaN
区别
# 函数Function
- 64 值传递引用传递
- 78 闭包
- 92 箭头函数无原型
- 98 数组解构和箭头函数
# 三、原型原型链相关
# 所有对象都有原型。
- A: 对
- B: 错
答案
# 答案: B
除了基本对象(base object),所有对象都有原型。基本对象可以访问一些方法和属性,比如 .toString
。这就是为什么你可以使用内置的 JavaScript 方法!所有这些方法在原型上都是可用的。虽然 JavaScript 不能直接在对象上找到这些方法,但 JavaScript 会沿着原型链找到它们,以便于你使用。
# {}
new Object()
Object.create()
区别
# var a = {}
a上有哪些方法?
# 四、执行机制相关
分析输入结果:
for (var i = 1; i < 3; i++) {}
setTimeout(() => {console.log(i)}, 0)
}
for (let i = 1; i < 3; i++) {}
setTimeout(() => {console.log(i)}, 0)
}
2
3
4
5
6
答案
# 答案: 3 3 3
1 2 3
var声明的变量i是全局作用域,因此查找时找到的是全局作用域中的i,即遍历完成之后的i,值为 3 3 3
而let声音的变量拥有块级作用域,因此查找时找到的是块级作用域中的i,相互独立,值为 1 2 3
- 82
# 五、异步相关
# 异步代码输出顺序:
console.log('script start')
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 start')
}
async1()
setTimeout(() => {
console.log('timeout')
}, 0)
Promise.resolve().then(() => {
console.log('promise1')
}).then(() => {
console.log('promise1 then')
})
console.log('script end')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- 71 140 yield
- 73 async await
- 124 for await ... of
- 133 异步代码执行顺序
- 152 promise.all
# 六、异常处理
# 输出是什么?
(() => {
let x, y
try {
throw new Error()
} catch (x) {
(x = 1), (y = 2)
console.log(x)
}
console.log(x)
console.log(y)
})()
2
3
4
5
6
7
8
9
10
11
- A:
1
undefined
2
- B:
undefined
undefined
undefined
- C:
1
1
2
- D:
1
undefined
undefined
答案
# 答案: A
catch
代码块接收参数 x
。当我们传递参数时,这与之前定义的变量 x
不同 。这个 x
是属于 catch
块级作用域的。
然后,我们将块级作用域中的变量赋值为 1
,同时也设置了变量 y
的值。现在,我们打印块级作用域中的变量 x
,值为 1
。
catch
块之外的变量 x
的值仍为 undefined
, y
的值为 2
。当我们在 catch
块之外执行 console.log(x)
时,返回 undefined
,y
返回 2
。
# 输出是什么?
function greeting() {
throw "Hello world!";
}
function sayHi() {
try {
const data = greeting();
console.log("It worked!", data);
} catch (e) {
console.log("Oh no an error:", e);
}
}
sayHi();
2
3
4
5
6
7
8
9
10
11
12
13
14
- A:
"It worked! Hello world!"
- B:
"Oh no an error: undefined
- C:
SyntaxError: can only throw Error objects
- D:
"Oh no an error: Hello world!
答案
# 答案: D
通过throw
语句,我么可以创建自定义错误。 而通过它,我们可以抛出异常。异常可以是一个字符串, 一个 数字, 一个 布尔类型 或者是一个 对象。在本例中,我们的异常是字符串'Hello world'
.
通过 catch
语句,我们可以设定当try
语句块中抛出异常后应该做什么处理。在本例中抛出的异常是字符串'Hello world'
. e
就是这个字符串,因此被输出。最终结果就是'Oh an error: Hello world'
.
# 七、模块化相关
- 67 import模块提前到编译阶段即执行
- 89 export default 和 export const name = 'xxx' 可以同时导出出来
- 134
import * as sum from "./sum"
# 输出是什么?
// counter.js
let counter = 10;
export default counter;
2
3
// index.js
import myCounter from "./counter";
myCounter += 1;
console.log(myCounter);
2
3
4
5
6
- A:
10
- B:
11
- C:
Error
- D:
NaN
答案
# 答案: C
引入的模块是 只读 的: 你不能修改引入的模块。只有导出他们的模块才能修改其值。
当我们给myCounter
增加一个值的时候会抛出一个异常: myCounter
是只读的,不能被修改。
# 八、ECMAScript新特性
# Array.prototype.reduce
# 输出是什么?
[[0, 1], [2, 3]].reduce(
(acc, cur) => {
return acc.concat(cur)
},
[1, 2]
)
2
3
4
5
6
- A:
[0, 1, 2, 3, 1, 2]
- B:
[6, 1, 2]
- C:
[1, 2, 0, 1, 2, 3]
- D:
[1, 2, 6]
答案
# 答案: C
[1, 2]
是初始值。初始值将会作为首次调用时第一个参数 acc
的值。在第一次执行时, acc
的值是 [1, 2]
, cur
的值是 [0, 1]
。合并它们,结果为 [1, 2, 0, 1]
。
第二次执行, acc
的值是 [1, 2, 0, 1]
, cur
的值是 [2, 3]
。合并它们,最终结果为 [1, 2, 0, 1, 2, 3]
# Set
# 输出是什么?
const set = new Set([1, 1, 2, 3, 4]);
console.log(set);
2
3
- A:
[1, 1, 2, 3, 4]
- B:
[1, 2, 3, 4]
- C:
{1, 1, 2, 3, 4}
- D:
{1, 2, 3, 4}
答案
# 答案: D
Set
对象是独一无二的值的集合:也就是说同一个值在其中仅出现一次。
我们传入了数组[1, 1, 2, 3, 4]
,他有一个重复值1
.以为一个集合里不能有两个重复的值,其中一个就被移除了。所以结果是 {1, 2, 3, 4}
.
# Map
# class
# 输出是什么?
class Chameleon {
static colorChange(newColor) {
this.newColor = newColor
return this.newColor
}
constructor({ newColor = 'green' } = {}) {
this.newColor = newColor
}
}
const freddie = new Chameleon({ newColor: 'purple' })
freddie.colorChange('orange')
2
3
4
5
6
7
8
9
10
11
12
13
答案
colorChange
是一个静态方法。静态方法被设计为只能被创建它们的构造器使用(也就是 Chameleon
),并且不能传递给实例。因为 freddie
是一个实例,静态方法不能被实例使用,因此抛出了 TypeError
错误。
# 标记模板字面量
# 输出是什么?
function getPersonInfo(one, two, three) {
console.log(one)
console.log(two)
console.log(three)
}
const person = 'Lydia'
const age = 21
getPersonInfo`${person} is ${age} years old`
2
3
4
5
6
7
8
9
10
- A:
"Lydia"
21
["", " is ", " years old"]
- B:
["", " is ", " years old"]
"Lydia"
21
- C:
"Lydia"
["", " is ", " years old"]
21
# ES6解构
# 输出是什么?
[...'Lydia']
- A:
["L", "y", "d", "i", "a"]
- B:
["Lydia"]
- C:
[[], "Lydia"]
- D:
[["L", "y", "d", "i", "a"]]
# 参考资料
测试题 (opens new window) javascript-questions (opens new window)