Skip to content

JS精选题集

JS设计缺陷

  • undefined 未定义成关键字(使用 void 0 替代)
  • typeof 判断 null 和 Object 都是 Object(使用其他类型判断方式,如 Object.prototype.toString
  • var变量提升导致变量覆盖和变量污染(ES6引入块级作用域)
  • this 不能继承外层函数的 this 值(使用箭头函数或定义self)

一、基础语法相关

运算符

  • 63 自加操作
  • 119 ES10可选链操作符?

num的值是什么?
javascript
const num = parseInt("7*6", 10);
  • A: 42
  • B: "42"
  • C: 7
  • D: NaN
答案

答案: C

只返回了字符串中第一个字母. 设定了 进制 后 (也就是第二个参数,指定需要解析的数字是什么进制: 十进制、十六机制、八进制、二进制等等……),parseInt 检查字符串中的字符是否合法. 一旦遇到一个在指定进制中不合法的字符后,立即停止解析并且忽略后面所有的字符。

*就是不合法的数字字符。所以只解析到"7",并将其解析为十进制的7. num的值即为7.


输出是什么?
javascript
const name = "Lydia";
age = 21;

console.log(delete name);
console.log(delete age);
  • 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.


输出是什么?
javascript
const settings = {
  username: "lydiahallie",
  level: 19,
  health: 90
};

const data = JSON.stringify(settings, ["level", "health"]);
console.log(data);
  • 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 类数组结构有什么特点?

输出是什么?
javascript
const numbers = [1, 2, 3]
numbers[10] = 11
console.log(numbers)
  • 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上有哪些方法?

四、执行机制相关


分析输入结果:

js
for (var i = 1; i < 3; i++) {}
  setTimeout(() => {console.log(i)}, 0)
}
for (let i = 1; i < 3; i++) {}
  setTimeout(() => {console.log(i)}, 0)
}
答案

答案: 3 3 3 1 2 3

var声明的变量i是全局作用域,因此查找时找到的是全局作用域中的i,即遍历完成之后的i,值为 3 3 3 而let声音的变量拥有块级作用域,因此查找时找到的是块级作用域中的i,相互独立,值为 1 2 3


  • 82

五、异步相关

异步代码输出顺序:
js
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')
  • 71 140 yield
  • 73 async await
  • 124 for await ... of
  • 133 异步代码执行顺序
  • 152 promise.all

六、异常处理


输出是什么?
javascript
(() => {
  let x, y
  try {
    throw new Error()
  } catch (x) {
    (x = 1), (y = 2)
    console.log(x)
  }
  console.log(x)
  console.log(y)
})()
  • 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


输出是什么?
javascript
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();
  • 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"

输出是什么?
javascript
// counter.js
let counter = 10;
export default counter;
javascript
// index.js
import myCounter from "./counter";

myCounter += 1;

console.log(myCounter);
  • A: 10
  • B: 11
  • C: Error
  • D: NaN
答案

答案: C

引入的模块是 只读 的: 你不能修改引入的模块。只有导出他们的模块才能修改其值。

当我们给myCounter增加一个值的时候会抛出一个异常: myCounter是只读的,不能被修改。


八、ECMAScript新特性

Array.prototype.reduce


输出是什么?
javascript
[[0, 1], [2, 3]].reduce(
  (acc, cur) => {
    return acc.concat(cur)
  },
  [1, 2]
)
  • 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


输出是什么?
javascript
const set = new Set([1, 1, 2, 3, 4]);

console.log(set);
  • 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


输出是什么?
javascript
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')
答案

colorChange 是一个静态方法。静态方法被设计为只能被创建它们的构造器使用(也就是 Chameleon),并且不能传递给实例。因为 freddie 是一个实例,静态方法不能被实例使用,因此抛出了 TypeError 错误。


标记模板字面量

输出是什么?
javascript
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`
  • A: "Lydia" 21 ["", " is ", " years old"]
  • B: ["", " is ", " years old"] "Lydia" 21
  • C: "Lydia" ["", " is ", " years old"] 21
答案

答案: B

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


ES6解构


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

答案: A

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


参考资料

测试题javascript-questions

MIT Licensed | 沪ICP备20013265号-1 | Copyright © 2019-present AaronKong