每日20道面试题带解析 — (81 - 100)

答案在问题下方的折叠部分,点击即可展开问题。祝你好运 ❤️

1. 怎样才能在 index.js 中调用 sum.js? 中的 sum?

// sum.js
export default function sum(x) {
	return x + x;
}

// index.js
import * as sum from "./sum";
  • A: sum(4)
  • B: sum.sum(4)
  • C: sum.default(4)
  • D: 默认导出不用 * 来导入,只能具名导出
点此查看答案及解析

答案 : C
解析 : 相当于以下形式引入值 sum:{ default: function sum(x) { return x + x } }
    通过调用 sum.default 来调用该函数

2. 以下哪一项会对对象 person 有副作用?

const person = { name: "Lydia Hallie" };

Object.seal(person);
  • A: person.name = "Evan Bacon"
  • B: person.age = 21
  • C: delete person.name
  • D: Object.assign(person, { age: 21 })
点此查看答案及解析

答案 : A
解析 : Object.seal 可以防止新属性 被添加,或者存在属性被移除.然而,你仍然可以对存在属性进行更改。

3. 以下哪一项会对对象 person 有副作用?

const person = {
	name: "Lydia Hallie",
	address: {
		street: "100 Main St"
	}
};

Object.freeze(person);
  • A: person.name = "Evan Bacon"
  • B: delete person.address
  • C: person.address.street = "101 Main St"
  • D: person.pet = { name: "Mara" }
点此查看答案及解析

答案 : C
解析 : Object.freeze 对一个对象进行 冻结。不能对属性进行添加,修改,删除。
   然而仅对 对象进行 浅 冻结,意味着只有 对象中的 直接 属性被冻结。
   如果属性是另一个 object,像案例中的 address,address 中的属性没有被冻结,仍然可以被修改

4. 写出执行结果,并解释原因

class Bird {
	constructor() {
		console.log("I'm a bird. 🦢");
	}
}

class Flamingo extends Bird {
	constructor() {
		console.log("I'm pink. 🌸");
		super();
	}
}

const pet = new Flamingo();
  • A: I'm pink. 🌸
  • B: I'm pink. 🌸 I'm a bird. 🦢
  • C: I'm a bird. 🦢 I'm pink. 🌸
  • D: Nothing, we didn't call any method
点此查看答案及解析

答案 : B
解析 : 创建了类 Flamingo 的实例 pet。实例化这个实例时Flamingo 中的 constructor 被调用。
   首先,输出 "I'm pink. 🌸", 随后调用super()。super() 调用父类的构造函数Bird。
   Bird 的构造函数被调用,并输出 "I'm a bird. 🦢"。

5. 哪一个选项会导致报错?

const emojis = ["🎄", "🎅🏼", "🎁", "⭐"];

/* 1 */ emojis.push("🦌");
/* 2 */ emojis.splice(0, 2);
/* 3 */ emojis = [...emojis, "🥂"];
/* 4 */ emojis.length = 0;
  • A: 1
  • B: 1 and 2
  • C: 3 and 4
  • D: 3
点此查看答案及解析

答案 : D
解析 : const 声明的变量不能 重定义 变量的值,仅可读。
     但数组中的值可被修改,如 push 新的值, 拼接,又或者将数组的长度设置为0。

6. 输出什么?

const fruit = ['🍌', '🍊', '🍎']

fruit.slice(0, 1)
fruit.splice(0, 1)
fruit.unshift('🍇')

console.log(fruit)
  • A: ['🍌', '🍊', '🍎']
  • B: ['🍊', '🍎']
  • C: ['🍇', '🍊', '🍎']
  • D: ['🍇', '🍌', '🍊', '🍎']
点此查看答案及解析

答案 : C
解析 :
    1. slice方法不会改变原数组,返回从数组截取的值
    2. splice方法会改变原数组,数组此时为 ['🍊', '🍎']。 
    3. unshift方法会改变原数组,第一个位置添加一个值,数组此时为 ['🍇', '🍊', '🍎']。

7. 输出什么?

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
解析 : 
   1. getList函数接收一个数组作为其参数。在getList函数的括号之间,立即解构这个数组。 
      [x, ...y] = [1, 2, 3, 4],剩余参数...y存放在一个数组中[2,3,4]
      当打印[x,y]时,会打印[1,[2,3,4]]。
   2. getUser函数接收一个对象。对于箭头函数,如果只返回一个值,不必编写花括号。
      但是,如果返回一个对象,必须在圆括号之间编写它,否则不会返回任何值! 因此该函数返回undefined。
      const getUser = user => ({ name: user.name, age: user.age })  // 可返回对象

8. 输出什么?

function getFine(speed, amount) {
  const formattedSpeed = new Intl.NumberFormat({
    'en-US',
    { style: 'unit', unit: 'mile-per-hour' }
  }).format(speed)

  const formattedAmount = new Intl.NumberFormat({
    'en-US',
    { style: 'currency', currency: 'USD' }
  }).format(amount)

  return `The driver drove ${formattedSpeed} and has to pay ${formattedAmount}`
}

console.log(getFine(130, 300))
  • A: The driver drove 130 and has to pay 300
  • B: The driver drove 130 mph and has to pay $300.00
  • C: The driver drove undefined and has to pay undefined
  • D: The driver drove 130.00 and has to pay 300.00
点此查看答案及解析

答案 : B
解析 : Intl.NumberFormat 方法,可以格式化任意区域的数字值。
      mile-per-hour 通过格式化结果为 mph; USD通过格式化结果为 $.

9. 如何能打印出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
解析 : generator函数在遇到yield关键字时会“暂停”其执行。
  1. 首先让函数产生字符串`Do you love JavaScript?`,这可以通过调用 game.next().value 来完成。
  2. yield 表达式本身没有返回值,或者说总是返回 undefined, 这意味着此时变量 answer 为 undefined
  3. next 方法可以带一个参数,该参数会被当作上一个 yield 表达式的返回值。
  4. 当调用 game.next("Yes").value 时,先前的 yield 的返回值将被替换为next()函数的参数"Yes"。
  5. 此时变量 answer 被赋值为 "Yes",if语句返回false,所以`JavaScript loves you back ❤️`被打印。

10. 输出什么?

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!"

11. 输出什么?

class Counter {
  #number = 10

  increment() {
    this.#number++
  }

  getNum() {
    return this.#number
  }
}

const counter = new Counter()
counter.increment()

console.log(counter.#number)
  • A: 10
  • B: 11
  • C: undefined
  • D: SyntaxError
点此查看答案及解析

答案 : D
解析 :ES2020 中,可以通过 # 给 class 添加私有变量。在 class 的外部无法获取该值。当尝试输出 counter.#number,语法错误被抛出:Uncaught SyntaxError: Private field '#number' must be declared in an enclosing class

12. 输出什么?

const teams = [
	{ name: "Team 1", members: ["Paul", "Lisa"] },
	{ name: "Team 2", members: ["Laura", "Tim"] }
];

function* getMembers(members) {
	for (let i = 0; i < members.length; i++) {
		yield members[i];
	}
}

function* getTeams(teams) {
	for (let i = 0; i < teams.length; i++) {
		// TODO: ✨ SOMETHING IS MISSING HERE ✨ 
	}
}

const obj = getTeams(teams);
obj.next(); // { value: "Paul", done: false }
obj.next(); // { value: "Lisa", done: false }
  • A: yield getMembers(teams[i].members)
  • B: yield* getMembers(teams[i].members)
  • C: return getMembers(teams[i].members)
  • D: return yield getMembers(teams[i].members)
点此查看答案及解析

答案 : B
解析 : 为了遍历 teams数组中每一项 members属性中的每一项,需要将 teams[i].members 传递给getMembers函数。
Generator 函数返回一个 generator 对象。为了遍历这个 generator 对象中的每一项,需要使用 yield*.

13. 输出什么?

const config = {
	languages: [],
	set language(lang) {
		return this.languages.push(lang);
	}
};

console.log(config.language);
  • A: function language(lang) { this.languages.push(lang }
  • B: 0
  • C: []
  • D: undefined
点此查看答案及解析

答案 :  D
解析 : 方法 language 是一个 setter。Setters 并不保存一个实际值,它们的使命在于 _修改_ 属性。当调用方法 setter, 返回 undefined。

14. 输出什么?

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属性。访问prototype属性时会返回undefined。

15. 写出执行结果,并解释原因

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类型是不可枚举的。
	1. 记录整个对象时,所有属性都是可见的,甚至是不可枚举的属性。
	2. Object.keys 方法返回对象上的所有可枚举的键属性。因此返回一个空数组。 

16. 写出执行结果,并解释原因

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();    //  ?
点此查看答案及解析

答案 : 'Oh an error: Hello world'
解析 : 通过throw语句,可以创建自定义错误。可以抛出异常。异常可以是字符串, 数字, 布尔类型 或者是一个对象。在本例中,异常是字符串'Hello world'.
catch语句,可以捕获异常并作出相应处理。最终结果就是'Oh an error: Hello world'. 

17. 写出执行结果,并解释原因

const handler = {
	set: () => console.log("Added a new property!"),
	get: () => console.log("Accessed a property!")
};

const person = new Proxy({}, handler);

person.name = "Lydia";
person.name;
点此查看答案及解析

答案 : Added a new property!, Accessed a property!
解析 : 使用 Proxy 对象可以给一个对象添加自定义行为,传递一个包含以下属性的对象 handler : set and get。 _设置_属性值时 set 被调用, _获取_属性值时 get 被调用。
第一个参数是一个空对象 `{}`,作为 `person` 的值。对于这个对象,自定义行为被定义在对象 `handler`。如果我们向对象 `person` 添加属性,`set` 将被调用。如果我们获取 `person` 的属性, `get` 将被调用。
首先,我们向 proxy 对象(`person.name = "Lydia"`)添加一个属性 `name`。`set` 被调用并输出 `"Added a new property!"`。
然后,我们获取 proxy 对象的一个属性,对象 handler 的属性 `get` 被调用。输出 `"Accessed a property!"`。

18. 输出什么?

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

const gen = generator(10);

console.log(gen.next().value);
console.log(gen.next().value);
点此查看答案及解析

答案 : 10, 20
解析 : 一般的函数在执行过程中不能暂停。但生成器函数却可以中途“停下”,之后可以再从停下的地方继续。生成器遇到yield关键字时,会生成yield后面的值。使用next()方法一步步执行生成器。

19. 输出什么?

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', 'b', 'c'] , a
解析 : 通过 yield* 关键字, 可以在一个 Generator 函数里面执行另一个 Generator 函数, 或可遍历的对象 (如数组).
在函数 generatorOne 中, yield ['a', 'b', 'c']。而one.next().value 等价于数组 ['a', 'b', 'c']
        console.log(one.next().value) // ['a', 'b', 'c']
        console.log(one.next().value) // undefined
在函数 generatorTwo 中, yield* ['a', 'b', 'c'], 等价于在迭代器中第一个 yield 的值。就是 a, 所以two.next().value 返回 a。
        console.log(two.next().value) // 'a'
        console.log(two.next().value) // 'b'
        console.log(two.next().value) // 'c'
        console.log(two.next().value) // undefined

20. 解释下段代码的意思以及用到的技术

[].forEach.call($$("*"),function(a){  
  a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)  
})  
点此查看答案及解析

答案与解析
直观操作:获取页面所有的元素,使用随机色给这些元素加上1px的外边框
用到的技术:
  1. 选择页面中所有的元素:$$函数
	$$函数是现代浏览器提供的一个命令行API,相当于document.querySelectorAll,可以将当前页面中的CSS选择器作为参数传给该方法,然后它会返回匹配的所有元素。
  2. 遍历元素:[].forEach.call( $$('*'), function( a ) { ... });  
	call和apply方法,可以实现在类数组对象上调用数组方法。
  3. 为元素添加外边框: a.style.outline="1px solid #" + color  
	使用outline属性给元素添加一个边框。由于渲染的outline不在CSS盒模型中,所以为元素添加outline并不会影响元素的大小和页面的布局。
  4. 生成随机颜色: ~~(Math.random()*(1<<24))).toString(16)  
	- Math.random()*(1<<24) 可以得到 0~2^24 - 1 之间的随机数,使用了位操作
	- 得到一个浮点数,连续使用两次取反操作符 ~ 获得整数部分,相当于使用parseInt,
            const a =12.34;
            ~~a == parseInt(a, 10);   // true  
	- 使用toString(16)转换为一个十六进制的字符串。该方法将数值转换成字符串时,接收一个参数用以指明数值的进制。如果省略该参数,则默认采用十进制,可以为其指定进制,

posted @ 2021-03-26 20:35  Echoyya、  阅读(134)  评论(0编辑  收藏  举报