每日20道面试题带解析 05
以下题目,本人验证无误,查阅了相关资料,得出解析部分并做了相关总结,希望对正准备跳槽或找工作的你有帮助!
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 {
increment() {
this.
}
getNum() {
return this.
}
}
const counter = new Counter()
counter.increment()
console.log(counter.
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);
}
}
答案及解析
答案 : '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";
答案 : 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)
答案 : ['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)转换为一个十六进制的字符串。该方法将数值转换成字符串时,接收一个参数用以指明数值的进制。如果省略该参数,则默认采用十进制,可以为其指定进制,
本文完~
学习更多技能
请点击下方公众号