# 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);
1
  • 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);
1
2
3
4
5
  • A: false, true
  • B: "Lydia", 21
  • C: true, true
  • D: undefined, undefined
答案

# 答案: A

delete操作符返回一个布尔值: true指删除成功,否则返回false. 但是通过 var, constlet 关键字声明的变量无法用 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);
1
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)
1
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)2Boolean(false)new Boolean(false)falseSymbol('foo')Symbol.for('foo')
  • 128 Number.isNaNisNaN 区别

# 函数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)
}
1
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')
1
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)
})()
1
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 的值仍为 undefinedy 的值为 2。当我们在 catch 块之外执行 console.log(x) 时,返回 undefinedy 返回 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();
1
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;
1
2
3
// index.js
import myCounter from "./counter";

myCounter += 1;

console.log(myCounter);
1
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]
)
1
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);
1
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')
1
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`
1
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
答案

# 答案: B

如果使用标记模板字面量,第一个参数的值总是包含字符串的数组。其余的参数获取的是传递的表达式的值!


# ES6解构


# 输出是什么?
[...'Lydia']
1
  • A: ["L", "y", "d", "i", "a"]
  • B: ["Lydia"]
  • C: [[], "Lydia"]
  • D: [["L", "y", "d", "i", "a"]]
答案

# 答案: A

string 类型是可迭代的。扩展运算符将迭代的每个字符映射成一个元素。


# 参考资料

测试题 (opens new window) javascript-questions (opens new window)

上次更新: 1/5/2022, 9:25:14 AM