05.代码输出结果

1. 输出是什么?

function sayHi() {
  console.log(name)
  console.log(age)
  var name = 'Lydia'
  let age = 21
}

sayHi()
  • A: Lydiaundefined
  • B: LydiaReferenceError
  • C: ReferenceError21
  • D: undefinedReferenceError

我的:D(ok)


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 20 1 2
  • B: 0 1 23 3 3
  • C: 3 3 30 1 2

我的:C(ok)


3. 输出是什么?

const shape = {
  radius: 10,
  diameter() {
    return this.radius * 2
  },
  perimeter: () => 2 * Math.PI * this.radius
}

shape.diameter()
shape.perimeter()
  • A: 20 and 62.83185307179586
  • B: 20 and NaN
  • C: 20 and 63
  • D: NaN and 63

我的:A(error) 正确:B

注意 `diameter` 的值是一个常规函数,但是 `perimeter` 的值是一个箭头函数。

对于箭头函数,`this` 关键字指向的是它当前周围作用域(简单来说是包含箭头函数的常规函数,如果没有常规函数的话就是全局对象),这个行为和常规函数不同。这意味着当我们调用 `perimeter` 时,`this` 不是指向 `shape` 对象,而是它的周围作用域(在例子中是 `window`)。

在 `window` 中没有 `radius` 这个属性,因此返回 `undefined`。

4. 输出是什么?

+true;
!"Lydia";
  • A: 1 and false
  • B: false and NaN
  • C: false and false

我的:A(ok?)

一元操作符加号尝试将 bool 转为 number。`true` 转换为 number 的话为 `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

我的:D(error) 正确:A


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(ok)

在 JavaScript 中,当设置两个对象彼此相等时,它们会通过*引用*进行交互。

首先,变量 `c` 的值是一个对象。接下来,我们给 `d` 分配了一个和 `c` 对象相同的引用。

<img src="https://i.imgur.com/ko5k0fs.png" width="200">

因此当我们改变其中一个对象时,其实是改变了所有的对象。

7. 输出是什么?

let a = 3
let b = new Number(3)
let c = 3

console.log(a == b)
console.log(a === b)
console.log(b === c)
  • A: true false true
  • B: false false true
  • C: true false false
  • D: false true true

我的:C(ok)


8. 输出是什么?

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')
  • A: orange
  • B: purple
  • C: green
  • D: TypeError

我的:A(error) 正确:D

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

9. 输出是什么?

let greeting
greetign = {} // Typo!
console.log(greetign)
  • A: {}
  • B: ReferenceError: greetign is not defined
  • C: undefined

我的:A(ok)

代码打印出了一个对象,这是因为我们在全局对象上创建了一个空对象!当我们将 `greeting` 写错成 `greetign` 时,JS 解释器实际在上浏览器中将它视为 `global.greetign = {}` (或者 `window.greetign = {}`)。

为了避免这个为题,我们可以使用 `"use strict"。这能确保当你声明变量时必须赋值。

10. 当我们这么做时,会发生什么?

function bark() {
  console.log('Woof!')
}

bark.animal = 'dog'
  • A: 正常运行!
  • B: SyntaxError. 你不能通过这种方式给函数增加属性。
  • C: undefined
  • D: ReferenceError

我的:A(ok)


11. 输出是什么?

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(ok?)


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(ok?)


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

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

我的:C(error) 正确:D


14. 所有对象都有原型。

  • A: true
  • B: false

我的:?


15. 输出是什么?

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

sum(1, '2')
  • A: NaN
  • B: TypeError
  • C: "12"
  • D: 3

我的:C(ok)


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(ok)


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

我的:B(error) 正确:C


19. 输出是什么?

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

getAge(21)
  • A: "number"
  • B: "array"
  • C: "object"
  • D: "NaN"

我的:B(error) 正确:C


20. 输出是什么?

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

getAge()
  • A: 21
  • B: undefined
  • C: ReferenceError
  • D: TypeError

我的:C(ok)


21. 输出是什么?

const sum = eval('10*10+5')
  • A: 105
  • B: "105"
  • C: TypeError
  • D: "10*10+5"

我的:A(ok)


22. cool_secret 可访问多长时间?

sessionStorage.setItem('cool_secret', 123)
  • A: 永远,数据不会丢失。
  • B: 当用户关掉标签页时。
  • C: 当用户关掉整个浏览器,而不只是关掉标签页。
  • D: 当用户关闭电脑时。

我的:B(ok)


23. 输出是什么?

var num = 8
var num = 10

console.log(num)
  • A: 8
  • B: 10
  • C: SyntaxError
  • D: ReferenceError

我的:B(ok)


24. 输出是什么?

const obj = { 1: 'a', 2: 'b', 3: 'c' }
const set = new Set([1, 2, 3, 4, 5])

obj.hasOwnProperty('1')
obj.hasOwnProperty(1)
set.has('1')
set.has(1)
  • A: false true false true
  • B: false true true true
  • C: true true false true
  • D: true true true true

我的:B(error) 正确:C

所有对象的键(不包括 Symbol)在底层都是字符串,即使你自己没有将其作为字符串输入。这就是为什么 `obj.hasOwnProperty('1')` 也返回 `true`。

对于集合,它不是这样工作的。在我们的集合中没有 `'1'`:`set.has('1')` 返回 `false`。它有数字类型为 `1`,`set.has(1)` 返回 `true`。

25. 输出是什么?

const obj = { a: 'one', b: 'two', a: 'three' }
console.log(obj)
  • A: { a: "one", b: "two" }
  • B: { b: "two", a: "three" }
  • C: { a: "three", b: "two" }
  • D: SyntaxError

我的:C(ok)


26. JavaScript 全局执行上下文为你做了两件事:全局对象和 this 关键字。

  • A: true
  • B: false
  • C: it depends

我的:? 正确:A

基本执行上下文是全局执行上下文:它是代码中随处可访问的内容。

27. 输出是什么?

for (let i = 1; i < 5; i++) {
  if (i === 3) continue
  console.log(i)
}
  • A: 1 2
  • B: 1 2 3
  • C: 1 2 4
  • D: 1 3 4

我的:? 正确:C

如果某个条件返回 `true`,则 `continue` 语句跳过本次迭代。

28. 输出是什么?

String.prototype.giveLydiaPizza = () => {
  return 'Just give Lydia pizza already!'
}

const name = 'Lydia'

name.giveLydiaPizza()
  • A: "Just give Lydia pizza already!"
  • B: TypeError: not a function
  • C: SyntaxError
  • D: undefined

我的:A(ok)

`String` 是内置的构造函数,我们可以向它添加属性。我只是在它的原型中添加了一个方法。基本类型字符串被自动转换为字符串对象,由字符串原型函数生成。因此,所有 string(string 对象)都可以访问该方法!

29. 输出是什么?

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

我的:D(error) 正确:B

对象的键被自动转换为字符串。我们试图将一个对象 `b` 设置为对象 `a` 的键,且相应的值为 `123`。

然而,当字符串化一个对象时,它会变成 `"[object Object]"`。因此这里说的是,`a["[object Object]"] = 123`。然后,我们再一次做了同样的事情,`c` 是另外一个对象,这里也有隐式字符串化,于是,`a["[object Object]"] = 456`。

然后,我们打印 `a[b]`,也就是 `a["[object Object]"]`。之前刚设置为 `456`,因此返回的是 `456`。

30. 输出是什么?

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(ok)


31. 当点击按钮时,event.target是什么?

<div onclick="console.log('first div')">
  <div onclick="console.log('second div')">
    <button onclick="console.log('button')">
      Click!
    </button>
  </div>
</div>
  • A: Outer div
  • B: Inner div
  • C: button
  • D: 一个包含所有嵌套元素的数组。

我的:C(ok)

导致事件的最深嵌套的元素是事件的 target。你可以通过 `event.stopPropagation` 来停止冒泡。

32. 当您单击该段落时,日志输出是什么?

<div onclick="console.log('div')">
  <p onclick="console.log('p')">
    Click here!
  </p>
</div>
  • A: p div
  • B: div p
  • C: p
  • D: div

我的:A(ok)(gosearch)

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

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(ok)

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

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

34. 输出是什么?

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

typeof sayHi()
  • A: "object"
  • B: "number"
  • C: "function"
  • D: "undefined"

我的:? 正确:B

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

参考:只有7种内置类型:`null`,`undefined`,`boolean`,`number`,`string`,`object` 和 `symbol`。 ``function`` 不是一种类型,函数是对象,它的类型是``object``。

35. 下面哪些值是 falsy?

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

我的:B(error) 正确:A (gosearch)

只有 6 种 [falsy](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy) 值:

- `undefined`
- `null`
- `NaN`
- `0`
- `''` (empty string)
- `false`

`Function` 构造函数, 比如 `new Number` 和 `new Boolean`,是 [truthy](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy)。

36. 输出是什么?

console.log(typeof typeof 1)
  • A: "number"
  • B: "string"
  • C: "object"
  • D: "undefined"

我的:B(ok)

`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

我的:D(error) 正确: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` 的值仍为 `undefined`, `y` 的值为 `2`。当我们在 `catch` 块之外执行 `console.log(x)` 时,返回 `undefined`,`y` 返回 `2`。

39. JavaScript 中的一切都是?

  • 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 (gosearch)

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

41. 输出是什么?

!!null
!!''
!!1
  • A: false true false
  • B: false false true
  • C: false true true
  • D: true true false

我的:D(ok)(gosearch)

`null` 是 [falsy](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy)。 `!null` 的值是 `true`。 `!true` 的值是 `false`。

`""` 是 [falsy](https://developer.mozilla.org/zh-CN/docs/Glossary/Falsy)。 `!""` 的值是 `true`。  `!true` 的值是 `false`。

`1` 是 [truthy](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy)。 `!1` 的值是 `false`。 `!false` 的值是 `true`。

42. setInterval 方法的返回值是什么?

setInterval(() => console.log('Hi'), 1000)
  • A: 一个唯一的id
  • B: 该方法指定的毫秒数
  • C: 传递的函数
  • D: undefined

我的:A(ok)


43. 输出是什么?

[...'Lydia']
  • A: ["L", "y", "d", "i", "a"]
  • B: ["Lydia"]
  • C: [[], "Lydia"]
  • D: [["L", "y", "d", "i", "a"]]

我的:A(?) 正确:A

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

44. 输出是什么?

function* generator(i) {
  yield i;
  yield i * 2;
}

const gen = generator(10);

console.log(gen.next().value);
console.log(gen.next().value);
  • A: [0, 10], [10, 20]
  • B: 20, 20
  • C: 10, 20
  • D: 0, 10 and 10, 20

我的:? 正确:C (gosearch)

一般的函数在执行之后是不能中途停下的。但是,生成器函数却可以中途“停下”,之后可以再从停下的地方继续。当生成器遇到`yield`关键字的时候,会生成`yield`后面的值。注意,生成器在这种情况下不 _返回_ (_return_ )值,而是 _生成_ (_yield_)值。

首先,我们用`10`作为参数`i`来初始化生成器函数。然后使用`next()`方法一步步执行生成器。第一次执行生成器的时候,`i`的值为`10`,遇到第一个`yield`关键字,它要生成`i`的值。此时,生成器“暂停”,生成了`10`。

然后,我们再执行`next()`方法。生成器会从刚才暂停的地方继续,这个时候`i`还是`10`。于是我们走到了第二个`yield`关键字处,这时候需要生成的值是`i*2`,`i`为`10`,那么此时生成的值便是`20`。所以这道题的最终结果是`10,20`。

45. 返回值是什么?

const firstPromise = new Promise((res, rej) => {
  setTimeout(res, 500, "one");
});

const secondPromise = new Promise((res, rej) => {
  setTimeout(res, 100, "two");
});

Promise.race([firstPromise, secondPromise]).then(res => console.log(res));
  • A: "one"
  • B: "two"
  • C: "two" "one"
  • D: "one" "two"

我的:? 正确:B

当我们向`Promise.race`方法中传入多个`Promise`时,会进行 _优先_ 解析。在这个例子中,我们用`setTimeout`给`firstPromise`和`secondPromise`分别设定了500ms和100ms的定时器。这意味着`secondPromise`会首先解析出字符串`two`。那么此时`res`参数即为`two`,是为输出结果。

46. 输出是什么?

let person = { name: "Lydia" };
const members = [person];
person = null;

console.log(members);
  • A: null
  • B: [null]
  • C: [{}]
  • D: [{ name: "Lydia" }]

我的:D(?) 正确:D

首先我们声明了一个拥有`name`属性的对象 `person`。

<img src="https://i.imgur.com/TML1MbS.png" width="200">

然后我们又声明了一个变量`members`. 将首个元素赋值为变量`person`。 当设置两个对象彼此相等时,它们会通过 _引用_ 进行交互。但是当你将引用从一个变量分配至另一个变量时,其实只是执行了一个 _复制_ 操作。(注意一点,他们的引用 _并不相同_!)

<img src="https://i.imgur.com/FSG5K3F.png" width="300">

接下来我们让`person`等于`null`。

<img src="https://i.imgur.com/sYjcsMT.png" width="300">

我们没有修改数组第一个元素的值,而只是修改了变量`person`的值,因为元素(复制而来)的引用与`person`不同。`members`的第一个元素仍然保持着对原始对象的引用。当我们输出`members`数组时,第一个元素会将引用的对象打印出来。

47. 输出是什么?

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

for (const item in person) {
  console.log(item);
}
  • A: { name: "Lydia" }, { age: 21 }
  • B: "name", "age"
  • C: "Lydia", 21
  • D: ["name", "Lydia"], ["age", 21]

我的:? 正确:B

在`for-in`循环中,我们可以通过对象的key来进行迭代,也就是这里的`name`和`age`。在底层,对象的key都是字符串(如果他们不是Symbol的话)。在每次循环中,我们将`item`设定为当前遍历到的key.所以一开始,`item`是`name`,之后 `item`输出的则是`age`。

48. 输出是什么?

console.log(3 + 4 + "5");
  • A: "345"
  • B: "75"
  • C: 12
  • D: "12"

我的:A(error) 正确:B

当所有运算符的 _优先级_ 相同时,计算表达式需要确定运算符的结合顺序,即从右到左还是从左往右。在这个例子中,我们只有一类运算符`+`,对于加法来说,结合顺序就是从左到右。

`3 + 4`首先计算,得到数字`7`.

由于类型的强制转换,`7 + '5'`的结果是`"75"`. JavaScript将`7`转换成了字符串,可以参考问题15.我们可以用`+`号把两个字符串连接起来。 `"7" + "5"` 就得到了`"75"`.

49. num的值是什么?

const num = parseInt("7*6", 10);
  • A: 42
  • B: "42"
  • C: 7
  • D: NaN

我的:A(error) 正确:C

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

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

50. 输出是什么?

[1, 2, 3].map(num => {
  if (typeof num === "number") return;
  return num * 2;
});
  • A: []
  • B: [null, null, null]
  • C: [undefined, undefined, undefined]
  • D: [ 3 x empty ]

我的:C(ok)


51. 输出的是什么?

function getInfo(member, year) {
  member.name = "Lydia";
  year = "1998";
}

const person = { name: "Sarah" };
const birthYear = "1997";

getInfo(person, birthYear);

console.log(person, birthYear);
  • A: { name: "Lydia" }, "1997"
  • B: { name: "Sarah" }, "1998"
  • C: { name: "Lydia" }, "1998"
  • D: { name: "Sarah" }, "1997"

我的:B(error) 正确:A

普通参数都是 _值_ 传递的,而对象则不同,是 _引用_ 传递。所以说,`birthYear`是值传递,因为他是个字符串而不是对象。当我们对参数进行值传递时,会创建一份该值的 _复制_ 。(可以参考问题46)

变量`birthYear`有一个对`"1997"`的引用,而传入的参数也有一个对`"1997"`的引用,但二者的引用并不相同。当我们通过给 `year`赋值`"1998"`来更新`year`的值的时候我们只是更新了`year`(的引用)。此时`birthYear`仍然是`"1997"`.

而`person`是个对象。参数`member`引用与之 _相同的_ 对象。当我们修改`member`所引用对象的属性时,`person`的相应属性也被修改了,因为他们引用了相同的对象. `person`的 `name`属性也变成了 `"Lydia"`.

52. 输出是什么?

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(ok)

通过`throw`语句,我么可以创建自定义错误。 而通过它,我们可以抛出异常。异常可以是一个<b>字符串</b>, 一个 <b>数字</b>, 一个 <b>布尔类型</b> 或者是一个 <b>对象</b>。在本例中,我们的异常是字符串`'Hello world'`.

通过 `catch`语句,我们可以设定当`try`语句块中抛出异常后应该做什么处理。在本例中抛出的异常是字符串`'Hello world'`. `e`就是这个字符串,因此被输出。最终结果就是`'Oh an error: Hello world'`.

53. 输出是什么?

function Car() {
  this.make = "Lamborghini";
  return { make: "Maserati" };
}

const myCar = new Car();
console.log(myCar.make);
  • A: "Lamborghini"
  • B: "Maserati"
  • C: ReferenceError
  • D: TypeError

我的:? 正确:B

返回属性的时候,属性的值等于 _返回的_ 值,而不是构造函数中设定的值。我们返回了字符串 `"Maserati"`,所以 `myCar.make`等于`"Maserati"`.

54. 输出是什么?

(() => {
  let x = (y = 10);
})();

console.log(typeof x);
console.log(typeof y);
  • A: "undefined", "number"
  • B: "number", "number"
  • C: "object", "number"
  • D: "number", "undefined"

我的:A(ok)

`let x = y = 10;` 是下面这个表达式的缩写:

```javascript
y = 10;
let x = y;
```

我们设定`y`等于`10`时,我们实际上增加了一个属性`y`给全局对象(浏览器里的`window`, Nodejs里的`global`)。在浏览器中, `window.y`等于`10`.

然后我们声明了变量`x`等于`y`,也是`10`.但变量是使用 `let`声明的,它只作用于 _块级作用域_, 仅在声明它的块中有效;就是案例中的立即调用表达式(IIFE)。使用`typeof`操作符时, 操作值 `x`没有被定义:因为我们在`x`声明块的外部,无法调用它。这就意味着`x`未定义。未分配或是未声明的变量类型为`"undefined"`. `console.log(typeof x)`返回`"undefined"`.

而我们创建了全局变量`y`,并且设定`y`等于`10`.这个值在我们的代码各处都访问的到。 `y`已经被定义了,而且有一个`"number"`类型的值。 `console.log(typeof y)`返回`"number"`.

55. 输出是什么?

class Dog {
  constructor(name) {
    this.name = name;
  }
}

Dog.prototype.bark = function() {
  console.log(`Woof I am ${this.name}`);
};

const pet = new Dog("Mara");

pet.bark();

delete Dog.prototype.bark;

pet.bark();
  • A: "Woof I am Mara", TypeError
  • B: "Woof I am Mara","Woof I am Mara"
  • C: "Woof I am Mara", undefined
  • D: TypeError, TypeError

我的:A(ok)

我们可以用`delete`关键字删除对象的属性,对原型也是适用的。删除了原型的属性后,该属性在原型链上就不可用了。在本例中,函数`bark`在执行了`delete Dog.prototype.bark`后不可用, 然而后面的代码还在调用它。

当我们尝试调用一个不存在的函数时`TypeError`异常会被抛出。在本例中就是 `TypeError: pet.bark is not a function`,因为`pet.bark`是`undefined`.

56. 输出是什么?

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}

我的:B(error) 正确:D

`Set`对象是独一无二的值的集合:也就是说同一个值在其中仅出现一次。

我们传入了数组`[1, 1, 2, 3, 4]`,他有一个重复值`1`.以为一个集合里不能有两个重复的值,其中一个就被移除了。所以结果是 `{1, 2, 3, 4}`.

57. 输出是什么?

// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from "./counter";

myCounter += 1;

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

我的:A(error) 正确:C

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

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

58. 输出是什么?

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`, `const` 或 `let` 关键字声明的变量无法用 `delete` 操作符来删除。

`name`变量由`const`关键字声明,所以删除不成功:返回 `false`. 而我们设定`age`等于`21`时,我们实际上添加了一个名为`age`的属性给全局对象。对象中的属性是可以删除的,全局对象也是如此,所以`delete age`返回`true`.

59. 输出是什么?

const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;

console.log(y);
  • A: [[1, 2, 3, 4, 5]]
  • B: [1, 2, 3, 4, 5]
  • C: 1
  • D: [1]

我的:? 正确:C

我们可以通过解构赋值来解析来自对象的数组或属性的值,比如说:

```javascript
[a, b] = [1, 2];
```

<img src="https://i.imgur.com/ADFpVop.png" width="200">

`a`的值现在是`1`,`b`的值现在是`2`.而在题目中,我们是这么做的:

```javascript
[y] = [1, 2, 3, 4, 5];
```

<img src="https://i.imgur.com/NzGkMNk.png" width="200">

也就是说,`y`等于数组的第一个值就是数字`1`.我们输出`y`, 返回`1`.

60. 输出是什么?

const user = { name: "Lydia", age: 21 };
const admin = { admin: true, ...user };

console.log(admin);
  • A: { admin: true, user: { name: "Lydia", age: 21 } }
  • B: { admin: true, name: "Lydia", age: 21 }
  • C: { admin: true, user: ["Lydia", 21] }
  • D: { admin: true }

我的:B(ok)


61. 输出是什么?

const person = { name: "Lydia" };

Object.defineProperty(person, "age", { value: 21 });

console.log(person);
console.log(Object.keys(person));
  • A: { name: "Lydia", age: 21 }, ["name", "age"]
  • B: { name: "Lydia", age: 21 }, ["name"]
  • C: { name: "Lydia"}, ["name", "age"]
  • D: { name: "Lydia"}, ["age"]

我的:A(error) 正确:B

通过`defineProperty`方法,我们可以给对象添加一个新属性,或者修改已经存在的属性。而我们使用`defineProperty`方法给对象添加了一个属性之后,属性默认为 _不可枚举(not enumerable)_. `Object.keys`方法仅返回对象中 _可枚举(enumerable)_ 的属性,因此只剩下了`"name"`.

用`defineProperty`方法添加的属性默认不可变。你可以通过`writable`, `configurable` 和 `enumerable`属性来改变这一行为。这样的话, 相比于自己添加的属性,`defineProperty`方法添加的属性有了更多的控制权。

62. 输出是什么?

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(ok)(gosearch)

`JSON.stringify`的第二个参数是 _替代者(replacer)_. 替代者(replacer)可以是个函数或数组,用以控制哪些值如何被转换为字符串。

如果替代者(replacer)是个 _数组_ ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为`"level"` 和 `"health"` 的属性被包括进来, `"username"`则被排除在外。 `data` 就等于 `"{"level":19, "health":90}"`.

而如果替代者(replacer)是个 _函数_,这个函数将被对象的每个属性都调用一遍。
函数返回的值会成为这个属性的值,最终体现在转化后的JSON字符串中(译者注:Chrome下,经过实验,如果所有属性均返回同一个值的时候有异常,会直接将返回值作为结果输出而不会输出JSON字符串),而如果返回值为`undefined`,则该属性会被排除在外。

63. 输出是什么?

let num = 10;

const increaseNumber = () => num++;
const increasePassedNumber = number => number++;

const num1 = increaseNumber();
const num2 = increasePassedNumber(num1);

console.log(num1);
console.log(num2);
  • A: 10, 10
  • B: 10, 11
  • C: 11, 11
  • D: 11, 12

我的:D(error) 正确:A

一元操作符 `++` _先返回_ 操作值, _再累加_ 操作值。`num1`的值是`10`, 因为`increaseNumber`函数首先返回`num`的值,也就是`10`,随后再进行 `num`的累加。

`num2`是`10`因为我们将 `num1`传入`increasePassedNumber`. `number`等于`10`(`num1`的值。同样道理,`++` _先返回_ 操作值, _再累加_ 操作值。) `number`是`10`,所以`num2`也是`10`.

64. 输出什么?

const value = { number: 10 };

const multiply = (x = { ...value }) => {
  console.log(x.number *= 2);
};

multiply();
multiply();
multiply(value);
multiply(value);
  • A: 20, 40, 80, 160
  • B: 20, 40, 20, 40
  • C: 20, 20, 20, 40
  • D: NaN, NaN, 20, 40

我的:D(error) 正确:C

在ES6中,我们可以使用默认值初始化参数。如果没有给函数传参,或者传的参值为 `"undefined"` ,那么参数的值将是默认值。上述例子中,我们将 `value` 对象进行了解构并传到一个新对象中,因此 `x` 的默认值为 `{number:10}` 。

默认参数在调用时才会进行计算,每次调用函数时,都会创建一个新的对象。我们前两次调用 `multiply` 函数且不传递值,那么每一次 `x` 的默认值都为 `{number:10}` ,因此打印出该数字的乘积值为`20`。

第三次调用 `multiply` 时,我们传递了一个参数,即对象`value`。 `*=`运算符实际上是`x.number = x.number * 2`的简写,我们修改了`x.number`的值,并打印出值`20`。

第四次,我们再次传递`value`对象。 `x.number`之前被修改为`20`,所以`x.number * = 2`打印为`40`。

65. 输出什么?

[1, 2, 3, 4].reduce((x, y) => console.log(x, y));
  • A: 1 2 and 3 3 and 6 4
  • B: 1 2 and 2 3 and 3 4
  • C: 1 undefined and 2 undefined and 3 undefined and 4 undefined
  • D: 1 2 and undefined 3 and undefined 4

我的:? 正确:D (gosearch)

`reducer` 函数接收4个参数:

1. Accumulator (acc) (累计器)
2. Current Value (cur) (当前值)
3. Current Index (idx) (当前索引)
4. Source Array (src) (源数组)

`reducer` 函数的返回值将会分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。

`reducer` 函数还有一个可选参数`initialValue`, 该参数将作为第一次调用回调函数时的第一个参数的值。如果没有提供`initialValue`,则将使用数组中的第一个元素。

在上述例子,`reduce`方法接收的第一个参数(Accumulator)是`x`, 第二个参数(Current Value)是`y`。
 
在第一次调用时,累加器`x`为`1`,当前值`“y”`为`2`,打印出累加器和当前值:`1`和`2`。

例子中我们的回调函数没有返回任何值,只是打印累加器的值和当前值。如果函数没有返回值,则默认返回`undefined`。 在下一次调用时,累加器为`undefined`,当前值为“3”, 因此`undefined`和`3`被打印出。

在第四次调用时,回调函数依然没有返回值。 累加器再次为 `undefined` ,当前值为“4”。 `undefined`和`4`被打印出。

66. 使用哪个构造函数可以成功继承Dog类?

class Dog {
  constructor(name) {
    this.name = name;
  }
};

class Labrador extends Dog {
  // 1 
  constructor(name, size) {
    this.size = size;
  }
  // 2
  constructor(name, size) {
    super(name);
    this.size = size;
  }
  // 3
  constructor(size) {
    super(name);
    this.size = size;
  }
  // 4 
  constructor(name, size) {
    this.name = name;
    this.size = size;
  }

};
  • A: 1
  • B: 2
  • C: 3
  • D: 4

我的:B(ok)

在子类中,在调用`super`之前不能访问到`this`关键字。 如果这样做,它将抛出一个`ReferenceError`:1和4将引发一个引用错误。

使用`super`关键字,需要用给定的参数来调用父类的构造函数。 父类的构造函数接收`name`参数,因此我们需要将`name`传递给`super`。

`Labrador`类接收两个参数,`name`参数是由于它继承了`Dog`,`size`作为`Labrador`类的额外属性,它们都需要传递给`Labrador`的构造函数,因此使用构造函数2正确完成。

67. 输出什么?

// index.js
console.log('running index.js');
import { sum } from './sum.js';
console.log(sum(1, 2));

// sum.js
console.log('running sum.js');
export const sum = (a, b) => a + b;
  • A: running index.js, running sum.js, 3
  • B: running sum.js, running index.js, 3
  • C: running sum.js, 3, running index.js
  • D: running index.js, undefined, running sum.js

我的:A(error) 正确:B

`import`命令是编译阶段执行的,在代码运行之前。因此这意味着被导入的模块会先运行,而导入模块的文件会后执行。

这是CommonJS中`require()`和`import`之间的区别。使用`require()`,您可以在运行代码时根据需要加载依赖项。 如果我们使用`require`而不是`import`,`running index.js`,`running sum.js`,`3`会被依次打印。

68. 输出什么?

console.log(Number(2) === Number(2))
console.log(Boolean(false) === Boolean(false))
console.log(Symbol('foo') === Symbol('foo'))
  • A: true, true, false
  • B: false, true, false
  • C: true, false, true
  • D: true, true, true

我的:? 正确:A (gosearch)

每个`Symbol`都是完全唯一的。传递给`Symbol`的参数只是给`Symbol`的一个描述。 `Symbol`的值不依赖于传递的参数。 当我们测试相等时,我们创建了两个全新的符号:第一个`Symbol('foo')`,第二个`Symbol('foo')`, 这两个值是唯一的,彼此不相等,因此返回`false`。

69. 输出什么?

const name = "Lydia Hallie"
console.log(name.padStart(13))
console.log(name.padStart(2))
  • A: "Lydia Hallie", "Lydia Hallie"
  • B: " Lydia Hallie", " Lydia Hallie" ("[13x whitespace]Lydia Hallie", "[2x whitespace]Lydia Hallie")
  • C: " Lydia Hallie", "Lydia Hallie" ("[1x whitespace]Lydia Hallie", "Lydia Hallie")
  • D: "Lydia Hallie", "Lyd"

我的:? 正确:C (gosearch)

使用`padStart`方法,我们可以在字符串的开头添加填充。传递给此方法的参数是字符串的总长度(包含填充)。字符串`Lydia Hallie`的长度为`12`, 因此`name.padStart(13)`在字符串的开头只会插入1(`13 - 12 = 1`)个空格。

如果传递给`padStart`方法的参数小于字符串的长度,则不会添加填充。

70. 输出什么?

console.log("🥑" + "💻");
  • A: "🥑💻"
  • B: 257548
  • C: A string containing their code points
  • D: Error

我的:A(ok)


71. 如何能打印出console.log语句后注释掉的值?

function* startGame() {
  const answer = yield "Do you love JavaScript?";
  if (answer !== "Yes") {
    return "Oh wow... Guess we're gone here";
  }
  return "JavaScript loves you back ❤️";
}

const game = startGame();
console.log(/* 1 */); // Do you love JavaScript?
console.log(/* 2 */); // JavaScript loves you back ❤️
  • A: game.next("Yes").value and game.next().value
  • B: game.next.value("Yes") and game.next.value()
  • C: game.next().value and game.next("Yes").value
  • D: game.next.value() and game.next.value("Yes")

我的:? 正确:C (gosearch)

`generator`函数在遇到`yield`关键字时会“暂停”其执行。 首先,我们需要让函数产生字符串`Do you love JavaScript?`,这可以通过调用`game.next().value`来完成。上述函数的第一行就有一个`yield`关键字,那么运行立即停止了,`yield`表达式本身没有返回值,或者说总是返回`undefined`, 这意味着此时变量 `answer` 为`undefined`

`next`方法可以带一个参数,该参数会被当作上一个 `yield` 表达式的返回值。当我们调用`game.next("Yes").value`时,先前的 `yield` 的返回值将被替换为传递给`next()`函数的参数`"Yes"`。此时变量 `answer` 被赋值为 `"Yes"`,`if`语句返回`false`,所以`JavaScript loves you back ❤️`被打印。

72. 输出什么?

console.log(String.raw`Hello\nworld`);
  • A: Hello world!
  • B: Hello world
  • C: Hello\nworld
  • D: Hello\n world

我的:B(error) 正确:C (gosearch)

`String.raw`函数是用来获取一个模板字符串的原始字符串的,它返回一个字符串,其中忽略了转义符(`\n`,`\v`,`\t`等)。但反斜杠可能造成问题,因为你可能会遇到下面这种类似情况:

```javascript
const path = `C:\Documents\Projects\table.html`
String.raw`${path}`
```

这将导致:

`"C:DocumentsProjects able.html"`

直接使用`String.raw`
```javascript
String.raw`C:\Documents\Projects\table.html`
```
它会忽略转义字符并打印:`C:\Documents\Projects\table.html`

上述情况,字符串是`Hello\nworld`被打印出。

73. 输出什么?

async function getData() {
  return await Promise.resolve("I made it!");
}

const data = getData();
console.log(data);
  • A: "I made it!"
  • B: Promise {<resolved>: "I made it!"}
  • C: Promise {<pending>}
  • D: undefined

我的:? 正确:C

异步函数始终返回一个promise。`await`仍然需要等待promise的解决:当我们调用`getData()`并将其赋值给`data`,此时`data`为`getData`方法返回的一个挂起的promise,该promise并没有解决。

如果我们想要访问已解决的值`"I made it!"`,可以在`data`上使用`.then()`方法:

`data.then(res => console.log(res))`

这样将打印 `"I made it!"`

74. 输出什么?

function addToList(item, list) {
  return list.push(item);
}

const result = addToList("apple", ["banana"]);
console.log(result);
  • A: ['apple', 'banana']
  • B: 2
  • C: true
  • D: undefined

我的:B(ok)

`push()`方法返回新数组的长度。一开始,数组包含一个元素(字符串`"banana"`),长度为1。 在数组中添加字符串`"apple"`后,长度变为2,并将从`addToList`函数返回。

`push`方法修改原始数组,如果你想从函数返回数组而不是数组长度,那么应该在push `item`之后返回`list`。

75. 输出什么?

const box = { x: 10, y: 20 };

Object.freeze(box);

const shape = box;
shape.x = 100;
console.log(shape)
  • A: { x: 100, y: 20 }
  • B: { x: 10, y: 20 }
  • C: { x: 100 }
  • D: ReferenceError

我的:C(error) 正确:B

`Object.freeze`使得无法添加、删除或修改对象的属性(除非属性的值是另一个对象)。

当我们创建变量`shape`并将其设置为等于冻结对象`box`时,`shape`指向的也是冻结对象。你可以使用`Object.isFrozen`检查一个对象是否被冻结,上述情况,`Object.isFrozen(shape)`将返回`true`。

由于`shape`被冻结,并且`x`的值不是对象,所以我们不能修改属性`x`。 `x`仍然等于`10`,`{x:10,y:20}`被打印。

注意,上述例子我们对属性`x`进行修改,可能会导致抛出TypeError异常(最常见但不仅限于严格模式下时)。

76. 输出什么?

const { name: myName } = { name: "Lydia" };

console.log(name);
  • A: "Lydia"
  • B: "myName"
  • C: undefined
  • D: ReferenceError

我的:? 正确:D

当我们从右侧的对象解构属性`name`时,我们将其值`Lydia`分配给名为`myName`的变量。

使用`{name:myName}`,我们是在告诉JavaScript我们要创建一个名为`myName`的新变量,并且其值是右侧对象的`name`属性的值。

当我们尝试打印`name`,一个未定义的变量时,就会引发`ReferenceError`。

77. 以下是个纯函数么?

function sum(a, b) {
  return a + b;
}
  • A: Yes
  • B: No

我的:A(ok)

纯函数一种若输入参数相同,则永远会得到相同输出的函数。

`sum`函数总是返回相同的结果。 如果我们传递`1`和`2`,它将总是返回`3`而没有副作用。 如果我们传递`5`和`10`,它将总是返回`15`,依此类推,这是纯函数的定义。

78. 输出什么?

const add = () => {
  const cache = {};
  return num => {
    if (num in cache) {
      return `From cache! ${cache[num]}`;
    } else {
      const result = num + 10;
      cache[num] = result;
      return `Calculated! ${result}`;
    }
  };
};

const addFunction = add();
console.log(addFunction(10));
console.log(addFunction(10));
console.log(addFunction(5 * 2));
  • A: Calculated! 20 Calculated! 20 Calculated! 20
  • B: Calculated! 20 From cache! 20 Calculated! 20
  • C: Calculated! 20 From cache! 20 From cache! 20
  • D: Calculated! 20 From cache! 20 Error

我的:C(ok)


79. 输出什么?

const myLifeSummedUp = ["☕", "💻", "🍷", "🍫"]

for (let item in myLifeSummedUp) {
  console.log(item)
}

for (let item of myLifeSummedUp) {
  console.log(item)
}
  • A: 0 1 2 3 and "☕" "💻" "🍷" "🍫"
  • B: "☕" "💻" "🍷" "🍫" and "☕" "💻" "🍷" "🍫"
  • C: "☕" "💻" "🍷" "🍫" and 0 1 2 3
  • D: 0 1 2 3 and {0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}

我的:A(ok)


80. 输出什么?

const list = [1 + 2, 1 * 2, 1 / 2]
console.log(list)
  • A: ["1 + 2", "1 * 2", "1 / 2"]
  • B: ["12", 2, 0.5]
  • C: [3, 2, 0.5]
  • D: [1, 1, 1]

我的:C(ok)


81. 输出什么?

function sayHi(name) {
  return `Hi there, ${name}`
}

console.log(sayHi())
  • A: Hi there,
  • B: Hi there, undefined
  • C: Hi there, null
  • D: ReferenceError

我的:B(ok)


82. 输出什么?

var status = "😎"

setTimeout(() => {
  const status = "😍"

  const data = {
    status: "🥑",
    getStatus() {
      return this.status
    }
  }

  console.log(data.getStatus())
  console.log(data.getStatus.call(this))
}, 0)
  • A: "🥑" and "😍"
  • B: "🥑" and "😎"
  • C: "😍" and "😎"
  • D: "😎" and "😎"

我的:A(error) 正确:B

`this`关键字的指向取决于使用它的位置。 在**函数**中,比如`getStatus`,`this`指向的是调用它的对象,上述例子中`data`对象调用了`getStatus`,因此`this`指向的就是`data`对象。 当我们打印`this.status`时,`data`对象的`status`属性被打印,即`"🥑"`。

使用`call`方法,可以更改`this`指向的对象。`data.getStatus.call(this)`是将`this`的指向由`data`对象更改为全局对象。在全局对象上,有一个名为`status`的变量,其值为`”😎“`。 因此打印`this.status`时,会打印`“😎”`。

83. 输出什么?

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

let city = person.city
city = "Amsterdam"

console.log(person)
  • A: { name: "Lydia", age: 21 }
  • B: { name: "Lydia", age: 21, city: "Amsterdam" }
  • C: { name: "Lydia", age: 21, city: undefined }
  • D: "Amsterdam"

我的:B(error) 正确:A

我们将变量`city`设置为等于`person`对象上名为`city`的属性的值。 这个对象上没有名为`city`的属性,因此变量`city`的值为`undefined`。

请注意,我们没有引用`person`对象本身,只是将变量`city`设置为等于`person`对象上`city`属性的当前值。

然后,我们将`city`设置为等于字符串`“Amsterdam”`。 这不会更改person对象:没有对该对象的引用。

因此打印`person`对象时,会返回未修改的对象。

84. 输出什么?

function checkAge(age) {
  if (age < 18) {
    const message = "Sorry, you're too young."
  } else {
    const message = "Yay! You're old enough!"
  }

  return message
}

console.log(checkAge(21))
  • A: "Sorry, you're too young."
  • B: "Yay! You're old enough!"
  • C: ReferenceError
  • D: undefined

我的:D(error) 正确:C

`const`和`let`声明的变量是具有**块级作用域**的,块是大括号(`{}`)之间的任何东西, 即上述情况`if / else`语句的花括号。 由于块级作用域,我们无法在声明的块之外引用变量,因此抛出`ReferenceError`。

85. 什么样的信息将被打印?

fetch('https://www.website.com/api/user/1')
  .then(res => res.json())
  .then(res => console.log(res))
  • A: fetch方法的结果
  • B: 第二次调用fetch方法的结果
  • C: 前一个.then()中回调方法返回的结果
  • D: 总是undefined

我的:? 正确:C

第二个`.then`中`res`的值等于前一个`.then`中的回调函数返回的值。 你可以像这样继续链接`.then`,将值传递给下一个处理程序。

86. 哪个选项是将hasName设置为true的方法,前提是不能将true作为参数传递?

function getName(name) {
  const hasName = //
}
  • A: !!name
  • B: name
  • C: new Boolean(name)
  • D: name.length

我的:A(ok)

使用逻辑非运算符`!`,将返回一个布尔值,使用`!! name`,我们可以确定`name`的值是真的还是假的。 如果`name`是真实的,那么`!name`返回`false`。 `!false`返回`true`。

通过将`hasName`设置为`name`,可以将`hasName`设置为等于传递给`getName`函数的值,而不是布尔值`true`。

`new Boolean(true)`返回一个对象包装器,而不是布尔值本身。

`name.length`返回传递的参数的长度,而不是布尔值`true`。

console.log(!true); //false
console.log(!!true); //true
console.log(!!!true);//false

87. 输出什么?

console.log("I want pizza"[0])
  • A: """
  • B: "I"
  • C: SyntaxError
  • D: undefined

我的:B(ok)


88. 输出什么?

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

sum(10)
  • A: NaN
  • B: 20
  • C: ReferenceError
  • D: undefined

我的:B(ok)

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

如果您尝试将默认参数的值设置为后面定义的参数,则可能导致参数的值尚未初始化,从而引发错误。比如:
```js
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

89. 输出什么?

// 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(ok)

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

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

90. 输出什么?

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(ok)

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

```javascript
function Person() {
  this.name = name
}
```

通过`new`来调用构造函数,将会生成构造函数`Person`的实例,对实例执行`typeof`关键字将返回`"object"`,上述情况打印出`"object"`。
console.log(typeof Person); //function

91. 输出什么?

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

console.log(newList.push(5))
  • A: [1, 2, 3, 4, 5]
  • B: [1, 2, 3, 5]
  • C: [1, 2, 3, 4]
  • D: Error

我的:A(?) 正确:D

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

然后,尝试在`newList`上使用`.push`方法。 由于`newList`是数值`4`,抛出TypeError。
console.log([].push(2)); //1
console.log([1].push(2)); //2
console.log([1,2].push(2)); //3
console.log([1,2,3].push(2)); //4

92. 输出什么?

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

我的:A(?) 正确:D

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

93. 输出什么?

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

我的:? 正确:B (gosearch)

`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`。
var result = Object.entries(person);
console.log(result); //[['name','Lydia'],['age',21]];
console.log(result[0]); //['name','Lydia']
console.log(result[1]); //['age',21]

94. 输出什么?

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`是剩余参数,剩余参数的值是一个包含所有剩余参数的数组,**并且只能作为最后一个参数**。上述示例中,剩余参数是第二个参数,这是不可能的,并会抛出语法错误。

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

getItems(["banana", "apple"], "pear", "orange")
```

上述例子是有效的,将会返回数组:`[ 'banana', 'apple', 'orange', 'pear' ]`
function getItems(fruitList,  favoriteFruit, ...args) {
  return [...fruitList, ...args, favoriteFruit]
}
getItems(["banana", "apple"], "pear", "orange"); //["banana", "apple", "orange", "pear"]


function getItems(fruitList,  favoriteFruit, ...args) {
  return [...fruitList, favoriteFruit, ...args]
}
getItems(["banana", "apple"], "pear", "orange"); //["banana", "apple", "pear", "orange"]

95. 输出什么?

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

我的:A(error) 正确:B

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)); // `a is bigger`, `undefined`
console.log(nums(1, 2)); // `b is bigger`, `undefined`


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)); //`a is bigger`, `6`
console.log(nums(1, 2)); //`b is bigger`, `3`

96. 输出什么?

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(?) 正确:B

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

97. 输出什么?

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 (gosearch)

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

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

98. 输出什么?

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`,我们将所有剩余参数放在一个数组中。 在这种情况下,其余的参数是`2`,`3`和`4`。 `y`的值是一个数组,包含所有其余参数。 在这种情况下,`x`的值等于`1`,所以当我们打印`[x,y]`时,会打印`[1,[2,3,4]]`。

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

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

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

99. 输出什么?

const name = "Lydia"

console.log(name())
  • A: SyntaxError
  • B: ReferenceError
  • C: TypeError
  • D: undefined

我的:? 正确:C

变量`name`保存字符串的值,该字符串不是函数,因此无法调用。

当值不是预期类型时,会抛出`TypeErrors`。 JavaScript期望`name`是一个函数,因为我们试图调用它。 但它是一个字符串,因此抛出`TypeError`:`name is not a function`

当你编写了一些非有效的JavaScript时,会抛出语法错误,例如当你把`return`这个词写成`retrun`时。
当JavaScript无法找到您尝试访问的值的引用时,抛出`ReferenceErrors`。

100. 输出什么?

// 🎉✨ This is my 100th question! ✨🎉

const output = `${[] && 'Im'}possible!
You should${'' && `n't`} see a therapist after so much JavaScript lol`
  • A: possible! You should see a therapist after so much JavaScript lol
  • B: Impossible! You should see a therapist after so much JavaScript lol
  • C: possible! You shouldn't see a therapist after so much JavaScript lol
  • D: Impossible! You shouldn't see a therapist after so much JavaScript lol

我的:A(?) 正确:B

`[]`是一个真值。 使用`&&`运算符,如果左侧值是真值,则返回右侧值。 在这种情况下,左侧值`[]`是一个真值,所以返回`Im`。

`""`是一个假值。 如果左侧值是假的,则不返回任何内容。 `n't`不会被退回。
var result = [] && 'hello';
console.log(result); // hello


var result = '' && 'hello';
console.log(result); // ''

var result = ' ' && 'hello';
console.log(result); // hello

101.输出什么?

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`等于`[]`。
function sayHello(name){
  var name = name || 'jim'
  console.log('hello ' + name)
}


var result = 1 || 2;
console.log(result); // 1

var result = undefined || 1;
console.log(result); // 1

var result = null || 1;
console.log(result); // 1

102. What’s the value of output?

const myPromise = () => Promise.resolve('I have resolved!')

function firstFunction() {
  myPromise().then(res => console.log(res))
  console.log('second')
}

async function secondFunction() {
  console.log(await myPromise())
  console.log('second')
}

firstFunction()
secondFunction()
  • A: I have resolved!, second and I have resolved!, second
  • B: second, I have resolved! and second, I have resolved!
  • C: I have resolved!, second and second, I have resolved!
  • D: second, I have resolved! and I have resolved!, second

我的:B (error) 正确:D

With a promise, we basically say _I want to execute this function, but I'll put it aside for now while it's running since this might take a while. Only when a certain value is resolved (or rejected), and when the call stack is empty, I want to use this value._

We can get this value with both `.then` and the `await` keyword in an `async` function. Although we can get a promise's value with both `.then` and `await`, they work a bit differently. 

In the `firstFunction`, we (sort of) put the myPromise function aside while it was running, but continued running the other code, which is `console.log('second')` in this case. Then, the function resolved with the string `I have resolved`, which then got logged after it saw that the callstack was empty. 

With the await keyword in `secondFunction`, we literally pause the execution of an async function until the value has been resolved befoer moving to the next line.

This means that it waited for the `myPromise` to resolve with the value `I have resolved`, and only once that happened, we moved to the next line: `second` got logged. 

103. What’s the value of output?

const set = new Set()

set.add(1)
set.add("Lydia")
set.add({ name: "Lydia" })

for (let item of set) {
  console.log(item + 2)
}
  • A: 3, NaN, NaN
  • B: 3, 7, NaN
  • C: 3, Lydia2, [Object object]2
  • D: "12", Lydia2, [Object object]2

我的:A (error) 正确:C

The `+` operator is not only used for adding numerical values, but we can also use it to concatenate strings. Whenever the JavaScript engine sees that one or more values are not a number, it coerces the number into a string. 

The first one is `1`, which is a numerical value. `1 + 2` returns the number 3.

However, the second one is a string `"Lydia"`. `"Lydia"` is a string and `2` is a number: `2` gets coerced into a string. `"Lydia"` and `"2"` get concatenated, which results in the string `"Lydia2"`. 

`{ name: "Lydia" }` is an object. Neither a number nor an object is a string, so it stringifies both. Whenever we stringify a regular object, it becomes `"[Object object]"`. `"[Object object]"` concatenated with `"2"` becomes `"[Object object]2"`.

104. What’s its value?

Promise.resolve(5)
  • A: 5
  • B: Promise {<pending>: 5}
  • C: Promise {<resolved>: 5}
  • D: Error

我的:C (ok)


105. What’s its value?

function compareMembers(person1, person2 = person) {
  if (person1 !== person2) {
    console.log("Not the same!")
  } else {
    console.log("They are the same!")
  }
}

const person = { name: "Lydia" }

compareMembers(person)
  • A: Not the same!
  • B: They are the same!
  • C: ReferenceError
  • D: SyntaxError

我的:B(ok)


106. What’s its value?

const colorConfig = {
  red: true,
  blue: false,
  green: true,
  black: true,
  yellow: false,
}

const colors = ["pink", "red", "blue"]

console.log(colorConfig.colors[1])
  • A: true
  • B: false
  • C: undefined
  • D: TypeError

我的:A (error) 正确:D

In JavaScript, we have two ways to access properties on an object: bracket notation, or dot notation. In this example, we use dot notation (`colorConfig.colors`) instead of bracket notation (`colorConfig["colors"]`). 

With dot notation, JavaScript tries to find the property on the object with that exact name. In this example, JavaScript tries to find a property called `colors` on the `colorConfig` object. There is no proprety called `colors`, so this returns `undefined`. Then, we try to access the value of the first element by using `[1]`. We cannot do this on a value that's `undefined`, so it throws a `TypeError`: `Cannot read property '1' of undefined`.

JavaScript interprets (or unboxes) statements. When we use bracket notation, it sees the first opening bracket `[` and keeps going until it finds the closing bracket `]`. Only then, it will evaluate the statement. If we would've used `colorConfig[colors[1]]`, it would have returned the value of the `red` property on the `colorConfig` object. 

107. What’s its value?

console.log('❤️' === '❤️')
  • A: true
  • B: false

我的:A(ok)


108. Which of these methods modifies the original array?

const emojis = ['✨', '🥑', '😍']

emojis.map(x => x + '✨')
emojis.filter(x => x !== '🥑')
emojis.find(x => x !== '🥑')
emojis.reduce((acc, cur) => acc + '✨')
emojis.slice(1, 2, '✨') 
emojis.splice(1, 2, '✨')
  • A: All of them
  • B: map reduce slice splice
  • C: map slice splice
  • D: splice

我的:? 正确:D

With `splice` method, we modify the original array by deleting, replacing or adding elements. In this case, we removed 2 items from index 1 (we removed `'🥑'` and `'😍'`) and added the ✨ emoji instead. 

`map`, `filter` and `slice` return a new array, `find` returns an element, and `reduce` returns a reduced value.

109. What’s the output?

const food = ['🍕', '🍫', '🥑', '🍔']
const info = { favoriteFood: food[0] }

info.favoriteFood = '🍝'

console.log(food)
  • A: ['🍕', '🍫', '🥑', '🍔']
  • B: ['🍝', '🍫', '🥑', '🍔']
  • C: ['🍝', '🍕', '🍫', '🥑', '🍔']
  • D: ReferenceError

我的:A(ok)


110. What does this method do?

JSON.parse()
  • A: Parses JSON to a JavaScript value
  • B: Parses a JavaScript object to JSON
  • C: Parses any JavaScript value to JSON
  • D: Parses JSON to a JavaScript object only

我的:D(error) 正确:A

With the `JSON.parse()` method, we can parse JSON string to a JavaScript value. 

```javascript
// Stringifying a number into valid JSON, then parsing the JSON string to a JavaScript value:
const jsonNumber = JSON.stringify(4) // '4'
JSON.parse(jsonNumber) // 4

// Stringifying an array value into valid JSON, then parsing the JSON string to a JavaScript value:
const jsonArray = JSON.stringify([1, 2, 3]) // '[1, 2, 3]'
JSON.parse(jsonArray) // [1, 2, 3]

// Stringifying an object  into valid JSON, then parsing the JSON string to a JavaScript value:
const jsonArray = JSON.stringify({ name: "Lydia" }) // '{"name":"Lydia"}'
JSON.parse(jsonArray) // { name: 'Lydia' }

111. What’s the output?

let name = 'Lydia'

function getName() {
  console.log(name)
  let name = 'Sarah'
}

getName()
  • A: Lydia
  • B: Sarah
  • C: undefined
  • D: ReferenceError

我的:D(ok)


112. What’s the output?

function* generatorOne() {
  yield ['a', 'b', 'c'];
}

function* generatorTwo() {
  yield* ['a', 'b', 'c'];
}

const one = generatorOne()
const two = generatorTwo()

console.log(one.next().value)
console.log(two.next().value)
  • A: a and a
  • B: a and undefined
  • C: ['a', 'b', 'c'] and a
  • D: a and ['a', 'b', 'c']

我的:? 正确:C

With the `yield` keyword, we `yield` values in a generator function. With the `yield*` keyword, we can yield values from another generator function, or iterable object (for example an array).

In `generatorOne`, we yield the entire array `['a', 'b', 'c']` using the `yield` keyword. The value of `value` property on the object returned by the `next` method on `one` (`one.next().value`) is equal to the entire array `['a', 'b', 'c']`.

```javascript
console.log(one.next().value) // ['a', 'b', 'c']
console.log(one.next().value) // undefined
```

In `generatorTwo`, we use the `yield*` keyword. This means that the first yielded value of `two`, is equal to the first yielded value in the iterator. The iterator is the array `['a', 'b', 'c']`. The first yielded value is `a`, so the first time we call `two.next().value`, `a` is returned. 

```javascript
console.log(two.next().value) // 'a'
console.log(two.next().value) // 'b'
console.log(two.next().value) // 'c'
console.log(two.next().value) // undefined
```

113. What’s the output?

console.log(`${(x => x)('I love')} to program`)
  • A: I love to program
  • B: undefined to program
  • C: ${(x => x)('I love') to program
  • D: TypeError

我的:A(ok)

Expressions within template literals are evaluated first. This means that the string will contain the returned value of the expression, the immediately invoked function `(x => x)('I love')` in this case. We pass the value `'I love'` as an argument to the `x => x` arrow function. `x` is equal to `'I love'`, which gets returned. This results in `I love to program`. 

114. What will happen?

let config = {
  alert: setInterval(() => {
    console.log('Alert!')
  }, 1000)
}

config = null
  • A: The setInterval callback won’t be invoked
  • B: The setInterval callback gets invoked once
  • C: The setInterval callback will still be called every second
  • D: We never invoked config.alert(), config is null

我的:D (error) 正确:C

Normally when we set objects equal to `null`, those objects get _garbage collected_ as there is no reference anymore to that object. However, since the callback function within `setInterval` is an arrow function (thus bound to the `config` object), the callback function still holds a reference to the `config` object. As long as there is a reference, the object won't get garbage collected. Since it's not garbage collected, the `setInterval` callback function will still get invoked every 1000ms (1s).

115. Which method(s) will return the value 'Hello world!'?

const myMap = new Map()
const myFunc = () => 'greeting'

myMap.set(myFunc, 'Hello world!')

//1
myMap.get('greeting')
//2
myMap.get(myFunc)
//3
myMap.get(() => 'greeting')
  • A: 1
  • B: 2
  • C: 2 and 3
  • D: All of them

我的:? 正确:B

When adding a key/value pair using the `set` method, the key will be the value of the first argument passed to the `set` function, and the value will be the second argument passed to the `set` function. The key is the _function_ `() => 'greeting'` in this case, and the value `'Hello world'`. `myMap` is now `{ () => 'greeting' => 'Hello world!' }`. 

1 is wrong, since the key is not `'greeting'` but `() => 'greeting'`.
3 is wrong, since we're creating a new function by passing it as a parameter to the `get` method. Object interact by _reference_. Functions are objects, which is why two functions are never strictly equal, even if they are identical: they have a reference to a different spot in memory. 

116. What’s the output?

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

const changeAge = (x = { ...person }) => x.age += 1
const changeAgeAndName = (x = { ...person }) => {
  x.age += 1
  x.name = "Sarah"
}

changeAge(person)
changeAgeAndName()

console.log(person)
  • A: {name: "Sarah", age: 22}
  • B: {name: "Sarah", age: 23}
  • C: {name: "Lydia", age: 22}
  • D: {name: "Lydia", age: 23}

我的:? 正确:C

Both the `changeAge` and `changeAgeAndName` functions have a default parameter, namely a _newly_ created object `{ ...person }`. This object has copies of all the key/values in the `person` object. 

First, we invoke the `changeAge` function and pass the `person` object as its argument. This function increases the value of the `age` property by 1. `person` is now `{ name: "Lydia", age: 22 }`.

Then, we invoke the `changeAgeAndName` function, however we don't pass a parameter. Instead, the value of `x` is equal to a _new_ object: `{ ...person }`. Since it's a new object, it doesn't affect the values of the properties on the `person` object. `person` is still equal to `{ name: "Lydia", age: 22 }`.

处理代码:

var details = document.querySelectorAll('details');
var app = document.querySelector('#app')
for(let i = 0; i < details.length; i++){console.log(i)
  app.removeChild(details[i])
}

More

javascript-questions
https://github.com/lydiahallie/javascript-questions