You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
这才会使 member.getFullName() 起作用。为什么这么做有益的?假设我们将这个方法添加到构造函数本身里。也许不是每个 Person 实例都需要这个方法。这将浪费大量内存空间,因为它们仍然具有该属性,这将占用每个实例的内存空间。相反,如果我们只将它添加到原型中,那么它只存在于内存中的一个位置,但是所有实例都可以访问它!
functiongetPersonInfo(one,two,three){console.log(one)console.log(two)console.log(three)}constperson='Lydia'constage=21getPersonInfo`${person} is ${age} years old`
A: "Lydia"21["", " is ", " years old"]
B: ["", " is ", " years old"]"Lydia"21
C: "Lydia"["", " is ", " years old"]21
答案
答案: B
如果使用标记模板字面量,第一个参数的值总是包含字符串的数组。其余的参数获取的是传递的表达式的值!
18. 输出是什么?
functioncheckAge(data){if(data==={age: 18}){console.log('You are an adult!')}elseif(data=={age: 18}){console.log('You are still an adult.')}else{console.log(`Hmm.. You don't have an age I guess`)}}checkAge({age: 18})
functiongreeting(){throw"Hello world!";}functionsayHi(){try{constdata=greeting();console.log("It worked!",data);}catch(e){console.log("Oh no an error!",e);}}sayHi();
classDog{constructor(name){this.name=name;}}Dog.prototype.bark=function(){console.log(`Woof I am ${this.name}`);};constpet=newDog("Mara");pet.bark();deleteDog.prototype.bark;pet.bark();
function*startGame(){constanswer=yield"Do you love JavaScript?";if(answer!=="Yes"){return"Oh wow... Guess we're gone here";}return"JavaScript loves you back ❤️";}constgame=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关键字时会“暂停”其执行。 首先,我们需要让函数产生字符串Do you love JavaScript?,这可以通过调用game.next().value来完成。上述函数的第一行就有一个yield关键字,那么运行立即停止了,yield表达式本身没有返回值,或者说总是返回undefined, 这意味着此时变量 answer 为undefined
next方法可以带一个参数,该参数会被当作上一个 yield 表达式的返回值。当我们调用game.next("Yes").value时,先前的 yield 的返回值将被替换为传递给next()函数的参数"Yes"。此时变量 answer 被赋值为 "Yes",if语句返回false,所以JavaScript loves you back ❤️被打印。
感谢你的补充,查阅了相关资料,
let 的「创建」过程被提升了,但是初始化没有提升。
var 的「创建」和「初始化」都被提升了。
function 的「创建」「初始化」和「赋值」都被提升了。
提升的过程可能不一致,导致了很多人误解let自始至终是不提升的,其实在创建过程是被提升了,只不过在暂时性死区的作用下,初始化是没有被提升的。
JavaScript 进阶必会知识点
从基础到进阶,测试你有多了解 JavaScript,刷新你的知识,或者帮助你的 coding 面试!先思考,然后自己给出答案,最好可以敲一遍代码,掌握的更牢固。
答案在问题下方的折叠部分,点击即可展开问题。祝你好运 ❤️
1. 输出是什么?
Lydia
和undefined
Lydia
和ReferenceError
ReferenceError
和21
undefined
和ReferenceError
答案
答案: D
在函数内部,我们首先通过
var
关键字声明了name
变量。这意味着变量被提升了(内存空间在创建阶段就被设置好了),直到程序运行到定义变量位置之前默认值都是undefined
。因为当我们打印name
变量时还没有执行到定义变量的位置,因此变量的值保持为undefined
。通过
let
和const
关键字声明的变量也会提升,但是和var
不同,它们不会被初始化。在我们声明(初始化)之前是不能访问它们的。这个行为被称之为暂时性死区。当我们试图在声明之前访问它们时,JavaScript 将会抛出一个ReferenceError
错误。2. 输出是什么?
0 1 2
和0 1 2
0 1 2
和3 3 3
3 3 3
和0 1 2
答案
答案: C
由于 JavaScript 的事件循环,
setTimeout
回调会在遍历结束后才执行。因为在第一个遍历中遍历i
是通过var
关键字声明的,所以这个值是全局作用域下的。在遍历过程中,我们通过一元操作符++
来每次递增i
的值。当setTimeout
回调执行的时候,i
的值等于 3。在第二个遍历中,遍历
i
是通过let
关键字声明的:通过let
和const
关键字声明的变量是拥有块级作用域(指的是任何在 {} 中的内容)。在每次的遍历过程中,i
都有一个新值,并且每个值都在循环内的作用域中。3. 输出是什么?
20
and62.83185307179586
20
andNaN
20
and63
NaN
and63
答案
答案: B
注意
diameter
的值是一个常规函数,但是perimeter
的值是一个箭头函数。对于箭头函数,
this
关键字指向的是它当前周围作用域(简单来说是包含箭头函数的常规函数,如果没有常规函数的话就是全局对象),这个行为和常规函数不同。这意味着当我们调用perimeter
时,this
不是指向shape
对象,而是它的周围作用域(在例子中是window
)。在
window
中没有radius
这个属性,因此返回undefined
。4. 输出是什么?
1
andfalse
false
andNaN
false
andfalse
答案
答案: A
一元操作符加号尝试将 bool 转为 number。
true
转换为 number 的话为1
,false
为0
。字符串
'Lydia'
是一个真值,真值取反那么就返回false
。5. 哪一个是无效的?
mouse.bird.size
mouse[bird.size]
mouse[bird["size"]]
答案
答案: A
在 JavaScript 中,所有对象的 keys 都是字符串(除非对象是 Symbol)。尽管我们可能不会定义它们为字符串,但它们在底层总会被转换为字符串。
当我们使用括号语法时([]),JavaScript 会解释(或者 unboxes)语句。它首先看到第一个开始括号
[
并继续前进直到找到结束括号]
。只有这样,它才会计算语句的值。mouse[bird.size]
:首先计算bird.size
,这会得到small
。mouse["small"]
返回true
。然后使用点语法的话,上面这一切都不会发生。
mouse
没有bird
这个 key,这也就意味着mouse.bird
是undefined
。然后当我们使用点语法mouse.bird.size
时,因为mouse.bird
是undefined
,这也就变成了undefined.size
。这个行为是无效的,并且会抛出一个错误类似Cannot read property "size" of undefined
。6. 输出是什么?
Hello
undefined
ReferenceError
TypeError
答案
答案: A
在 JavaScript 中,当设置两个对象彼此相等时,它们会通过引用进行交互。
首先,变量
c
的值是一个对象。接下来,我们给d
分配了一个和c
对象相同的引用。因此当我们改变其中一个对象时,其实是改变了所有的对象。
7. 输出是什么?
true
false
true
false
false
true
true
false
false
false
true
true
答案
答案: C
new Number()
是一个内建的函数构造器。虽然它看着像是一个 number,但它实际上并不是一个真实的 number:它有一堆额外的功能并且它是一个对象。当我们使用
==
操作符时,它只会检查两者是否拥有相同的值。因为它们的值都是3
,因此返回true
。然后,当我们使用
===
操作符时,两者的值以及类型都应该是相同的。new Number()
是一个对象而不是 number,因此返回false
。8. 输出是什么?
orange
purple
green
TypeError
答案
答案: D
colorChange
是一个静态方法。静态方法被设计为只能被创建它们的构造器使用(也就是Chameleon
),并且不能传递给实例。因为freddie
是一个实例,静态方法不能被实例使用,因此抛出了TypeError
错误。9. 输出是什么?
{}
ReferenceError: greetign is not defined
undefined
答案
答案: A
代码打印出了一个对象,这是因为我们在全局对象上创建了一个空对象!当我们将
greeting
写错成greetign
时,JS 解释器实际在上浏览器中将它视为global.greetign = {}
(或者window.greetign = {}
)。为了避免这个为题,我们可以使用 `"use strict"。这能确保当你声明变量时必须赋值。
10. 当我们这么做时,会发生什么?
SyntaxError
. 你不能通过这种方式给函数增加属性。undefined
ReferenceError
答案
答案: A
这在 JavaScript 中是可以的,因为函数是对象!(除了基本类型之外其他都是对象)
函数是一个特殊的对象。你写的这个代码其实不是一个实际的函数。函数是一个拥有属性的对象,并且属性也可被调用。
11. 输出是什么?
TypeError
SyntaxError
Lydia Hallie
undefined
undefined
答案
答案: A
你不能像常规对象那样,给构造函数添加属性。如果你想一次性给所有实例添加特性,你应该使用原型。因此本例中,使用如下方式:
这才会使
member.getFullName()
起作用。为什么这么做有益的?假设我们将这个方法添加到构造函数本身里。也许不是每个Person
实例都需要这个方法。这将浪费大量内存空间,因为它们仍然具有该属性,这将占用每个实例的内存空间。相反,如果我们只将它添加到原型中,那么它只存在于内存中的一个位置,但是所有实例都可以访问它!12. 输出是什么?
Person {firstName: "Lydia", lastName: "Hallie"}
andundefined
Person {firstName: "Lydia", lastName: "Hallie"}
andPerson {firstName: "Sarah", lastName: "Smith"}
Person {firstName: "Lydia", lastName: "Hallie"}
and{}
Person {firstName: "Lydia", lastName: "Hallie"}
andReferenceError
答案
答案: A
对于
sarah
,我们没有使用new
关键字。当使用new
时,this
引用我们创建的空对象。当未使用new
时,this
引用的是全局对象(global object)。我们说
this.firstName
等于"Sarah"
,并且this.lastName
等于"Smith"
。实际上我们做的是,定义了global.firstName = 'Sarah'
和global.lastName = 'Smith'
。而sarah
本身是undefined
。13. 事件传播的三个阶段是什么?
答案
答案: D
在捕获(capturing)阶段中,事件从祖先元素向下传播到目标元素。当事件达到目标(target)元素后,冒泡(bubbling)才开始。
14. 所有对象都有原型。
答案
答案: B
除了基本对象(base object),所有对象都有原型。基本对象可以访问一些方法和属性,比如
.toString
。这就是为什么你可以使用内置的 JavaScript 方法!所有这些方法在原型上都是可用的。虽然 JavaScript 不能直接在对象上找到这些方法,但 JavaScript 会沿着原型链找到它们,以便于你使用。15. 输出是什么?
NaN
TypeError
"12"
3
答案
答案: C
JavaScript 是一种动态类型语言:我们不指定某些变量的类型。值可以在你不知道的情况下自动转换成另一种类型,这种类型称为隐式类型转换(implicit type coercion)。Coercion 是指将一种类型转换为另一种类型。
在本例中,JavaScript 将数字
1
转换为字符串,以便函数有意义并返回一个值。在数字类型(1
)和字符串类型('2'
)相加时,该数字被视为字符串。我们可以连接字符串,比如"Hello" + "World"
,这里发生的是"1" + "2"
,它返回"12"
。16. 输出是什么?
1
1
2
1
2
2
0
2
2
0
1
2
答案
答案: C
一元后自增运算符
++
:0
)1
)一元前自增运算符
++
:2
)2
)结果是
0 2 2
.17. 输出是什么?
"Lydia"
21
["", " is ", " years old"]
["", " is ", " years old"]
"Lydia"
21
"Lydia"
["", " is ", " years old"]
21
答案
答案: B
如果使用标记模板字面量,第一个参数的值总是包含字符串的数组。其余的参数获取的是传递的表达式的值!
18. 输出是什么?
You are an adult!
You are still an adult.
Hmm.. You don't have an age I guess
答案
答案: C
在测试相等性时,基本类型通过它们的值(value)进行比较,而对象通过它们的引用(reference)进行比较。JavaScript 检查对象是否具有对内存中相同位置的引用。
题目中我们正在比较的两个对象不是同一个引用:作为参数传递的对象引用的内存位置,与用于判断相等的对象所引用的内存位置并不同。
这也是
{ age: 18 } === { age: 18 }
和{ age: 18 } == { age: 18 }
都返回false
的原因。19. 输出是什么?
"number"
"array"
"object"
"NaN"
答案
答案: C
扩展运算符(
...args
)会返回实参组成的数组。而数组是对象,因此typeof args
返回"object"
。20. 输出是什么?
21
undefined
ReferenceError
TypeError
答案
答案: C
使用
"use strict"
,你可以确保不会意外地声明全局变量。我们从来没有声明变量age
,因为我们使用"use strict"
,它将抛出一个引用错误。如果我们不使用"use strict"
,它就会工作,因为属性age
会被添加到全局对象中了。21. 输出是什么?
105
"105"
TypeError
"10*10+5"
答案
答案: A
代码以字符串形式传递进来,
eval
对其求值。如果它是一个表达式,就像本例中那样,它对表达式求值。表达式是10 * 10 + 5
。这将返回数字105
。22. cool_secret 可访问多长时间?
答案
答案: B
关闭 tab 标签页 后,
sessionStorage
存储的数据才会删除。如果使用
localStorage
,那么数据将永远在那里,除非调用了localStorage.clear()
。23. 输出是什么?
8
10
SyntaxError
ReferenceError
答案
答案: B
使用
var
关键字,你可以用相同的名称声明多个变量。然后变量将保存最新的值。你不能使用
let
或const
来实现这一点,因为它们是块作用域的。24. 输出是什么?
false
true
false
true
false
true
true
true
true
true
false
true
true
true
true
true
答案
答案: C
所有对象的键(不包括 Symbol)在底层都是字符串,即使你自己没有将其作为字符串输入。这就是为什么
obj.hasOwnProperty('1')
也返回true
。对于集合,它不是这样工作的。在我们的集合中没有
'1'
:set.has('1')
返回false
。它有数字类型为1
,set.has(1)
返回true
。25. 输出是什么?
{ a: "one", b: "two" }
{ b: "two", a: "three" }
{ a: "three", b: "two" }
SyntaxError
答案
答案: C
如果你有两个名称相同的键,则键会被替换掉。它仍然位于第一个键出现的位置,但是值是最后出现那个键的值。
26. JavaScript 全局执行上下文为你做了两件事:全局对象和 this 关键字。
答案
答案: A
基本执行上下文是全局执行上下文:它是代码中随处可访问的内容。
27. 输出是什么?
1
2
1
2
3
1
2
4
1
3
4
答案
答案: C
如果某个条件返回
true
,则continue
语句跳过本次迭代。28. 输出是什么?
"Just give Lydia pizza already!"
TypeError: not a function
SyntaxError
undefined
答案
答案: A
String
是内置的构造函数,我们可以向它添加属性。我只是在它的原型中添加了一个方法。基本类型字符串被自动转换为字符串对象,由字符串原型函数生成。因此,所有 string(string 对象)都可以访问该方法!29. 输出是什么?
123
456
undefined
ReferenceError
答案
答案: B
对象的键被自动转换为字符串。我们试图将一个对象
b
设置为对象a
的键,且相应的值为123
。然而,当字符串化一个对象时,它会变成
"[object Object]"
。因此这里说的是,a["[object Object]"] = 123
。然后,我们再一次做了同样的事情,c
是另外一个对象,这里也有隐式字符串化,于是,a["[object Object]"] = 456
。然后,我们打印
a[b]
,也就是a["[object Object]"]
。之前刚设置为456
,因此返回的是456
。30. 输出是什么?
First
Second
Third
First
Third
Second
Second
First
Third
Second
Third
First
答案
答案: B
我们有一个
setTimeout
函数,并首先调用它。然而,它是最后打印日志的。这是因为在浏览器中,我们不仅有运行时引擎,还有一个叫做
WebAPI
的东西。WebAPI
提供了setTimeout
函数,也包含其他的,例如 DOM。将 callback 推送到 WebAPI 后,
setTimeout
函数本身(但不是回调!)将从栈中弹出。现在,
foo
被调用,打印"First"
。foo
从栈中弹出,baz
被调用. 打印"Third"
。WebAPI 不能随时向栈内添加内容。相反,它将回调函数推到名为 queue 的地方。
这就是事件循环开始工作的地方。一个事件循环查看栈和任务队列。如果栈是空的,它接受队列上的第一个元素并将其推入栈。
bar
被调用,打印"Second"
,然后它被栈弹出。31. 当点击按钮时,event.target是什么?
div
div
button
答案
答案: C
导致事件的最深嵌套的元素是事件的 target。你可以通过
event.stopPropagation
来停止冒泡。32. 当您单击该段落时,日志输出是什么?
p
div
div
p
p
div
答案
答案: A
如果我们点击
p
,我们会看到两个日志:p
和div
。在事件传播期间,有三个阶段:捕获、目标和冒泡。默认情况下,事件处理程序在冒泡阶段执行(除非将useCapture
设置为true
)。它从嵌套最深的元素向外传播。33. 输出是什么?
undefined is 21
Lydia is 21
function
function
Lydia is 21
Lydia is 21
Lydia is 21
function
答案
答案: D
使用这两种方法,我们都可以传递我们希望
this
关键字引用的对象。但是,.call
是立即执行的。.bind
返回函数的副本,但带有绑定上下文!它不是立即执行的。34. 输出是什么?
"object"
"number"
"function"
"undefined"
答案
答案: B
sayHi
方法返回的是立即执行函数(IIFE)的返回值.此立即执行函数的返回值是0
, 类型是number
参考:只有7种内置类型:
null
,undefined
,boolean
,number
,string
,object
和symbol
。function
不是一种类型,函数是对象,它的类型是object
。35. 下面哪些值是 falsy?
0
,''
,undefined
0
,new Number(0)
,''
,new Boolean(false)
,undefined
0
,''
,new Boolean(false)
,undefined
答案
答案: A
只有 6 种 falsy 值:
undefined
null
NaN
0
''
(empty string)false
Function
构造函数, 比如new Number
和new Boolean
,是 truthy。36. 输出是什么?
"number"
"string"
"object"
"undefined"
答案
答案: B
typeof 1
返回"number"
。typeof "number"
返回"string"
。37. 输出是什么?
[1, 2, 3, 7 x null, 11]
[1, 2, 3, 11]
[1, 2, 3, 7 x empty, 11]
SyntaxError
答案
答案: C
当你为数组设置超过数组长度的值的时候, JavaScript 会创建名为 "empty slots" 的东西。它们的值实际上是
undefined
。你会看到以下场景:[1, 2, 3, 7 x empty, 11]
这取决于你的运行环境(每个浏览器,以及 node 环境,都有可能不同)
38. 输出是什么?
1
undefined
2
undefined
undefined
undefined
1
1
2
1
undefined
undefined
答案
答案: A
catch
代码块接收参数x
。当我们传递参数时,这与之前定义的变量x
不同 。这个x
是属于catch
块级作用域的。然后,我们将块级作用域中的变量赋值为
1
,同时也设置了变量y
的值。现在,我们打印块级作用域中的变量x
,值为1
。catch
块之外的变量x
的值仍为undefined
,y
的值为2
。当我们在catch
块之外执行console.log(x)
时,返回undefined
,y
返回2
。39. JavaScript 中的一切都是?
答案
答案: A
JavaScript 只有基本类型和对象。
基本类型包括
boolean
,null
,undefined
,bigint
,number
,string
,symbol
。40. 输出是什么?
[0, 1, 2, 3, 1, 2]
[6, 1, 2]
[1, 2, 0, 1, 2, 3]
[1, 2, 6]
答案
答案: C
[1, 2]
是初始值。初始值将会作为首次调用时第一个参数acc
的值。在第一次执行时,acc
的值是[1, 2]
,cur
的值是[0, 1]
。合并它们,结果为[1, 2, 0, 1]
。第二次执行,
acc
的值是[1, 2, 0, 1]
,cur
的值是[2, 3]
。合并它们,最终结果为[1, 2, 0, 1, 2, 3]
41. 输出是什么?
false
true
false
false
false
true
false
true
true
true
true
false
答案
答案: B
null
是 falsy。!null
的值是true
。!true
的值是false
。""
是 falsy。!""
的值是true
。!true
的值是false
。1
是 truthy。!1
的值是false
。!false
的值是true
。42.
setInterval
方法的返回值是什么?undefined
答案
答案: A
setInterval
返回一个唯一的 id。此 id 可被用于clearInterval
函数来取消定时。43. 输出是什么?
["L", "y", "d", "i", "a"]
["Lydia"]
[[], "Lydia"]
[["L", "y", "d", "i", "a"]]
答案
答案: A
string 类型是可迭代的。扩展运算符将迭代的每个字符映射成一个元素。
44. 输出是什么?
[0, 10], [10, 20]
20, 20
10, 20
0, 10 and 10, 20
答案
答案: C
一般的函数在执行之后是不能中途停下的。但是,生成器函数却可以中途“停下”,之后可以再从停下的地方继续。当生成器遇到
yield
关键字的时候,会生成yield
后面的值。注意,生成器在这种情况下不 返回 (return )值,而是 生成 (yield)值。首先,我们用
10
作为参数i
来初始化生成器函数。然后使用next()
方法一步步执行生成器。第一次执行生成器的时候,i
的值为10
,遇到第一个yield
关键字,它要生成i
的值。此时,生成器“暂停”,生成了10
。然后,我们再执行
next()
方法。生成器会从刚才暂停的地方继续,这个时候i
还是10
。于是我们走到了第二个yield
关键字处,这时候需要生成的值是i*2
,i
为10
,那么此时生成的值便是20
。所以这道题的最终结果是10,20
。45. 返回值是什么?
"one"
"two"
"two" "one"
"one" "two"
答案
答案: B
当我们向
Promise.race
方法中传入多个Promise
时,会进行 优先 解析。在这个例子中,我们用setTimeout
给firstPromise
和secondPromise
分别设定了500ms和100ms的定时器。这意味着secondPromise
会首先解析出字符串two
。那么此时res
参数即为two
,是为输出结果。46. 输出是什么?
null
[null]
[{}]
[{ name: "Lydia" }]
答案
答案: D
首先我们声明了一个拥有
name
属性的对象person
。然后我们又声明了一个变量
members
. 将首个元素赋值为变量person
。 当设置两个对象彼此相等时,它们会通过 引用 进行交互。但是当你将引用从一个变量分配至另一个变量时,其实只是执行了一个 复制 操作。(注意一点,他们的引用 并不相同!)接下来我们让
person
等于null
。我们没有修改数组第一个元素的值,而只是修改了变量
person
的值,因为元素(复制而来)的引用与person
不同。members
的第一个元素仍然保持着对原始对象的引用。当我们输出members
数组时,第一个元素会将引用的对象打印出来。47. 输出是什么?
{ name: "Lydia" }, { age: 21 }
"name", "age"
"Lydia", 21
["name", "Lydia"], ["age", 21]
答案
答案: B
在
for-in
循环中,我们可以通过对象的key来进行迭代,也就是这里的name
和age
。在底层,对象的key都是字符串(如果他们不是Symbol的话)。在每次循环中,我们将item
设定为当前遍历到的key.所以一开始,item
是name
,之后item
输出的则是age
。48. 输出是什么?
"345"
"75"
12
"12"
答案
答案: B
当所有运算符的 优先级 相同时,计算表达式需要确定运算符的结合顺序,即从右到左还是从左往右。在这个例子中,我们只有一类运算符
+
,对于加法来说,结合顺序就死从左到右。3 + 4
首先计算,得到数字7
.由于类型的强制转换,
7 + '5'
的结果是"75"
. JavaScript将7
转换成了字符串,可以参考问题15.我们可以用+
号把两个字符串连接起来。"7" + "5"
就得到了"75"
.49.
num
的值是什么?42
"42"
7
NaN
答案
答案: C
只返回了字符串中第一个字母. 设定了 进制 后 (也就是第二个参数,指定需要解析的数字是什么进制: 十进制、十六机制、八进制、二进制等等……),
parseInt
检查字符串中的字符是否合法. 一旦遇到一个在指定进制中不合法的字符后,立即停止解析并且忽略后面所有的字符。*
就是不合法的数字字符。所以只解析到"7"
,并将其解析为十进制的7
.num
的值即为7
.50. 输出是什么?
[]
[null, null, null]
[undefined, undefined, undefined]
[ 3 x empty ]
答案
答案: C
对数组进行映射的时候,
num
就是当前循环到的元素. 在这个例子中,所有的映射都是number类型,所以if中的判断typeof num === "number"
结果都是true
.map函数创建了新数组并且将函数的返回值插入数组。但是,没有任何值返回。当函数没有返回任何值时,即默认返回
undefined
.对数组中的每一个元素来说,函数块都得到了这个返回值,所以结果中每一个元素都是undefined
.51. 输出的是什么?
{ name: "Lydia" }, "1997"
{ name: "Sarah" }, "1998"
{ name: "Lydia" }, "1998"
{ name: "Sarah" }, "1997"
答案
答案: A
普通参数都是 值 传递的,而对象则不同,是 引用 传递。所以说,
birthYear
是值传递,因为他是个字符串而不是对象。当我们对参数进行值传递时,会创建一份该值的 复制 。(可以参考问题46)变量
birthYear
有一个对"1997"
的引用,而传入的参数也有一个对"1997"
的引用,但二者的引用并不相同。当我们通过给year
赋值"1998"
来更新year
的值的时候我们只是更新了year
(的引用)。此时birthYear
仍然是"1997"
.而
person
是个对象。参数member
引用与之 相同的 对象。当我们修改member
所引用对象的属性时,person
的相应属性也被修改了,因为他们引用了相同的对象.person
的name
属性也变成了"Lydia"
.52. 输出是什么?
"It worked! Hello world!"
"Oh no an error: undefined
SyntaxError: can only throw Error objects
"Oh no an error: Hello world!
答案
答案: D
通过
throw
语句,我么可以创建自定义错误。 而通过它,我们可以抛出异常。异常可以是一个字符串, 一个 数字, 一个 布尔类型 或者是一个 对象。在本例中,我们的异常是字符串'Hello world'
.通过
catch
语句,我们可以设定当try
语句块中抛出异常后应该做什么处理。在本例中抛出的异常是字符串'Hello world'
.e
就是这个字符串,因此被输出。最终结果就是'Oh an error: Hello world'
.53. 输出是什么?
"Lamborghini"
"Maserati"
ReferenceError
TypeError
答案
答案: B
返回属性的时候,属性的值等于 返回的 值,而不是构造函数中设定的值。我们返回了字符串
"Maserati"
,所以myCar.make
等于"Maserati"
.54. 输出是什么?
"undefined", "number"
"number", "number"
"object", "number"
"number", "undefined"
答案
答案: A
let x = y = 10;
是下面这个表达式的缩写:我们设定
y
等于10
时,我们实际上增加了一个属性y
给全局对象(浏览器里的window
, Nodejs里的global
)。在浏览器中,window.y
等于10
.然后我们声明了变量
x
等于y
,也是10
.但变量是使用let
声明的,它只作用于 块级作用域, 仅在声明它的块中有效;就是案例中的立即调用表达式(IIFE)。使用typeof
操作符时, 操作值x
没有被定义:因为我们在x
声明块的外部,无法调用它。这就意味着x
未定义。未分配或是未声明的变量类型为"undefined"
.console.log(typeof x)
返回"undefined"
.而我们创建了全局变量
y
,并且设定y
等于10
.这个值在我们的代码各处都访问的到。y
已经被定义了,而且有一个"number"
类型的值。console.log(typeof y)
返回"number"
.55. 输出是什么?
"Woof I am Mara"
,TypeError
"Woof I am Mara"
,"Woof I am Mara"
"Woof I am Mara"
,undefined
TypeError
,TypeError
答案
答案: A
我们可以用
delete
关键字删除对象的属性,对原型也是适用的。删除了原型的属性后,该属性在原型链上就不可用了。在本例中,函数bark
在执行了delete Dog.prototype.bark
后不可用, 然而后面的代码还在调用它。当我们尝试调用一个不存在的函数时
TypeError
异常会被抛出。在本例中就是TypeError: pet.bark is not a function
,因为pet.bark
是undefined
.56. 输出是什么?
[1, 1, 2, 3, 4]
[1, 2, 3, 4]
{1, 1, 2, 3, 4}
{1, 2, 3, 4}
答案
答案: D
Set
对象手机 独一无二 的值:也就是说同一个值在其中仅出现一次。我们传入了数组
[1, 1, 2, 3, 4]
,他有一个重复值1
.以为一个集合里不能有两个重复的值,其中一个就被移除了。所以结果是{1, 2, 3, 4}
.57. 输出是什么?
10
11
Error
NaN
答案
答案: C
引入的模块是 只读 的: 你不能修改引入的模块。只有导出他们的模块才能修改其值。
当我们给
myCounter
增加一个值的时候会抛出一个异常:myCounter
是只读的,不能被修改。58. 输出是什么?
false
,true
"Lydia"
,21
true
,true
undefined
,undefined
答案
答案: A
delete
操作符返回一个布尔值:true
指删除成功,否则返回false
. 但是通过var
,const
或let
关键字声明的变量无法用delete
操作符来删除。name
变量由const
关键字声明,所以删除不成功:返回false
. 而我们设定age
等于21
时,我们实际上添加了一个名为age
的属性给全局对象。对象中的属性是可以删除的,全局对象也是如此,所以delete age
返回true
.59. 输出是什么?
[[1, 2, 3, 4, 5]]
[1, 2, 3, 4, 5]
1
[1]
答案
答案: C
我们可以通过解构赋值来解析来自对象的数组或属性的值,比如说:
a
的值现在是1
,b
的值现在是2
.而在题目中,我们是这么做的:也就是说,
y
等于数组的第一个值就是数字1
.我们输出y
, 返回1
.60. 输出是什么?
{ admin: true, user: { name: "Lydia", age: 21 } }
{ admin: true, name: "Lydia", age: 21 }
{ admin: true, user: ["Lydia", 21] }
{ admin: true }
答案
答案: B
扩展运算符
...
为对象的组合提供了可能。你可以复制对象中的键值对,然后把它们加到另一个对象里去。在本例中,我们复制了user
对象键值对,然后把它们加入到admin
对象中。admin
对象就拥有了这些键值对,所以结果为{ admin: true, name: "Lydia", age: 21 }
.61. 输出是什么?
{ name: "Lydia", age: 21 }
,["name", "age"]
{ name: "Lydia", age: 21 }
,["name"]
{ name: "Lydia"}
,["name", "age"]
{ name: "Lydia"}
,["age"]
答案
答案: B
通过
defineProperty
方法,我们可以给对象添加一个新属性,或者修改已经存在的属性。而我们使用defineProperty
方法给对象添加了一个属性之后,属性默认为 不可枚举(not enumerable).Object.keys
方法仅返回对象中 可枚举(enumerable) 的属性,因此只剩下了"name"
.用
defineProperty
方法添加的属性默认不可变。你可以通过writable
,configurable
和enumerable
属性来改变这一行为。这样的话, 相比于自己添加的属性,defineProperty
方法添加的属性有了更多的控制权。62. 输出是什么?
"{"level":19, "health":90}"
"{"username": "lydiahallie"}"
"["level", "health"]"
"{"username": "lydiahallie", "level":19, "health":90}"
答案
答案: A
JSON.stringify
的第二个参数是 替代者(replacer). 替代者(replacer)可以是个函数或数组,用以控制哪些值如何被转换为字符串。如果替代者(replacer)是个 数组 ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为
"level"
和"health"
的属性被包括进来,"username"
则被排除在外。data
就等于"{"level":19, "health":90}"
.而如果替代者(replacer)是个 函数,这个函数将被对象的每个属性都调用一遍。
函数返回的值会成为这个属性的值,最终体现在转化后的JSON字符串中(译者注:Chrome下,经过实验,如果所有属性均返回同一个值的时候有异常,会直接将返回值作为结果输出而不会输出JSON字符串),而如果返回值为
undefined
,则该属性会被排除在外。63. 输出是什么?
10
,10
10
,11
11
,11
11
,12
答案
答案: A
一元操作符
++
先返回 操作值, 再累加 操作值。num1
的值是10
, 因为increaseNumber
函数首先返回num
的值,也就是10
,随后再进行num
的累加。num2
是10
因为我们将num1
传入increasePassedNumber
.number
等于10
(num1
的值。同样道理,++
先返回 操作值, 再累加 操作值。)number
是10
,所以num2
也是10
.64. 输出什么?
20
,40
,80
,160
20
,40
,20
,40
20
,20
,20
,40
NaN
,NaN
,20
,40
答案
答案: C
在ES6中,我们可以使用默认值初始化参数。如果没有给函数传参,或者传的参值为
"undefined"
,那么参数的值将是默认值。上述例子中,我们将value
对象进行了解构并传到一个新对象中,因此x
的默认值为{number:10}
。默认参数在调用时才会进行计算,每次调用函数时,都会创建一个新的对象。我们前两次调用
multiply
函数且不传递值,那么每一次x
的默认值都为{number:10}
,因此打印出该数字的乘积值为20
。第三次调用
multiply
时,我们传递了一个参数,即对象value
。*=
运算符实际上是x.number = x.number * 2
的简写,我们修改了x.number
的值,并打印出值20
。第四次,我们再次传递
value
对象。x.number
之前被修改为20
,所以x.number * = 2
打印为40
。65. 输出什么?
1
2
and3
3
and6
4
1
2
and2
3
and3
4
1
undefined
and2
undefined
and3
undefined
and4
undefined
1
2
andundefined
3
andundefined
4
答案
答案: D
reducer
函数接收4个参数:reducer
函数的返回值将会分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。reducer
函数还有一个可选参数initialValue
, 该参数将作为第一次调用回调函数时的第一个参数的值。如果没有提供initialValue
,则将使用数组中的第一个元素。在上述例子,
reduce
方法接收的第一个参数(Accumulator)是x
, 第二个参数(Current Value)是y
。在第一次调用时,累加器
x
为1
,当前值“y”
为2
,打印出累加器和当前值:1
和2
。例子中我们的回调函数没有返回任何值,只是打印累加器的值和当前值。如果函数没有返回值,则默认返回
undefined
。 在下一次调用时,累加器为undefined
,当前值为“3”, 因此undefined
和3
被打印出。在第四次调用时,回调函数依然没有返回值。 累加器再次为
undefined
,当前值为“4”。undefined
和4
被打印出。66. 使用哪个构造函数可以成功继承
Dog
类?答案
答案: B
在子类中,在调用
super
之前不能访问到this
关键字。 如果这样做,它将抛出一个ReferenceError
:1和4将引发一个引用错误。使用
super
关键字,需要用给定的参数来调用父类的构造函数。 父类的构造函数接收name
参数,因此我们需要将name
传递给super
。Labrador
类接收两个参数,name
参数是由于它继承了Dog
,size
作为Labrador
类的额外属性,它们都需要传递给Labrador
的构造函数,因此使用构造函数2正确完成。67. 输出什么?
running index.js
,running sum.js
,3
running sum.js
,running index.js
,3
running sum.js
,3
,running index.js
running index.js
,undefined
,running sum.js
答案
答案: B
import
命令是编译阶段执行的,在代码运行之前。因此这意味着被导入的模块会先运行,而导入模块的文件会后执行。这是CommonJS中
require()
和import
之间的区别。使用require()
,您可以在运行代码时根据需要加载依赖项。 如果我们使用require
而不是import
,running index.js
,running sum.js
,3
会被依次打印。68. 输出什么?
true
,true
,false
false
,true
,false
true
,false
,true
true
,true
,true
答案
答案: A
每个
Symbol
都是完全唯一的。传递给Symbol
的参数只是给Symbol
的一个描述。Symbol
的值不依赖于传递的参数。 当我们测试相等时,我们创建了两个全新的符号:第一个Symbol('foo')
,第二个Symbol('foo')
, 这两个值是唯一的,彼此不相等,因此返回false
。69. 输出什么?
"Lydia Hallie"
,"Lydia Hallie"
" Lydia Hallie"
," Lydia Hallie"
("[13x whitespace]Lydia Hallie"
,"[2x whitespace]Lydia Hallie"
)" Lydia Hallie"
,"Lydia Hallie"
("[1x whitespace]Lydia Hallie"
,"Lydia Hallie"
)"Lydia Hallie"
,"Lyd"
答案
答案: C
使用
padStart
方法,我们可以在字符串的开头添加填充。传递给此方法的参数是字符串的总长度(包含填充)。字符串Lydia Hallie
的长度为12
, 因此name.padStart(13)
在字符串的开头只会插入1(13 - 12 = 1
)个空格。如果传递给
padStart
方法的参数小于字符串的长度,则不会添加填充。70. 输出什么?
"🥑💻"
257548
答案
答案: A
使用
+
运算符,您可以连接字符串。 上述情况,我们将字符串“🥑”
与字符串”💻“
连接起来,产生”🥑💻“
。71. 如何能打印出
console.log
语句后注释掉的值?game.next("Yes").value
andgame.next().value
game.next.value("Yes")
andgame.next.value()
game.next().value
andgame.next("Yes").value
game.next.value()
andgame.next.value("Yes")
答案
答案: C
generator
函数在遇到yield
关键字时会“暂停”其执行。 首先,我们需要让函数产生字符串Do you love JavaScript?
,这可以通过调用game.next().value
来完成。上述函数的第一行就有一个yield
关键字,那么运行立即停止了,yield
表达式本身没有返回值,或者说总是返回undefined
, 这意味着此时变量answer
为undefined
next
方法可以带一个参数,该参数会被当作上一个yield
表达式的返回值。当我们调用game.next("Yes").value
时,先前的yield
的返回值将被替换为传递给next()
函数的参数"Yes"
。此时变量answer
被赋值为"Yes"
,if
语句返回false
,所以JavaScript loves you back ❤️
被打印。72. 输出什么?
Hello world!
Hello
world
Hello\nworld
Hello\n
world
答案
答案: C
String.raw
函数是用来获取一个模板字符串的原始字符串的,它返回一个字符串,其中忽略了转义符(\n
,\v
,\t
等)。但反斜杠可能造成问题,因为你可能会遇到下面这种类似情况:这将导致:
"C:DocumentsProjects able.html"
直接使用
String.raw
它会忽略转义字符并打印:
C:\Documents\Projects\table.html
上述情况,字符串是
Hello\nworld
被打印出。73. 输出什么?
"I made it!"
Promise {<resolved>: "I made it!"}
Promise {<pending>}
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. 输出什么?
['apple', 'banana']
2
true
undefined
答案
答案: B
push()
方法返回新数组的长度。一开始,数组包含一个元素(字符串"banana"
),长度为1。 在数组中添加字符串"apple"
后,长度变为2,并将从addToList
函数返回。push
方法修改原始数组,如果你想从函数返回数组而不是数组长度,那么应该在pushitem
之后返回list
。75. 输出什么?
{ x: 100, y: 20 }
{ x: 10, y: 20 }
{ x: 100 }
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. 输出什么?
"Lydia"
"myName"
undefined
ReferenceError
答案
答案: D
当我们从右侧的对象解构属性
name
时,我们将其值Lydia
分配给名为myName
的变量。使用
{name:myName}
,我们是在告诉JavaScript我们要创建一个名为myName
的新变量,并且其值是右侧对象的name
属性的值。当我们尝试打印
name
,一个未定义的变量时,就会引发ReferenceError
。77. 以下是个纯函数么?
答案
答案: A
纯函数一种若输入参数相同,则永远会得到相同输出的函数。
sum
函数总是返回相同的结果。 如果我们传递1
和2
,它将总是返回3
而没有副作用。 如果我们传递5
和10
,它将总是返回15
,依此类推,这是纯函数的定义。78. 输出什么?
Calculated! 20
Calculated! 20
Calculated! 20
Calculated! 20
From cache! 20
Calculated! 20
Calculated! 20
From cache! 20
From cache! 20
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
被打印。The text was updated successfully, but these errors were encountered: