每日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]]
andundefined
- 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
andgame.next().value
- B:
game.next.value("Yes")
andgame.next.value()
- C:
game.next().value
andgame.next("Yes").value
- D:
game.next.value()
andgame.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)转换为一个十六进制的字符串。该方法将数值转换成字符串时,接收一个参数用以指明数值的进制。如果省略该参数,则默认采用十进制,可以为其指定进制,