JavaScript 进阶问题列表(各种js代码段66-107)
投稿:mdxy-dxy
我在我的 Instagram 上每天都会发布 JavaScript 的多选问题,并且同时也会在这个仓库中发布。
从基础到进阶,测试你有多了解 JavaScript,刷新你的知识,或者帮助你的 coding 面试! :muscle: :rocket: 我每周都会在这个仓库下更新新的问题。
答案在问题下方的折叠部分,点击即可展开问题。祝你好运
66. 使用哪个构造函数可以成功继承Dog
类?
class Dog { constructor(name) { this.name = name; } }; class Labrador extends Dog { // 1 constructor(name, size) { this.size = size; } // 2 constructor(name, size) { super(name); this.size = size; } // 3 constructor(size) { super(name); this.size = size; } // 4 constructor(name, size) { this.name = name; this.size = size; } };
- A: 1
- B: 2
- C: 3
- D: 4
答案
答案:B
在子类中,在调用super
之前不能访问到this
关键字。如果这样做,它将抛出一个ReferenceError
:1 和 4 将引发一个引用错误。
使用super
关键字,需要用给定的参数来调用父类的构造函数。父类的构造函数接收name
参数,因此我们需要将name
传递给super
。
Labrador
类接收两个参数,name
参数是由于它继承了Dog
,size
作为Labrador
类的额外属性,它们都需要传递给Labrador
的构造函数,因此使用构造函数 2 正确完成。
67. 输出什么?
// index.js console.log('running index.js'); import { sum } from './sum.js'; console.log(sum(1, 2)); // sum.js console.log('running sum.js'); export const sum = (a, b) => a + b;
- A:
running index.js
,running sum.js
,3
- B:
running sum.js
,running index.js
,3
- C:
running sum.js
,3
,running index.js
- D:
running index.js
,undefined
,running sum.js
答案
答案:B
import
命令是编译阶段执行的,在代码运行之前。因此这意味着被导入的模块会先运行,而导入模块的文件会后执行。
这是 CommonJS 中require()
和import
之间的区别。使用require()
,您可以在运行代码时根据需要加载依赖项。如果我们使用require
而不是import
,running index.js
,running sum.js
,3
会被依次打印。
68. 输出什么?
console.log(Number(2) === Number(2)) console.log(Boolean(false) === Boolean(false)) console.log(Symbol('foo') === Symbol('foo'))
- A:
true
,true
,false
- B:
false
,true
,false
- C:
true
,false
,true
- D:
true
,true
,true
答案
答案:A
每个Symbol
都是完全唯一的。传递给Symbol
的参数只是给Symbol
的一个描述。Symbol
的值不依赖于传递的参数。当我们测试相等时,我们创建了两个全新的符号:第一个Symbol('foo')
,第二个Symbol('foo')
,这两个值是唯一的,彼此不相等,因此返回false
。
69. 输出什么?
const name = "Lydia Hallie" console.log(name.padStart(13)) console.log(name.padStart(2))
- A:
"Lydia Hallie"
,"Lydia Hallie"
- B:
" Lydia Hallie"
," Lydia Hallie"
("[13x whitespace]Lydia Hallie"
,"[2x whitespace]Lydia Hallie"
) - C:
" Lydia Hallie"
,"Lydia Hallie"
("[1x whitespace]Lydia Hallie"
,"Lydia Hallie"
) - D:
"Lydia Hallie"
,"Lyd"
答案
答案:C
使用padStart
方法,我们可以在字符串的开头添加填充。传递给此方法的参数是字符串的总长度(包含填充)。字符串Lydia Hallie
的长度为12
,因此name.padStart(13)
在字符串的开头只会插入 1(13 - 12 = 1
)个空格。
如果传递给padStart
方法的参数小于字符串的长度,则不会添加填充。
70. 输出什么?
console.log("🥑" + "💻");
- A:
"🥑💻"
- B:
257548
- C: A string containing their code points
- D: Error
答案
答案:A
使用+
运算符,您可以连接字符串。上述情况,我们将字符串“🥑”
与字符串”💻“
连接起来,产生”🥑💻“
。
71. 如何能打印出console.log
语句后注释掉的值?
function* startGame() { const 答案 = yield "Do you love JavaScript?"; if (答案 !== "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
关键字时会“暂停”其执行。首先,我们需要让函数产生字符串Do you love JavaScript?
,这可以通过调用game.next().value
来完成。上述函数的第一行就有一个yield
关键字,那么运行立即停止了,yield
表达式本身没有返回值,或者说总是返回undefined
,这意味着此时变量 答案
为undefined
next
方法可以带一个参数,该参数会被当作上一个 yield
表达式的返回值。当我们调用game.next("Yes").value
时,先前的 yield
的返回值将被替换为传递给next()
函数的参数"Yes"
。此时变量 答案
被赋值为 "Yes"
,if
语句返回false
,所以JavaScript loves you back ❤️
被打印。
72. 输出什么?
console.log(String.raw`Hello\nworld`);
- A:
Hello world!
- B:
Hello
world
- C:
Hello\nworld
- D:
Hello\n
world
答案
答案:C
String.raw
函数是用来获取一个模板字符串的原始字符串的,它返回一个字符串,其中忽略了转义符(\n
,\v
,\t
等)。但反斜杠可能造成问题,因为你可能会遇到下面这种类似情况:
const path = `C:\Documents\Projects\table.html` String.raw`${path}`
这将导致:
"C:DocumentsProjects able.html"
直接使用String.raw
String.raw`C:\Documents\Projects\table.html`
C:\Documents\Projects\table.html
上述情况,字符串是Hello\nworld
被打印出。
73. 输出什么?
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!"
74. 输出什么?
function addToList(item, list) { return list.push(item); } const result = addToList("apple", ["banana"]); console.log(result);
- A:
['apple', 'banana']
- B:
2
- C:
true
- D:
undefined
答案
答案:B
push()
方法返回新数组的长度。一开始,数组包含一个元素(字符串"banana"
),长度为 1。在数组中添加字符串"apple"
后,长度变为 2,并将从addToList
函数返回。
push
方法修改原始数组,如果你想从函数返回数组而不是数组长度,那么应该在 push item
之后返回list
。
75. 输出什么?
const box = { x: 10, y: 20 }; Object.freeze(box); const shape = box; shape.x = 100; console.log(shape)
- A:
{ x: 100, y: 20 }
- B:
{ x: 10, y: 20 }
- C:
{ x: 100 }
- D:
ReferenceError
答案
答案:B
Object.freeze
使得无法添加、删除或修改对象的属性(除非属性的值是另一个对象)。
当我们创建变量shape
并将其设置为等于冻结对象box
时,shape
指向的也是冻结对象。你可以使用Object.isFrozen
检查一个对象是否被冻结,上述情况,Object.isFrozen(shape)
将返回true
。
由于shape
被冻结,并且x
的值不是对象,所以我们不能修改属性x
。x
仍然等于10
,{x:10,y:20}
被打印。
注意,上述例子我们对属性x
进行修改,可能会导致抛出 TypeError 异常(最常见但不仅限于严格模式下时)。
76. 输出什么?
const { name: myName } = { name: "Lydia" }; console.log(name);
- A:
"Lydia"
- B:
"myName"
- C:
undefined
- D:
ReferenceError
答案
答案:D
当我们从右侧的对象解构属性name
时,我们将其值Lydia
分配给名为myName
的变量。
使用{name:myName}
,我们是在告诉 JavaScript 我们要创建一个名为myName
的新变量,并且其值是右侧对象的name
属性的值。
当我们尝试打印name
,一个未定义的变量时,就会引发ReferenceError
。
77. 以下是个纯函数么?
function sum(a, b) { return a + b; }
- A: Yes
- B: No
答案
答案:A
纯函数在相同的输入值时,需产生相同的输出,其输出的结果,与输入值以外的其他隐藏信息或状态无关,也和由 I/O 设备产生的外部输出无关。 纯函数不会产生副作用。
纯函数与副作用的定义可参考: https://zh.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)
78. 输出什么?
const add = () => { const cache = {}; return num => { if (num in cache) { return `From cache! ${cache[num]}`; } else { const result = num + 10; cache[num] = result; return `Calculated! ${result}`; } }; }; const addFunction = add(); console.log(addFunction(10)); console.log(addFunction(10)); console.log(addFunction(5 * 2));
- A:
Calculated! 20
Calculated! 20
Calculated! 20
- B:
Calculated! 20
From cache! 20
Calculated! 20
- C:
Calculated! 20
From cache! 20
From cache! 20
- D:
Calculated! 20
From cache! 20
Error
答案
答案:C
add
函数是一个记忆函数。通过记忆化,我们可以缓存函数的结果,以加快其执行速度。上述情况,我们创建一个cache
对象,用于存储先前返回过的值。
如果我们使用相同的参数多次调用addFunction
函数,它首先检查缓存中是否已有该值,如果有,则返回缓存值,这将节省执行时间。如果没有,那么它将计算该值,并存储在缓存中。
我们用相同的值三次调用了addFunction
函数:
在第一次调用,num
等于10
时函数的值尚未缓存,if 语句num in cache
返回false
,else 块的代码被执行:Calculated! 20
,并且其结果被添加到缓存对象,cache
现在看起来像{10:20}
。
第二次,cache
对象包含10
的返回值。if 语句 num in cache
返回true
,From cache! 20
被打印。
第三次,我们将5 * 2
(值为 10) 传递给函数。cache
对象包含10
的返回值。if 语句 num in cache
返回true
,From cache! 20
被打印。
79. 输出什么?
const myLifeSummedUp = ["☕", "💻", "🍷", "🍫"] for (let item in myLifeSummedUp) { console.log(item) } for (let item of myLifeSummedUp) { console.log(item) }
- A:
0
1
2
3
and"☕"
"💻"
"🍷"
"🍫"
- B:
"☕"
"💻"
"🍷"
"🍫"
and"☕"
"💻"
"🍷"
"🍫"
- C:
"☕"
"💻"
"🍷"
"🍫"
and0
1
2
3
- D:
0
1
2
3
and{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}
答案
答案:A
通过for-in
循环,我们可以遍历一个对象自有的、继承的、可枚举的、非 Symbol 的属性。在数组中,可枚举属性是数组元素的“键”,即它们的索引。类似于下面这个对象:
{0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}
其中键则是可枚举属性,因此 0
,1
,2
,3
被记录。
通过for-of
循环,我们可以迭代可迭代对象(包括 Array
,Map
,Set
,String
,arguments
等)。当我们迭代数组时,在每次迭代中,不同属性的值将被分配给变量item
,因此“☕”
,“💻”
,“🍷”
,“🍫”
被打印。
80. 输出什么?
const list = [1 + 2, 1 * 2, 1 / 2] console.log(list)
- A:
["1 + 2", "1 * 2", "1 / 2"]
- B:
["12", 2, 0.5]
- C:
[3, 2, 0.5]
- D:
[1, 1, 1]
答案
答案:C
数组元素可以包含任何值。数字,字符串,布尔值,对象,数组,null
,undefined
,以及其他表达式,如日期,函数和计算。
元素将等于返回的值。1 + 2
返回3
,1 * 2
返回'2,'1 / 2
返回0.5
。
81. 输出什么?
function sayHi(name) { return `Hi there, ${name}` } console.log(sayHi())
- A:
Hi there,
- B:
Hi there, undefined
- C:
Hi there, null
- D:
ReferenceError
答案
答案:B
默认情况下,如果不给函数传参,参数的值将为undefined
。上述情况,我们没有给参数name
传值。name
等于undefined
,并被打印。
在 ES6 中,我们可以使用默认参数覆盖此默认的undefined
值。例如:
function sayHi (name =“Lydia”){...}
在这种情况下,如果我们没有传递值或者如果我们传递undefined
,name
总是等于字符串Lydia
82. 输出什么?
var status = "😎" setTimeout(() => { const status = "😍" const data = { status: "🥑", getStatus() { return this.status } } console.log(data.getStatus()) console.log(data.getStatus.call(this)) }, 0)
- A:
"🥑"
and"😍"
- B:
"🥑"
and"😎"
- C:
"😍"
and"😎"
- D:
"😎"
and"😎"
答案
答案:B
this
关键字的指向取决于使用它的位置。在函数中,比如getStatus
,this
指向的是调用它的对象,上述例子中data
对象调用了getStatus
,因此this
指向的就是data
对象。当我们打印this.status
时,data
对象的status
属性被打印,即"🥑"
。
使用call
方法,可以更改this
指向的对象。data.getStatus.call(this)
是将this
的指向由data
对象更改为全局对象。在全局对象上,有一个名为status
的变量,其值为”😎“
。因此打印this.status
时,会打印“😎”
。
83. 输出什么?
const person = { name: "Lydia", age: 21 } let city = person.city city = "Amsterdam" console.log(person)
- A:
{ name: "Lydia", age: 21 }
- B:
{ name: "Lydia", age: 21, city: "Amsterdam" }
- C:
{ name: "Lydia", age: 21, city: undefined }
- D:
"Amsterdam"
答案
答案:A
我们将变量city
设置为等于person
对象上名为city
的属性的值。这个对象上没有名为city
的属性,因此变量city
的值为undefined
。
请注意,我们没有引用person
对象本身,只是将变量city
设置为等于person
对象上city
属性的当前值。
然后,我们将city
设置为等于字符串“Amsterdam”
。这不会更改 person 对象:没有对该对象的引用。
因此打印person
对象时,会返回未修改的对象。
84. 输出什么?
function checkAge(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))
- A:
"Sorry, you're too young."
- B:
"Yay! You're old enough!"
- C:
ReferenceError
- D:
undefined
答案
答案:C
const
和let
声明的变量是具有块级作用域的,块是大括号({}
)之间的任何东西,即上述情况if / else
语句的花括号。由于块级作用域,我们无法在声明的块之外引用变量,因此抛出ReferenceError
。
85. 什么样的信息将被打印?
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
,将值传递给下一个处理程序。
86. 哪个选项是将hasName
设置为true
的方法,前提是不能将true
作为参数传递?
function getName(name) { const hasName = // }
- A:
!!name
- B:
name
- C:
new Boolean(name)
- D:
name.length
答案
答案:A
使用逻辑非运算符!
,将返回一个布尔值,使用!! name
,我们可以确定name
的值是真的还是假的。如果name
是真实的,那么!name
返回false
。!false
返回true
。
通过将hasName
设置为name
,可以将hasName
设置为等于传递给getName
函数的值,而不是布尔值true
。
new Boolean(true)
返回一个对象包装器,而不是布尔值本身。
name.length
返回传递的参数的长度,而不是布尔值true
。
87. 输出什么?
console.log("I want pizza"[0])
- A:
"""
- B:
"I"
- C:
SyntaxError
- D:
undefined
答案
答案:B
可以使用方括号表示法获取字符串中特定索引的字符,字符串中的第一个字符具有索引 0,依此类推。在这种情况下,我们想要得到索引为 0 的元素,字符'I'
被记录。
请注意,IE7 及更低版本不支持此方法。在这种情况下,应该使用.charAt()
88. 输出什么?
function sum(num1, num2 = num1) { console.log(num1 + num2) } sum(10)
- A:
NaN
- B:
20
- C:
ReferenceError
- D:
undefined
答案
答案:B
您可以将默认参数的值设置为函数的另一个参数,只要另一个参数定义在其之前即可。我们将值10
传递给sum
函数。如果sum
函数只接收 1 个参数,则意味着没有传递num2
的值,这种情况下,num1
的值等于传递的值10
。num2
的默认值是num1
的值,即10
。num1 + num2
返回20
。
如果您尝试将默认参数的值设置为后面定义的参数,则可能导致参数的值尚未初始化,从而引发错误。比如:
function test(m = n, n = 2) { console.log(m, n) } test() // Uncaught ReferenceError: Cannot access 'n' before initialization test(3) // 3 2 test(3, 4) // 3 4
89. 输出什么?
// module.js export default () => "Hello world" export const name = "Lydia" // index.js import * as data from "./module" console.log(data)
- A:
{ default: function default(), name: "Lydia" }
- B:
{ default: function default() }
- C:
{ default: "Hello world", name: "Lydia" }
- D: Global object of
module.js
答案
答案:A
使用import * as name
语法,我们将module.js
文件中所有export
导入到index.js
文件中,并且创建了一个名为data
的新对象。在module.js
文件中,有两个导出:默认导出和命名导出。默认导出是一个返回字符串“Hello World”的函数,命名导出是一个名为name
的变量,其值为字符串“Lydia”
。
data
对象具有默认导出的default
属性,其他属性具有指定 exports 的名称及其对应的值。
90. 输出什么?
class Person { constructor(name) { this.name = name } } const member = new Person("John") console.log(typeof member)
- A:
"class"
- B:
"function"
- C:
"object"
- D:
"string"
答案
答案:C
类是构造函数的语法糖,如果用构造函数的方式来重写Person
类则将是:
function Person() { this.name = name }
通过new
来调用构造函数,将会生成构造函数Person
的实例,对实例执行typeof
关键字将返回"object"
,上述情况打印出"object"
。
91. 输出什么?
let newList = [1, 2, 3].push(4) console.log(newList.push(5))
- A:
[1, 2, 3, 4, 5]
- B:
[1, 2, 3, 5]
- C:
[1, 2, 3, 4]
- D:
Error
答案
答案:D
.push
方法返回数组的长度,而不是数组本身!通过将newList
设置为[1,2,3].push(4)
,实际上newList
等于数组的新长度:4
。
然后,尝试在newList
上使用.push
方法。由于newList
是数值4
,抛出 TypeError。
92. 输出什么?
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
属性。尝试使用giveLydiaChocolate.prototype
访问prototype
属性时会返回undefined
。
93. 输出什么?
const person = { name: "Lydia", age: 21 } for (const [x, y] of Object.entries(person)) { console.log(x, y) }
- A:
name
Lydia
andage
21
- B:
["name", "Lydia"]
and["age", 21]
- C:
["name", "age"]
andundefined
- D:
Error
答案
答案:A
Object.entries()
方法返回一个给定对象自身可枚举属性的键值对数组,上述情况返回一个二维数组,数组每个元素是一个包含键和值的数组:
[['name','Lydia'],['age', 21]]
使用for-of
循环,我们可以迭代数组中的每个元素,上述情况是子数组。我们可以使用const [x,y]
在for-of
循环中解构子数组。x
等于子数组中的第一个元素,y
等于子数组中的第二个元素。
第一个子阵列是[“name”,“Lydia”]
,其中x
等于name
,而y
等于Lydia
。 第二个子阵列是[“age”,21]
,其中x
等于age
,而y
等于21
。
94. 输出什么?
function getItems(fruitList, ...args, favoriteFruit) { return [...fruitList, ...args, favoriteFruit] } getItems(["banana", "apple"], "pear", "orange")
- A:
["banana", "apple", "pear", "orange"]
- B:
[["banana", "apple"], "pear", "orange"]
- C:
["banana", "apple", ["pear"], "orange"]
- D:
SyntaxError
答案
答案:D
... args
是剩余参数,剩余参数的值是一个包含所有剩余参数的数组,并且只能作为最后一个参数。上述示例中,剩余参数是第二个参数,这是不可能的,并会抛出语法错误。
function getItems(fruitList, favoriteFruit, ...args) { return [...fruitList, ...args, favoriteFruit] }
getItems(["banana", "apple"], "pear", "orange")
上述例子是有效的,将会返回数组:[ 'banana', 'apple', 'orange', 'pear' ]
95. 输出什么?
function nums(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:
a is bigger
,6
andb is bigger
,3
- B:
a is bigger
,undefined
andb is bigger
,undefined
- C:
undefined
andundefined
- D:
SyntaxError
答案
答案:B
在 JavaScript 中,我们不必显式地编写分号 (;
),但是 JavaScript 引擎仍然在语句之后自动添加分号。这称为自动分号插入。例如,一个语句可以是变量,或者像throw
、return
、break
这样的关键字。
在这里,我们在新的一行上写了一个return
语句和另一个值a + b
。然而,由于它是一个新行,引擎并不知道它实际上是我们想要返回的值。相反,它会在return
后面自动添加分号。你可以这样看:
return; a + b
这意味着永远不会到达a + b
,因为函数在return
关键字之后停止运行。如果没有返回值,就像这里,函数返回undefined
。注意,在if/else
语句之后没有自动插入!
96. 输出什么?
class Person { constructor() { this.name = "Lydia" } } Person = class AnotherPerson { constructor() { this.name = "Sarah" } } const member = new Person() console.log(member.name)
- A:
"Lydia"
- B:
"Sarah"
- C:
Error: cannot redeclare Person
- D:
SyntaxError
答案
答案:B
我们可以将类设置为等于其他类/函数构造函数。在这种情况下,我们将Person
设置为AnotherPerson
。这个构造函数的名字是Sarah
,所以新的Person
实例member
上的 name 属性是Sarah
。
97. 输出什么?
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
类型是不可枚举的。Object.keys
方法返回对象上的所有可枚举的键属性。Symbol
类型是不可见的,并返回一个空数组。记录整个对象时,所有属性都是可见的,甚至是不可枚举的属性。
这是Symbol
的众多特性之一:除了表示完全唯一的值(防止对象意外名称冲突,例如当使用 2 个想要向同一对象添加属性的库时),您还可以隐藏
这种方式对象的属性(尽管不完全。你仍然可以使用Object.getOwnPropertySymbols()
方法访问 Symbol
。
98. 输出什么?
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]]
andSyntaxError
- 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
getList
函数接收一个数组作为其参数。在getList
函数的括号之间,我们立即解构这个数组。您可以将其视为:
[x, ...y] = [1, 2, 3, 4]
使用剩余的参数... y
,我们将所有剩余参数放在一个数组中。在这种情况下,其余的参数是2
,3
和4
。 y
的值是一个数组,包含所有其余参数。在这种情况下,x
的值等于1
,所以当我们打印[x,y]
时,会打印[1,[2,3,4]]
。
getUser
函数接收一个对象。对于箭头函数,如果只返回一个值,我们不必编写花括号。但是,如果您想从一个箭头函数返回一个对象,您必须将它写在圆括号之间,否则两个花括号之间的所有内容都将被解释为一个块语句!在这种情况下,花括号之间的代码不是有效的 JavaScript 代码,因此会抛出 SyntaxError。
以下函数将返回一个对象:
const getUser = user => ({ name: user.name, age: user.age })
99. 输出什么?
const name = "Lydia" console.log(name())
- A:
SyntaxError
- B:
ReferenceError
- C:
TypeError
- D:
undefined
答案
答案:C
变量name
保存字符串的值,该字符串不是函数,因此无法调用。
当值不是预期类型时,会抛出TypeErrors
。JavaScript 期望name
是一个函数,因为我们试图调用它。但它是一个字符串,因此抛出TypeError
:name is not a function
当你编写了一些非有效的 JavaScript 时,会抛出语法错误,例如当你把return
这个词写成retrun
时。 当 JavaScript 无法找到您尝试访问的值的引用时,抛出ReferenceErrors
。
100. 输出什么?
// 🎉✨ This is my 100th question! ✨🎉 const output = `${[] && 'Im'}possible! You should${'' && `n't`} see a therapist after so much JavaScript lol`
- A:
possible! You should see a therapist after so much JavaScript lol
- B:
Impossible! You should see a therapist after so much JavaScript lol
- C:
possible! You shouldn't see a therapist after so much JavaScript lol
- D:
Impossible! You shouldn't see a therapist after so much JavaScript lol
答案
答案:B
[]
是一个真值。使用&&
运算符,如果左侧值是真值,则返回右侧值。在这种情况下,左侧值[]
是一个真值,所以返回Im
。
""
是一个假值。如果左侧值是假的,则不返回任何内容。n't
不会被退回。
101.输出什么?
const one = (false || {} || null) const two = (null || false || "") const three = ([] || 0 || true) console.log(one, two, three)
- A:
false
null
[]
- B:
null
""
true
- C:
{}
""
[]
- D:
null
null
true
答案
答案:C
使用||
运算符,我们可以返回第一个真值。如果所有值都是假值,则返回最后一个值。
(false || {} || null)
:空对象{}
是一个真值。这是第一个(也是唯一的)真值,它将被返回。one
等于{}
。
(null || false ||“”)
:所有值都是假值。这意味着返回传递的值""
。two
等于""
。
([] || 0 ||“”)
:空数组[]
是一个真值。这是第一个返回的真值。three
等于[]
。
102. 依次输出什么?
const myPromise = () => Promise.resolve('I have resolved!') function firstFunction() { myPromise().then(res => console.log(res)) console.log('second') } async function secondFunction() { console.log(await myPromise()) console.log('second') } firstFunction() secondFunction()
- A:
I have resolved!
,second
andI have resolved!
,second
- B:
second
,I have resolved!
andsecond
,I have resolved!
- C:
I have resolved!
,second
andsecond
,I have resolved!
- D:
second
,I have resolved!
andI have resolved!
,second
答案
答案:D
有了 promise,我们通常会说:当我想要调用某个方法,但是由于它可能需要一段时间,因此暂时将它放在一边。只有当某个值被 resolved/rejected,并且执行栈为空时才使用这个值。
我们可以在async
函数中通过.then
和await
关键字获得该值。尽管我们可以通过.then
和await
获得 promise 的价值,但是它们的工作方式有所不同。
在 firstFunction
中,当运行到myPromise
方法时我们将其放在一边,即 promise 进入微任务队列,其他后面的代码(console.log('second')
)照常运行,因此second
被打印出,firstFunction
方法到此执行完毕,执行栈中宏任务队列被清空,此时开始执行微任务队列中的任务,I have resolved
被打印出。
在secondFunction
方法中,我们通过await
关键字,暂停了后面代码的执行,直到异步函数的值被解析才开始后面代码的执行。这意味着,它会等着直到 myPromise
以值I have resolved
被解决之后,下一行second
才开始执行。
103. 输出什么?
const set = new Set() set.add(1) set.add("Lydia") set.add({ name: "Lydia" }) for (let item of set) { console.log(item + 2) }
- A:
3
,NaN
,NaN
- B:
3
,7
,NaN
- C:
3
,Lydia2
,[Object object]2
- D:
"12"
,Lydia2
,[Object object]2
答案
答案:C
“+”运算符不仅用于添加数值,还可以使用它来连接字符串。每当 JavaScript 引擎发现一个或多个值不是数字时,就会将数字强制为字符串。
第一个是数字 1。1 + 2 返回数字 3。
但是,第二个是字符串“Lydia”。 “Lydia”是一个字符串,2 是一个数字:2 被强制转换为字符串。 “Lydia”和“2”被连接起来,产生字符串“Lydia2”。
{name:“Lydia”}
是一个对象。数字和对象都不是字符串,因此将二者都字符串化。每当我们对常规对象进行字符串化时,它就会变成[Object object]
。与“2”串联的“ [Object object]”成为“[Object object]2”。
104. 结果是什么?
Promise.resolve(5)
- A:
5
- B:
Promise {<pending>: 5}
- C:
Promise {<fulfilled>: 5}
- D:
Error
答案
答案:C
我们可以将我们想要的任何类型的值传递Promise.resolve
,无论是否promise
。该方法本身返回带有已解析值的Promise
()。如果您传递常规函数,它将是具有常规值的已解决promise
。如果你通过了 promise,它将是一个已经 resolved 的且带有传的值的 promise。
上述情况,我们传了数字 5,因此返回一个 resolved 状态的 promise,resolve 值为5
105. 输出什么?
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)
- A:
Not the same!
- B:
They are the same!
- C:
ReferenceError
- D:
SyntaxError
答案
答案:B
对象通过引用传递。当我们检查对象的严格相等性(===)时,我们正在比较它们的引用。
我们将“person2”的默认值设置为“person”对象,并将“person”对象作为“person1”的值传递。
这意味着两个值都引用内存中的同一位置,因此它们是相等的。
运行“else”语句中的代码块,并记录They are the same!
。
106. 输出什么?
const colorConfig = { red: true, blue: false, green: true, black: true, yellow: false, } const colors = ["pink", "red", "blue"] console.log(colorConfig.colors[1])
- A:
true
- B:
false
- C:
undefined
- D:
TypeError
答案
答案:D
在 JavaScript 中,我们有两种访问对象属性的方法:括号表示法或点表示法。在此示例中,我们使用点表示法(colorConfig.colors
)代替括号表示法(colorConfig [“colors”]
)。
使用点表示法,JavaScript 会尝试使用该确切名称在对象上查找属性。在此示例中,JavaScript 尝试在 colorConfig 对象上找到名为 colors 的属性。没有名为“colors”的属性,因此返回“undefined”。 然后,我们尝试使用[1]
访问第一个元素的值。我们无法对未定义的值执行此操作,因此会抛出Cannot read property '1' of undefined
。
JavaScript 解释(或取消装箱)语句。当我们使用方括号表示法时,它会看到第一个左方括号[
并一直进行下去,直到找到右方括号]
。只有这样,它才会评估该语句。如果我们使用了 colorConfig [colors [1]],它将返回 colorConfig 对象上 red 属性的值。
107. 输出什么?
console.log('❤️' === '❤️')
- A:
true
- B:
false
答案
答案:A
在内部,表情符号是 unicode。heat 表情符号的 unicode 是“U + 2764 U + FE0F”
。对于相同的表情符号,它们总是相同的,因此我们将两个相等的字符串相互比较,这将返回 true。