来源:
javascript-questions/zh-CN/README-zh_CN.md at master · lydiahallie/javascript-questions · GitHub
记录一些有趣的题。
系列:
【前端】35道JavaScript进阶问题(1)
【前端】20道JavaScript进阶问题(2)
1
[1,2,3,4].reduce((x, y)=> console.log(x, y));
答:
12undefined3undefined4
解析:
reduce 方法接收一个回调函数和一个可选的初始值。 在你的例子中,回调函数是 (x, y) => console.log(x, y),没有提供初始值。
reduce 方法会对数组中的每个元素执行回调函数。 在每次调用回调函数时,它都会接收两个参数:累积值(我们这里称之为 x)和当前元素(我们这里称之为 y)。然后,回调函数的返回值会成为下一次调用回调函数时的累积值。
在你的例子中,回调函数并没有返回任何值,所以在第二次及以后调用回调函数时,x 的值都是 undefined。
以下是详细的步骤:
- 首先,reduce 方法会取数组的第一个元素(也就是 1)作为累积值 x,然后取数组的第二个元素(也就是 2)作为当前元素 y,然后调用回调函数。所以,第一次调用 console.log(x, y) 会输出 1 2。
- 然后,因为回调函数没有返回任何值,所以下一次调用回调函数时,x 的值是 undefined,y 的值是数组的第三个元素(也就是 3)。所以,第二次调用 console.log(x, y) 会输出 undefined 3。
- 同样,因为回调函数没有返回任何值,所以下一次调用回调函数时,x 的值还是 undefined,y 的值是数组的第四个元素(也就是 4)。所以,第三次调用 console.log(x, y) 会输出 undefined 4。
- 所以,你的代码会依次输出 1 2、undefined 3 和 undefined 4。
2
使用哪个构造函数可以成功继承
Dog
类?
classDog{constructor(name){this.name = name;}};classLabradorextendsDog{// 1 constructor(name, size){this.size = size;}// 2constructor(name, size){super(name);this.size = size;}// 3constructor(size){super(name);this.size = size;}// 4 constructor(name, size){this.name = name;this.size = size;}};
答:
2
解析:
在 JavaScript 中,如果你想要继承一个类,你需要在子类的构造函数中首先调用 super 函数。 super 函数会调用父类的构造函数,这是必须的,否则 JavaScript 会不能访问到
this
关键字。
所以,在你的例子中,只有第二个构造函数可以成功继承 Dog 类:
constructor(name, size){super(name);this.size = size;}
在这个构造函数中,首先调用了 super(name) 来调用 Dog 类的构造函数,然后设置了 size 属性。这样就成功地创建了一个 Labrador 对象,它既有 Dog 类的 name 属性,也有自己的 size 属性。
3
输出为?
// index.js
console.log('running index.js');import{ sum }from'./sum.js';
console.log(sum(1,2));// sum.js
console.log('running sum.js');exportconstsum=(a, b)=> a + b;
答:
running sum.js
,
running index.js
,
3
解析:
import命令是编译阶段执行的。在代码运行之前。因此这意味着被导入的模块会先运行,而导入模块的文件会后执行。
这是 CommonJS 中
require()
和
import
之间的区别。使用require(),您可以在运行代码时根据需要加载依赖项。 如果我们使用
require
而不是
import
,
running index.js
,
running sum.js
,
3
会被依次打印。
4
console.log(Number(2)===Number(2))
console.log(Boolean(false)===Boolean(false))
console.log(Symbol('foo')===Symbol('foo'))
答:
true
,
true
,
false
解析:
Number(2)
会返回一个数值 2,因此第一个为true。
若是new Number(2),则会返回一个对象。
console.log(newNumber(2)===newNumber(2));// false
每个Symbol都是完全唯一的。
传递给
Symbol
的参数只是给
Symbol
的一个描述。
Symbol
的值不依赖于传递的参数。当我们测试相等时,我们创建了两个全新的符号:第一个
Symbol('foo')
,第二个
Symbol('foo')
,这两个值是唯一的,彼此不相等,因此返回
false
。
5
const name ="Lydia Hallie"
console.log(name.padStart(13))
console.log(name.padStart(2))
答:
Lydia Hallie
Lydia Hallie
解析:
padStart传入的参数表示前面添加空格后总字符串的长度。小于原有长度的不处理。
6
console.log("🥑"+"💻");
- A:
"🥑💻"
- B:
257548
- C: A string containing their code points
- D: Error
答:
A。
7
如何能打印出
console.log
语句后注释掉的值?
function*startGame(){const ans =yield"Do you love JavaScript?";if(ans !=="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 ❤️
答:
console.log(game.next().value);// Do you love JavaScript?
console.log(game.next('Yes').value);// JavaScript loves you back ❤️
在第一次调用
game.next()
时,生成器函数会运行到第一个
yield
语句,并返回其右侧的值。然后,在第二次调用
game.next('Yes')
时,
yield
表达式的结果将被替换为传递给
next()
的参数(在这种情况下是"Yes"),然后函数继续执行,直到遇到下一个
yield
或者结束,返回其值。
8
console.log(String.raw`Hello\nworld`);
答:
Hello\nworld
String.raw
是一个模板字符串的标签函数,它会将所有的反斜杠(\)视为普通字符。因此,\n不会被解析为换行符,而是会被视为两个独立的字符:反斜杠和n。
但是,要直接接一个字符串,而不是变量:
const path =`C:\Documents\Projects\table.html`
console.log(String.raw`${path}`)// C:DocumentsProjects able.html
console.log(String.raw`C:\Documents\Projects\table.html`)// C:\Documents\Projects\table.html
9
asyncfunctiongetData(){returnawait Promise.resolve("I made it!");}const data =getData();
console.log(data);
答:
Promise {<pending>}
异步函数始终返回一个 promise。
await
仍然需要等待 promise 的解决:当我们调用
getData()
并将其赋值给
data
,此时
data
为
getData
方法返回的一个挂起
pending
的 promise,该 promise 并没有解决。
如果我们想要访问已解决的值
"I made it!"
,可以在
data
上使用
.then()
方法:
data.then(res => console.log(res))
这样将打印
"I made it!"
10
const box ={ x:10, y:20};
Object.freeze(box);const shape = box;
shape.x =100;
console.log(shape)
答:
{ x:10, y:20}
Object.freeze
使得无法添加、删除或修改对象的属性(除非属性的值是另一个对象)。
当我们创建变量
shape
并将其设置为等于冻结对象
box
时,
shape
指向的也是冻结对象。你可以使用
Object.isFrozen
检查一个对象是否被冻结,上述情况,
Object.isFrozen(shape)
将返回
true
。
由于
shape
被冻结,并且
x
的值不是对象,所以我们不能修改属性
x
。
x
仍然等于
10
,
{x:10,y:20}
被打印。
注意,上述例子我们对属性
x
进行修改,可能会导致抛出 TypeError 异常(最常见但不仅限于严格模式下时)。
11
const{ name: myName }={ name:"Lydia"};
console.log(name);
答:
ReferenceError
当我们从右侧的对象解构属性
name
时,我们将其值
Lydia
分配给名为
myName
的变量。
使用
{name:myName}
,我们是在告诉 JavaScript 我们要创建一个名为
myName
的新变量,并且其值是右侧对象的
name
属性的值。
当我们尝试打印
name
,一个未定义的变量时,就会引发
ReferenceError
。
const{ name: myName }={ name:"Lydia"};
console.log(name);// ReferenceError: name is not defined
console.log(myName);// Lydia
12
const myLifeSummedUp =["☕","💻","🍷","🍫"]for(let item in myLifeSummedUp){
console.log(item)}for(let item of myLifeSummedUp){
console.log(item)}
答:
0123
☕
💻
🍷
🍫
通过
for-in
循环,我们可以遍历一个对象自有的、继承的、可枚举的、非 Symbol 的属性。在数组中,可枚举属性是数组元素的“键”,即它们的索引。类似于下面这个对象:
{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}
其中键则是可枚举属性,因此
0
,
1
,
2
,
3
被记录。
通过
for-of
循环,我们可以迭代可迭代对象(包括
Array
,
Map
,
Set
,
String
,
arguments
等)。当我们迭代数组时,在每次迭代中,不同属性的值将被分配给变量
item
,因此
“☕”
,
“💻”
,
“🍷”
,
“🍫”
被打印。
13
var status ="😎"setTimeout(()=>{const status ="😍"const data ={
status:"🥑",getStatus(){returnthis.status
}}
console.log(data.getStatus())
console.log(data.getStatus.call(this))},0)
答:
🥑
undefined
这段代码中,
data.getStatus()
和
data.getStatus.call(this)
的返回值取决于函数调用时的上下文(也就是this的值)。
data.getStatus()
:在这种情况下,this指向的是data对象,因此this.status返回的是data对象的status属性,即"🥑"。所以,console.log(data.getStatus())
将打印出"🥑"。data.getStatus.call(this)
:Function.prototype.call
方法允许你改变函数调用时this的值。在这个例子中,由于call方法被调用时没有提供参数,所以this的值将是全局对象(在非严格模式下)。然而,由于这段代码是在一个箭头函数中执行的,this的值实际上是从包围它的普通(非箭头)函数(在这种情况下是全局作用域)继承来的。在全局作用域中,this通常指向全局对象(在浏览器中是window),但是由于status不是全局对象的属性,this.status将返回undefined。所以,console.log(data.getStatus.call(this))
将打印出undefined。
需要注意的是,这个行为可能会因JavaScript运行环境的不同而有所差异。例如,在Node.js中,全局this的值是一个空对象,而不是global对象。
14
functioncheckAge(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))
答:
ReferenceError: message is not defined
const
和
let
声明的变量是具有块级作用域的,块是大括号(
{}
)之间的任何东西,即上述情况
if / else
语句的花括号。
在return的地方已经没有message这个变量了。
15
打印什么?
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
,将值传递给下一个处理程序。
16
// module.js exportdefault()=>"Hello world"exportconst name ="Lydia"// index.js import*as data from"./module"
console.log(data)
答:
{default:functiondefault(), name:"Lydia"}
使用
import * as name
语法,我们将
module.js
文件中所有
export
导入到
index.js
文件中,并且创建了一个名为
data
的新对象。在
module.js
文件中,有两个导出:默认导出和命名导出。默认导出是一个返回字符串“Hello World”的函数,命名导出是一个名为
name
的变量,其值为字符串
“Lydia”
。
data
对象具有默认导出的
default
属性,其他属性具有指定 exports 的名称及其对应的值。
17
classPerson{constructor(name){this.name = name
}}const member =newPerson("John")
console.log(typeof member)
答:
object
解析:
类是构造函数的语法糖,如果用构造函数的方式来重写
Person
类则将是:
functionPerson(){this.name = name
}
通过
new
来调用构造函数,将会生成构造函数
Person
的实例,对实例执行
typeof
关键字将返回
"object"
,上述情况打印出
"object"
。
18
functiongiveLydiaPizza(){return"Here is pizza!"}constgiveLydiaChocolate=()=>"Here's chocolate... now go hit the gym already."
console.log(giveLydiaPizza.prototype)
console.log(giveLydiaChocolate.prototype)
答:
{ constructor:...}undefined
解析:
在JavaScript中,只有通过function关键字定义的函数才有prototype属性。箭头函数并没有prototype属性。
所以,
console.log(giveLydiaPizza.prototype)
将打印出giveLydiaPizza函数的原型对象,通常是一个空对象,但包含一个constructor属性指向该函数本身。
而
console.log(giveLydiaChocolate.prototype)
将打印出
undefined
,因为giveLydiaChocolate是一个箭头函数,它没有prototype属性。
19
functiongetItems(fruitList,...args, favoriteFruit){return[...fruitList,...args, favoriteFruit]}getItems(["banana","apple"],"pear","orange")
答:
SyntaxError: Rest parameter must be last formal parameter
解析:
... args
是剩余参数,剩余参数的值是一个包含所有剩余参数的数组,并且只能作为最后一个参数。
20
functionnums(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 is bigger
undefined
b is bigger
undefined
解析:
相当于:
functionnums(a, b){if(a > b) console.log("a is bigger");else console.log("b is bigger");return;
a + b;}
a+b永远走不到,只return一个undefined。
版权归原作者 karshey 所有, 如有侵权,请联系我们删除。