0


【前端】20道JavaScript进阶问题(2)

来源:

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。


本文转载自: https://blog.csdn.net/karshey/article/details/142592587
版权归原作者 karshey 所有, 如有侵权,请联系我们删除。

“【前端】20道JavaScript进阶问题(2)”的评论:

还没有评论