阅读 18585

[查缺补漏]再来100道JS输出题酸爽继续(共1.8W字)

前言

最近一直在复习JavaScript部分,如果停留在基础知识点的话,收获可能不是很大,所以打算空闲的时间给做一张常见的JS面试题,给自己充充电🔋🔋

当然了,肯定有人已经做过类似有趣的事情了,我觉得自己去做的话,总结一下,对巩固自己的知识点有所帮助✔️

你的鼓励点赞👍收藏是这篇文章坚持下去的动力

下面是我收集一些有趣的,易错的JS代码题,对JS基础知识点的考察都有所涉及,内容可能不全面,希望对大家有所帮助。


👨‍💻由于排版加上内容(1.8W字👍,所以打算分为两期,可以点这查看下一期)


1.下面代码的输出是什么?

const one = (false || {} || null)
const two = (null || false || "")
const three = ([] || 0 || true)

console.log(one, two, three)
复制代码
  • A: false null []
  • B: null "" true
  • C: {} "" []
  • D: null null true
答案

答案: C

使用||运算符,我们可以返回第一个真值。 如果所有值都是假值,则返回最后一个值。

(false || {} || null):空对象{}是一个真值。 这是第一个(也是唯一的)真值,它将被返回。one等于{}

(null || false ||“”):所有值都是假值。 这意味着返回传递的值""two等于""

([] || 0 ||“”):空数组[]是一个真值。 这是第一个返回的真值。 three等于[]

2.What does this return?

[..."Lydia"];
复制代码
  • A: ["L", "y", "d", "i", "a"]
  • B: ["Lydia"]
  • C: [[], "Lydia"]
  • D: [["L", "y", "d", "i", "a"]]
答案

答案: A

字符串是可迭代的。 扩展运算符将迭代的每个字符映射到一个元素。

3.下面代码的输出是什么?

[[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]是我们的初始值。 这是我们开始执行reduce函数的初始值,以及第一个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]。

4.下面代码的输出是什么?

(() => {
 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仍然是undefined,而y是2。 当我们想在catch块之外的console.log(x)时,它返回undefined,而y返回2。

5.下面代码的输出是什么?

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会创建一个名为“空插槽”的东西。 这些位置的值实际上是undefined,但你会看到类似的东西:

[1, 2, 3, 7 x empty, 11]

这取决于你运行它的位置(每个浏览器有可能不同)

6.下面代码的输出是什么?

function sayHi() {
 return (() => 0)();
}

typeof sayHi();
复制代码
  • A: "object"
  • B: "number"
  • C: "function"
  • D: "undefined"
答案

答案: **B**

sayHi函数返回立即调用的函数(IIFE)的返回值。 该函数返回0,类型为数字。

7.下面代码的输出是什么?

const person = { name: "Lydia" };

function sayHi(age) {
 console.log(`${this.name} is ${age}`);
}

sayHi.call(person, 21);
sayHi.bind(person, 21);
复制代码
  • A: undefined is 21 Lydia is 21
  • B: function function
  • C: Lydia is 21 Lydia is 21
  • D: Lydia is 21 function
答案

答案: **D**

使用两者,我们可以传递我们想要this关键字引用的对象。 但是,.call方法会立即执行!

.bind方法会返回函数的拷贝值,但带有绑定的上下文! 它不会立即执行。

8.单击下面的html片段打印的内容是什么?

<div onclick="console.log('div')">
 <p onclick="console.log('p')">
 Click here!

</div>
复制代码
  • A: p div
  • B: div p
  • C: p
  • D: div
答案

答案: **A**

如果我们单击p,我们会看到两个日志:p和div。在事件传播期间,有三个阶段:捕获,目标和冒泡。 默认情况下,事件处理程序在冒泡阶段执行(除非您将useCapture设置为true)。 它从最深的嵌套元素向外延伸。

9.下面代码的输出是什么?

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"));
const baz = () => console.log("Third");

bar();
foo();
baz();
复制代码
  • A: First Second Third
  • B: First Third Second
  • C: Second First Third
  • D: Second Third First
答案

答案: **B**

我们有一个setTimeout函数并首先调用它。 然而却最后打印了它。

这是因为在浏览器中,我们不只有运行时引擎,我们还有一个叫做WebAPI的东西。WebAPI为我们提供了setTimeout函数,例如DOM。

将callback推送到WebAPI后,setTimeout函数本身(但不是回调!)从堆栈中弹出。

10.下面代码的输出是什么?

const a = {};
const b = { key: "b" };
const c = { key: "c" };

a[b] = 123;
a[c] = 456;

console.log(a[b]);
复制代码
  • A: 123
  • B: 456
  • C: undefined
  • D: ReferenceError
答案

答案: **B**

对象键自动转换为字符串。我们试图将一个对象设置为对象a的键,其值为123。

但是,当对象自动转换为字符串化时,它变成了[Object object]。 所以我们在这里说的是a["Object object"] = 123。 然后,我们可以尝试再次做同样的事情。 c对象同样会发生隐式类型转换。那么,a["Object object"] = 456。

然后,我们打印a[b],它实际上是a["Object object"]。 我们将其设置为456,因此返回456。

11. 事件传播的三个阶段是什么?

  • A: Target > Capturing > Bubbling
  • B: Bubbling > Target > Capturing
  • C: Target > Bubbling > Capturing
  • D: Capturing > Target > Bubbling
答案

答案: D

捕获(capturing)阶段中,事件从祖先元素向下传播到目标元素。当事件达到目标(target)元素后,冒泡(bubbling)才开始。

12. 下面代码的输出是什么?

function Person(firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}

const lydia = new Person('Lydia', 'Hallie')
const sarah = Person('Sarah', 'Smith')

console.log(lydia)
console.log(sarah)
复制代码
  • A: Person {firstName: "Lydia", lastName: "Hallie"} and undefined
  • B: Person {firstName: "Lydia", lastName: "Hallie"} and Person {firstName: "Sarah", lastName: "Smith"}
  • C: Person {firstName: "Lydia", lastName: "Hallie"} and {}
  • D:Person {firstName: "Lydia", lastName: "Hallie"} and ReferenceError
答案

答案: A

对于 sarah,我们没有使用 new 关键字。当使用 new 时,this 引用我们创建的空对象。当未使用 new 时,this 引用的是全局对象(global object)。

我们说 this.firstName 等于 "Sarah",并且 this.lastName 等于 "Smith"。实际上我们做的是,定义了 global.firstName = 'Sarah'global.lastName = 'Smith'。而 sarah 本身是 undefined


13. 下面代码的输出是什么?

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const member = new Person("Lydia", "Hallie");
Person.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
}

console.log(member.getFullName());
复制代码
  • A: TypeError
  • B: SyntaxError
  • C: Lydia Hallie
  • D: undefined undefined
答案

答案: A

你不能像常规对象那样,给构造函数添加属性。如果你想一次性给所有实例添加特性,你应该使用原型。因此本例中,使用如下方式:

Person.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
}
复制代码

这才会使 member.getFullName() 起作用。为什么这么做有益的?假设我们将这个方法添加到构造函数本身里。也许不是每个 Person 实例都需要这个方法。这将浪费大量内存空间,因为它们仍然具有该属性,这将占用每个实例的内存空间。相反,如果我们只将它添加到原型中,那么它只存在于内存中的一个位置,但是所有实例都可以访问它!


14. 所有对象都有原型

  • A: true
  • B: false
答案

答案: B

除了基本对象(base object),所有对象都有原型。基本对象可以访问一些方法和属性,比如 .toString。这就是为什么你可以使用内置的 JavaScript 方法!所有这些方法在原型上都是可用的。虽然 JavaScript 不能直接在对象上找到这些方法,但 JavaScript 会沿着原型链找到它们,以便于你使用。

15. 下面代码的输出是什么?

function sum(a, b) {
  return a + b
}

sum(1, '2')
复制代码
  • A: NaN
  • B: TypeError
  • C: "12"
  • D: 3
答案

答案: C

JavaScript 是一种动态类型语言:我们不指定某些变量的类型。值可以在你不知道的情况下自动转换成另一种类型,这种类型称为隐式类型转换(implicit type coercion)。Coercion 是指将一种类型转换为另一种类型。

在本例中,JavaScript 将数字 1 转换为字符串,以便函数有意义并返回一个值。在数字类型(1)和字符串类型('2')相加时,该数字被视为字符串。我们可以连接字符串,比如 "Hello" + "World",这里发生的是 "1" + "2",它返回 "12"


16. 下面代码的输出是什么?

let number = 0
console.log(number++)
console.log(++number)
console.log(number)
复制代码
  • A: 1 1 2
  • B: 1 2 2
  • C: 0 2 2
  • D: 0 1 2
答案

答案: C

一元后自增运算符 ++

  1. 返回值(返回 0
  2. 值自增(number 现在是 1

一元前自增运算符 ++

  1. 值自增(number 现在是 2
  2. 返回值(返回 2

结果是 0 2 2.


17. 下面代码的输出是什么?

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

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


18. 下面代码的输出是什么?

function checkAge(data) {
  if (data === { age: 18 }) {
    console.log('You are an adult!')
  } else if (data == { age: 18 }) {
    console.log('You are still an adult.')
  } else {
    console.log(`Hmm.. You don't have an age I guess`)
  }
}

checkAge({ age: 18 })
复制代码
  • A: You are an adult!
  • B: You are still an adult.
  • C: Hmm.. You don't have an age I guess
答案

答案: C

在测试相等性时,基本类型通过它们的值(value)进行比较,而对象通过它们的引用(reference)进行比较。JavaScript 检查对象是否具有对内存中相同位置的引用。

题目中我们正在比较的两个对象不是同一个引用:作为参数传递的对象引用的内存位置,与用于判断相等的对象所引用的内存位置并不同。

这也是 { age: 18 } === { age: 18 }{ age: 18 } == { age: 18 } 都返回 false 的原因。


19. 下面代码的输出是什么?

function getAge(...args) {
  console.log(typeof args)
}

getAge(21)
复制代码
  • A: "number"
  • B: "array"
  • C: "object"
  • D: "NaN"
答案

答案: C

扩展运算符(...args)会返回实参组成的数组。而数组是对象,因此 typeof args 返回 "object"


20. 下面代码的输出是什么?

function getAge() {
  'use strict'
  age = 21
  console.log(age)
}

getAge()
复制代码
  • A: 21
  • B: undefined
  • C: ReferenceError
  • D: TypeError
答案

答案: C

使用 "use strict",你可以确保不会意外地声明全局变量。我们从来没有声明变量 age,因为我们使用 "use strict",它将抛出一个引用错误。如果我们不使用 "use strict",它就会工作,因为属性 age 会被添加到全局对象中了。


21. 下面代码的输出是什么?

const getList = ([x, ...y]) => [x, y]
const getUser = user => { name: user.name, age: user.age }

const list = [1, 2, 3, 4]
const user = { name: "Lydia", age: 21 }

console.log(getList(list))
console.log(getUser(user))
复制代码
  • A: [1, [2, 3, 4]] and undefined
  • B: [1, [2, 3, 4]] and { name: "Lydia", age: 21 }
  • C: [1, 2, 3, 4] and { name: "Lydia", age: 21 }
  • D: Error and { name: "Lydia", age: 21 }
答案

答案: A

getList函数接收一个数组作为其参数。 在getList函数的括号之间,我们立即解构这个数组。 您可以将其视为:

[x, ...y] = [1, 2, 3, 4]

使用剩余的参数... y,我们将所有剩余参数放在一个数组中。 在这种情况下,其余的参数是234y的值是一个数组,包含所有其余参数。 在这种情况下,x的值等于1,所以当我们打印[x,y]时,会打印[1,[2,3,4]]

getUser函数接收一个对象。对于箭头函数,如果只返回一个值,我们不必编写花括号。但是,如果您想从一个箭头函数返回一个对象,您必须在圆括号之间编写它,否则不会返回任何值!下面的函数将返回一个对象:

const getUser = user => ({ name: user.name, age: user.age })

由于在这种情况下不返回任何值,因此该函数返回undefined


22. 下面代码的输出是什么?

const info = {
  [Symbol('a')]: 'b'
}

console.log(info)
console.log(Object.keys(info))
复制代码
  • A: {Symbol('a'): 'b'} and ["{Symbol('a')"]
  • B: {} and []
  • C: { a: "b" } and ["a"]
  • D: {Symbol('a'): 'b'} and []
答案

答案: D

Symbol类型是不可枚举的。Object.keys方法返回对象上的所有可枚举的键属性。Symbol类型是不可见的,并返回一个空数组。 记录整个对象时,所有属性都是可见的,甚至是不可枚举的属性。

这是Symbol的众多特性之一:除了表示完全唯一的值(防止对象意外名称冲突,例如当使用2个想要向同一对象添加属性的库时),您还可以隐藏这种方式对象的属性(尽管不完全。你仍然可以使用Object.getOwnPropertySymbols()方法访问 Symbol


23. 下面代码的输出是什么?

class Person {
  constructor() {
    this.name = "Lydia"
  }
}

Person = class AnotherPerson {
  constructor() {
    this.name = "Sarah"
  }
}

const member = new Person()
console.log(member.name)
复制代码
  • A: "Lydia"
  • B: "Sarah"
  • C: Error: cannot redeclare Person
  • D: SyntaxError
答案

答案: B

我们可以将类设置为等于其他类/函数构造函数。 在这种情况下,我们将Person设置为AnotherPerson。 这个构造函数的名字是Sarah,所以新的Person实例member上的name属性是Sarah


24. 下面代码的输出是什么?

function nums(a, b) {
  if
  (a > b)
  console.log('a is bigger')
  else 
  console.log('b is bigger')
  return 
  a + b
}

console.log(nums(4, 2))
console.log(nums(1, 2))
复制代码
  • A: a is bigger, 6 and b is bigger, 3
  • B: a is bigger, undefined and b is bigger, undefined
  • C: undefined and undefined
  • D: SyntaxError
答案

答案: B

在JavaScript中,我们不必显式地编写分号(;),但是JavaScript引擎仍然在语句之后自动添加分号。这称为自动分号插入。例如,一个语句可以是变量,或者像throwreturnbreak这样的关键字。

在这里,我们在新的一行上写了一个return语句和另一个值a + b。然而,由于它是一个新行,引擎并不知道它实际上是我们想要返回的值。相反,它会在return后面自动添加分号。你可以这样看:

  return;
  a + b
复制代码

这意味着永远不会到达a + b,因为函数在return关键字之后停止运行。如果没有返回值,就像这里,函数返回undefined。注意,在if/else语句之后没有自动插入!


25. 下面代码的输出是什么?

function getItems(fruitList, ...args, favoriteFruit) {
  return [...fruitList, ...args, favoriteFruit]
}

getItems(["banana", "apple"], "pear", "orange")
复制代码
  • A: ["banana", "apple", "pear", "orange"]
  • B: [["banana", "apple"], "pear", "orange"]
  • C: ["banana", "apple", ["pear"], "orange"]
  • D: SyntaxError
答案

答案: D

... args是剩余参数,剩余参数的值是一个包含所有剩余参数的数组,并且只能作为最后一个参数。上述示例中,剩余参数是第二个参数,这是不可能的,并会抛出语法错误。

function getItems(fruitList, favoriteFruit, ...args) {
  return [...fruitList, ...args, favoriteFruit]
}

getItems(["banana", "apple"], "pear", "orange")
复制代码

上述例子是有效的,将会返回数组:[ 'banana', 'apple', 'orange', 'pear' ]


26. 下面代码的输出是什么?

const person = {
  name: "Lydia",
  age: 21
}

for (const [x, y] of Object.entries(person)) {
  console.log(x, y)
}
复制代码
  • A: name Lydia and age 21
  • B: ["name", "Lydia"] and ["age", 21]
  • C: ["name", "age"] and undefined
  • D: Error
答案

答案: A

Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,上述情况返回一个二维数组,数组每个元素是一个包含键和值的数组:

[['name','Lydia'],['age',21]]

使用for-of循环,我们可以迭代数组中的每个元素,上述情况是子数组。 我们可以使用const [x,y]for-of循环中解构子数组。 x等于子数组中的第一个元素,y等于子数组中的第二个元素。

第一个子阵列是[“name”,“Lydia”],其中x等于name,而y等于Lydia。 第二个子阵列是[“age”,21],其中x等于age,而y等于21


27. 下面代码的输出是什么?

function giveLydiaPizza() {
  return "Here is pizza!"
}

const giveLydiaChocolate = () => "Here's chocolate... now go hit the gym already."

console.log(giveLydiaPizza.prototype)
console.log(giveLydiaChocolate.prototype)
复制代码
  • A: { constructor: ...} { constructor: ...}
  • B: {} { constructor: ...}
  • C: { constructor: ...} {}
  • D: { constructor: ...} undefined
答案

答案: D

常规函数,例如giveLydiaPizza函数,有一个prototype属性,它是一个带有constructor属性的对象(原型对象)。 然而,箭头函数,例如giveLydiaChocolate函数,没有这个prototype属性。 尝试使用giveLydiaChocolate.prototype访问prototype属性时会返回undefined


28. 下面代码的输出是什么?

let newList = [1, 2, 3].push(4)

console.log(newList.push(5))
复制代码
  • A: [1, 2, 3, 4, 5]
  • B: [1, 2, 3, 5]
  • C: [1, 2, 3, 4]
  • D: Error
答案

答案: D

.push方法返回数组的长度,而不是数组本身! 通过将newList设置为[1,2,3].push(4),实际上newList等于数组的新长度:4

然后,尝试在newList上使用.push方法。 由于newList是数值4,抛出TypeError。


29.下面代码的输出是什么?

console.log("I want pizza"[0])
复制代码
  • A: """
  • B: "I"
  • C: SyntaxError
  • D: undefined
答案

答案: B

可以使用方括号表示法获取字符串中特定索引的字符,字符串中的第一个字符具有索引0,依此类推。 在这种情况下,我们想要得到索引为0的元素,字符'I'被记录。

请注意,IE7及更低版本不支持此方法。 在这种情况下,应该使用.charAt()


30. 下面代码的输出是什么?

function sum(num1, num2 = num1) {
  console.log(num1 + num2)
}

sum(10)
复制代码
  • A: NaN
  • B: 20
  • C: ReferenceError
  • D: undefined
答案

答案: B

您可以将默认参数的值设置为函数的另一个参数,只要另一个参数定义在其之前即可。 我们将值10传递给sum函数。 如果sum函数只接收1个参数,则意味着没有传递num2的值,这种情况下,num1的值等于传递的值10num2的默认值是num1的值,即10num1 + num2返回20

如果您尝试将默认参数的值设置为后面定义的参数,则可能导致参数的值尚未初始化,从而引发错误。比如:

function test(m = n, n = 2) {
 console.log(m, n)
}
test() // Uncaught ReferenceError: Cannot access 'n' before initialization
test(3) // 3 2
test(3, 4) // 3 4
复制代码


31. 下面代码的输出是什么?

// module.js 
export default () => "Hello world"
export const name = "Lydia"

// index.js 
import * as data from "./module"

console.log(data)
复制代码
  • A: { default: function default(), name: "Lydia" }
  • B: { default: function default() }
  • C: { default: "Hello world", name: "Lydia" }
  • D: Global object of module.js
答案

答案: A

使用import * as name语法,我们将module.js文件中所有export导入到index.js文件中,并且创建了一个名为data的新对象。 在module.js文件中,有两个导出:默认导出和命名导出。 默认导出是一个返回字符串“Hello World”的函数,命名导出是一个名为name的变量,其值为字符串“Lydia”

data对象具有默认导出的default属性,其他属性具有指定exports的名称及其对应的值。


32. 下面代码的输出是什么?

class Person {
  constructor(name) {
    this.name = name
  }
}

const member = new Person("John")
console.log(typeof member)
复制代码
  • A: "class"
  • B: "function"
  • C: "object"
  • D: "string"
答案

答案: C

类是构造函数的语法糖,如果用构造函数的方式来重写Person类则将是:

function Person() {
  this.name = name
}
复制代码

通过new来调用构造函数,将会生成构造函数Person的实例,对实例执行typeof关键字将返回"object",上述情况打印出"object"


33. 下面代码的输出是什么?

const person = { name: 'Lydia' }

function sayHi(age) {
  console.log(`${this.name} is ${age}`)
}

sayHi.call(person, 21)
sayHi.bind(person, 21)
复制代码
  • A: undefined is 21 Lydia is 21
  • B: function function
  • C: Lydia is 21 Lydia is 21
  • D: Lydia is 21 function
答案

答案: D

使用这两种方法,我们都可以传递我们希望 this 关键字引用的对象。但是,.call立即执行的。

.bind 返回函数的副本,但带有绑定上下文!它不是立即执行的。


34. 下面代码的输出是什么?

function sayHi() {
  return (() => 0)()
}

typeof sayHi()
复制代码
  • A: "object"
  • B: "number"
  • C: "function"
  • D: "undefined"
答案

答案: B

sayHi 方法返回的是立即执行函数(IIFE)的返回值.此立即执行函数的返回值是 0, 类型是 number

参考:只有7种内置类型:nullundefinedbooleannumberstringobjectsymbolfunction 不是一种类型,函数是对象,它的类型是object


35. 下面代码的输出是什么?

0
new Number(0)
('')
(' ')
new Boolean(false)
undefined
复制代码
  • A: 0, '', undefined
  • B: 0, new Number(0), '', new Boolean(false), undefined
  • C: 0, '', new Boolean(false), undefined
  • D: All of them are falsy
答案

答案: A

只有 6 种 falsy 值:

  • undefined
  • null
  • NaN
  • 0
  • '' (empty string)
  • false

Function 构造函数, 比如 new Numbernew Boolean,是 truthy


36. 下面代码的输出是什么?

console.log(typeof typeof 1)
复制代码
  • A: "number"
  • B: "string"
  • C: "object"
  • D: "undefined"
答案

答案: B

typeof 1 返回 "number"typeof "number" 返回 "string"


37. 下面代码的输出是什么?

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 环境,都有可能不同)


38. 下面代码的输出是什么?

(() => {
  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


39. 下面代码的输出是什么?

  • A: 基本类型与对象
  • B: 函数与对象
  • C: 只有对象
  • D: 数字与对象
答案

答案: A

JavaScript 只有基本类型和对象。

基本类型包括 boolean, null, undefined, bigint, number, string, symbol


40. 下面代码的输出是什么?

[[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]


上一期传送门

上一期传送门

❤️ 感谢大家

如果你觉得这篇内容对你挺有有帮助的话:

  1. 点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)

  2. 欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。

  3. 觉得不错的话,也可以看看往期文章:

    [[诚意满满👍]Chrome DevTools调试小技巧,效率➡️🚀🚀🚀

    [干货👍]从详细操作js数组到浅析v8中array.js

    [1.2W字👍]写给女友的秘籍-浏览器工作原理(上)篇

    [1.1W字]写给女友的秘籍-浏览器工作原理(渲染流程)篇

    [建议👍]再来100道JS输出题酸爽继续(共1.8W字+巩固JS基础)

    「算法与数据结构」链表的9个基本操作

本文使用 mdnice 排版