当前位置: 首页 > article >正文

【前端】20道JavaScript进阶问题(3-完结)

来源:

javascript-questions/zh-CN/README-zh_CN.md at master · lydiahallie/javascript-questions · GitHub
记录一些有趣的题。

系列:
【前端】35道JavaScript进阶问题(1)
【前端】20道JavaScript进阶问题(2)

1

const info = {
  [Symbol('a')]: 'b'
}

console.log(info)
console.log(Object.keys(info))

答:

{ [Symbol(a)]: 'b' }
[]

第一个 console.log(info) 语句打印出整个对象,包括符号键。然而,第二个 console.log(Object.keys(info)) 语句返回一个空数组,因为 Object.keys() 只返回可枚举属性的名称作为一个字符串数组,它不包括 Symbol 属性。

如果你想获取用作对象键的符号,你可以使用 Object.getOwnPropertySymbols()

console.log(Object.getOwnPropertySymbols(info))
[ Symbol('a') ]

2

const output = `${[] && 'Im'}possible!
You should${'' && `n't`} see a therapist after so much JavaScript lol`

答:

Impossible!
You should see a therapist after so much JavaScript lol

解析:

[]是一个真值。使用&&运算符,如果左侧值是真值,则返回右侧值。在这种情况下,左侧值[]是一个真值,所以返回Im

""是一个假值。如果左侧值是假的,则不返回任何内容。n't不会被退回。

使用||运算符,我们可以返回第一个真值。如果所有值都是假值,则返回最后一个值。

3

Promise.resolve(5)

答:

Promise {<fulfilled>: 5}

4

function compareMembers(person1, person2 = person) {
  if (person1 !== person2) {
    console.log("Not the same!")
  } else {
    console.log("They are the same!")
  }
}

const person = { name: "Lydia" }

compareMembers(person)

答:

They are the same!

解析:

使用同一个引用person

5

const colorConfig = {
  red: true,
  blue: false,
  green: true,
  black: true,
  yellow: false,
}

const colors = ["pink", "red", "blue"]

console.log(colorConfig.colors[1])

答:

TypeError

解析:

colorConfig.colors是undefined,undefined[1]会报错。

6

哪些方法修改了原数组:

const emojis = ['✨', '🥑', '😍']

emojis.map(x => x + '✨')
emojis.filter(x => x !== '🥑')
emojis.find(x => x !== '🥑')
emojis.reduce((acc, cur) => acc + '✨')
emojis.slice(1, 2, '✨') 
emojis.splice(1, 2, '✨')

答:

splice修改原数组。

解析:

mapfilterslice返回一个新数组,find返回一个元素,而reduce返回一个减小的值。

7

这个函数干了什么?

JSON.parse()

答:

将 JSON 字符串解析为 JavaScript 值。(不会只解析为对象)

8

let name = 'Lydia'

function getName() {
  console.log(name)
  let name = 'Sarah'
}

getName()

答:

ReferenceError

解析:

name变量定义在函数作用域里。let没有作用域的提升,在console.log(name)时还没有name的声明。会报错。

但是:

let name = 'Lydia'

function getName() {
  console.log(name)
}

getName() // Lydia

根据作用域链,会找到外面的name,输出Lydia

9

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

解析:

generatorOne 和 generatorTwo 都是生成器函数,它们使用 yield 关键字来产生一系列的值。但是,它们在处理数组时有所不同。

generatorOne 使用 yield [‘a’, ‘b’, ‘c’],这会直接返回整个数组 [‘a’, ‘b’, ‘c’]。因此,当你调用 one.next().value,你得到的是整个数组 [‘a’, ‘b’, ‘c’]。

generatorTwo 使用 yield* [‘a’, ‘b’, ‘c’],yield* 是一个特殊的语法,它会遍历可迭代对象(在这种情况下是数组)并逐个产生其元素。 因此,当你首次调用 two.next().value,你得到的是数组的第一个元素 ‘a’。如果你再次调用 two.next().value,你将得到 ‘b’,然后是 ‘c’。

console.log(one.next().value) // ['a', 'b', 'c']
console.log(one.next().value) // undefined
console.log(two.next().value) // 'a'
console.log(two.next().value) // 'b'
console.log(two.next().value) // 'c'
console.log(two.next().value) // undefined

为什么第一个会直接返回整个数组?

在JavaScript中,yield关键字用于从生成器函数返回一个值,并暂停执行。当你使用yield关键字与一个数组一起时,它会将整个数组视为一个单一的值,并直接返回这个数组。

在generatorOne函数中,yield ['a', 'b', 'c']语句就是这样工作的。它返回了整个数组[‘a’, ‘b’, ‘c’],并且暂停了函数的执行。所以,当你调用one.next().value,你得到的是整个数组[‘a’, ‘b’, ‘c’]。

如果你想要逐个返回数组中的元素,你可以使用yield*语句,如generatorTwo函数所示。yield*语句会遍历可迭代对象(例如数组),并逐个返回其元素。

10

console.log(`${(x => x)('I love')} to program`)

答:

I love to program

解析:

${(x => x)('I love')} 是一个模板字符串中的表达式。在这个表达式中,(x => x) 是一个箭头函数它接收一个参数 x 并直接返回这个参数。当你调用这个函数并传入 ‘I love’ 作为参数时,它会返回 ‘I love’。

因此,${(x => x)(‘I love’)} 这个表达式的值就是 ‘I love’,所以整个模板字符串的值就是 ‘I love to program’。

11

let config = {
  alert: setInterval(() => {
    console.log('Alert!')
  }, 1000)
}

config = null
  • A: setInterval 的回调不会被调用
  • B: setInterval 的回调被调用一次
  • C: setInterval 的回调仍然会被每秒钟调用
  • D: 我们从没调用过 config.alert(), config 为 null

答:

C。

解析:

这段代码首先创建了一个名为config的对象,并在该对象中定义了一个属性alert。这个alert属性是一个定时器,每隔1000毫秒(1秒)就会打印出’Alert!'。

然后,你将config设置为null。这意味着config不再引用之前的对象,看起来好像它已经被删除了。但实际上,虽然config现在是null,定时器仍然在运行,并且每隔1秒就会打印出’Alert!'。

这是因为setInterval()函数创建的定时器并不依赖于创建它的对象或变量。 即使你将config设置为null,定时器仍然存在并持续运行,直到你明确地使用clearInterval()函数来停止它,或者关闭页面(在浏览器环境中)或结束进程(在Node.js环境中)。

省流:只有显式地调用clearInterval()来停止它,定时器才会停止。

12

哪一个方法会返回 'Hello world!'

const myMap = new Map()
const myFunc = () => 'greeting'

myMap.set(myFunc, 'Hello world!')

//1
myMap.get('greeting')
//2
myMap.get(myFunc)
//3
myMap.get(() => 'greeting')

答:

2

解析:

在这段代码中,你使用函数myFunc(而不是字符串’greeting’)作为键来设置Map的值。因此,当你使用相同的函数myFunc作为键来获取值时,它会返回 ‘Hello world!’。

对于方法1 myMap.get('greeting') 和方法3 myMap.get(() => 'greeting'),它们都不会返回 ‘Hello world!’,因为它们使用的键与设置Map时使用的键不同。在JavaScript的Map对象中,键的比较是基于同一性(即必须完全相同),而不是基于等价性。

13

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

console.log(config.language);

答:

undefined。

解析:

language是一个setter,不是一个值。所以是undefined

14

const name = "Lydia Hallie";

console.log(!typeof name === "object");
console.log(!typeof name === "string");

答:

false
false

解析:

!操作符的优先级高于 === 操作符。因此,问题相当于:

(!'string') === 'object'

即:

false === 'object'

因此两个都是false。

15

const add = x => y => z => {
	console.log(x, y, z);
	return x + y + z;
};

add(4)(5)(6);

答:

4 5 6

解析:

add 是一个柯里化函数,它接收一个参数并返回一个新的函数,这个新的函数也接收一个参数并返回另一个新的函数。最后这个新的函数接收一个参数,打印出所有的参数,并返回这三个参数的和。

所以当你调用 add(4)(5)(6) 时,首先调用 add(4) 返回一个新的函数,这个新的函数等待接收第二个参数。然后你调用这个新的函数并传入 5 作为参数,它又返回另一个新的函数,等待接收第三个参数。最后你调用这个新的函数并传入 6 作为参数,它打印出所有的参数 4, 5, 6,并返回这三个参数的和 15。

16

哪个作为method的值可以打印{ name: "Lydia", age: 22 }?

const keys = ["name", "age"]
const values = ["Lydia", 22]

const method = /* ?? */
Object[method](keys.map((_, i) => {
	return [keys[i], values[i]]
})) // { name: "Lydia", age: 22 }
  • A: entries
  • B: values
  • C: fromEntries
  • D: forEach

答:

C。

解析:

Object.fromEntries() 是一个JavaScript的静态方法,它接收一个键值对的列表(通常是一个二维数组或者一个可迭代对象)并返回一个新的对象,这个新的对象的属性由这些键值对定义。

例如:

const entries = [['name', 'John'], ['age', 30]];
const obj = Object.fromEntries(entries);
console.log(obj); // { name: 'John', age: 30 }

在这个例子中,Object.fromEntries() 接收一个二维数组 entries 并返回一个新的对象 obj。这个新的对象有两个属性:name 和 age,它们的值分别是 ‘John’ 和 30。

注意,Object.fromEntries() 是在ES2019中引入的,所以在旧版本的JavaScript环境中可能不可用。

17

const user = {
	email: "my@email.com",
	updateEmail: email => {
		this.email = email
	}
}

user.updateEmail("new@email.com")
console.log(user.email)

答:

"my@email.com"

解析:

在JavaScript中,箭头函数并不绑定this。所以,在updateEmail方法中,this并不指向user对象,而是指向了该箭头函数被定义时的上下文(通常是全局对象,在浏览器中是window,在Node.js中是global)。

因此,user.updateEmail("new@email.com")实际上并没有改变user对象的email属性,而是尝试在全局对象上设置一个email属性。然后,当你打印user.email时,它仍然是原来的值。

如果你想要在方法中访问和修改对象的属性,你应该使用普通的函数,而不是箭头函数,像这样:

const user = {
	email: "my@email.com",
	updateEmail: function(email) {
		this.email = email;
	}
}

user.updateEmail("new@email.com")
console.log(user.email) // "new@email.com"

在这个版本的代码中,updateEmail是一个普通的函数,所以this指向user对象。因此,user.updateEmail("new@email.com")正确地改变了user对象的email属性,然后打印user.email会得到新的值。

18

const animals = {};
let dog = { emoji: '🐶' }
let cat = { emoji: '🐈' }

animals[dog] = { ...dog, name: "Mara" }
animals[cat] = { ...cat, name: "Sara" }

console.log(animals[dog])

答:

{ emoji: '🐈', name: 'Sara' }

解析:

对象的键会被转换为字符串。

因为 dog 的值是一个对象,animals[dog] 实际上意味着我们创建了一个叫做 "object Object" 的属性来代表新的对象。animals["object Object"] 现在等于 { emoji: "🐶", name: "Mara"}

cat 也是一个对象,animals[cat] 实际上意味着我们在用新的 cat 的属性覆盖animals["object Object"] 的值。

打印 animals[dog],实际上是animals["object Object"],这是因为转化dog对象为一个字符串结果 "object Object",所以返回 { emoji: "🐈", name: "Sara" }

19

哪一个选项会导致报错?

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

/* 1 */ emojis.push("🦌");
/* 2 */ emojis.splice(0, 2);
/* 3 */ emojis = [...emojis, "🥂"];
/* 4 */ emojis.length = 0;

答:

3

解析:

这是一个const常量,不能用=赋值。

20

const randomValue = 21;

function getInfo() {
	console.log(typeof randomValue);
	const randomValue = "Lydia Hallie";
}

getInfo();

答:

ReferenceError

解析:

通过 const 关键字声明的变量在被初始化之前不可被引用:这被称之为 暂时性死区

如果没有const randomValue = "Lydia Hallie";,会输出number


http://www.kler.cn/a/552948.html

相关文章:

  • 一周学会Flask3 Python Web开发-request请求钩子(Hook)
  • Qt之多线程处理
  • Netty:高并发网络编程的核心框架
  • JVM类文件结构深度解析:跨平台基石与字节码探秘
  • 深度学习-118-Text2SQL之基于langchain和LLM将问题文本转化成SQL语句和答案
  • 《天津大学DeepSeek原理与效应》.pdf(文末有完整版下载地址)
  • leetcode刷题-动态规划06
  • 23种设计模式 - 空对象模式
  • 使用 ollama 在 windows 系统本地部署 deepseek r1 模型
  • 深入解析 Flutter GetX
  • Redis 客户端C++使用
  • GoFound 与 MySQL 集成优化方案
  • 寒假总结与心得
  • 侯捷 C++ 课程学习笔记:设计模式在面向对象开发中的应用
  • Python 爬虫入门:从基础到实战
  • 修改项目的一些前端记录(自用)
  • MySQL-慢SQL解析及调试分析思路
  • 可变列二维数组【C语言】
  • 内网常见问题处理
  • java数据结构_优先级队列(堆)_6.1