@@ -4714,3 +4714,375 @@ const person = {
4714
4714
4715
4715
</p>
4716
4716
</details>
4717
+
4718
+ ---
4719
+
4720
+ ###### 145. 输出什么?
4721
+ ```javascript
4722
+ let count = 0;
4723
+ const nums = [0, 1, 2, 3];
4724
+
4725
+ nums.forEach(num => {
4726
+ if (num) count += 1
4727
+ })
4728
+
4729
+ console.log(count)
4730
+ ```
4731
+
4732
+ - A: 1
4733
+ - B: 2
4734
+ - C: 3
4735
+ - D: 4
4736
+ <details><summary><b>答案</b></summary>
4737
+ <p>
4738
+
4739
+ #### 答案: C
4740
+
4741
+ 在 `forEach` 循环内部的 `if` 会判断 `num` 的值是truthy或者是falsy。因为 `nums` 数组的第一个数字是 `0`,一个falsy值, `if` 语句代码块不会被执行。`count` 仅仅在 `nums` 数组的其他3个数字 `1`,`2`,`3` 时加1。因为 `count` 执行了3次加 `1` 运算,所以 `count` 的值为 `3`。
4742
+
4743
+ </p>
4744
+ </details>
4745
+
4746
+ ---
4747
+
4748
+ ###### 146. 输出是什么?
4749
+
4750
+ ```javascript
4751
+ function getFruit(fruits) {
4752
+ console.log(fruits?.[1]?.[1])
4753
+ }
4754
+
4755
+ getFruit([[' 🍊' , ' 🍌' ], [' 🍍' ]])
4756
+ getFruit()
4757
+ getFruit([[' 🍍' ], [' 🍊' , ' 🍌' ]])
4758
+ ```
4759
+
4760
+ - A: `null`, `undefined`, 🍌
4761
+ - B: `[]`, `null`, 🍌
4762
+ - C: `[]`, `[]`, 🍌
4763
+ - D: `undefined`, `undefined`, 🍌
4764
+
4765
+ <details><summary><b>答案</b></summary>
4766
+ <p>
4767
+
4768
+ #### 答案: D
4769
+
4770
+ `?` 允许我们去选择性地访问对象内部更深层的嵌套属性。 我们尝试打印 `fruits` 数组索引值为 `1` 的子数组内部的索引值为 `1` 的元素。 如果在 `fruits` 数组索引值 为 `1` 的位置不存在元素,会直接返回 `undefined`。 如果 `fruits` 数组在索引值为 `1` 的位置存在元素,但是子数组在索引值为 `1` 的位置不存在元素,也会返回 `undefined`。
4771
+
4772
+ 首先,我们尝试打印 `[[' 🍊' , ' 🍌' ], [' 🍍' ]]` 的子数组 `[' 🍍' ]` 的第2个元素。这个子数组只包含一个元素,也就意味着在索引值为 `1` 的位置不存在元素,所以返回的是 `undefined` 。
4773
+
4774
+ 其次,我们在没有传入任何参数调用了 `getFruits` 函数,也就意味着形参 `fruits` 的默认值为`undefined`。因为我们选择性地链接了 `fruits` 在索引值为 `1` 的元素,因为在索引值为 `1` 的位置不存在元素,因此返回的是 `undefined` 。
4775
+
4776
+ 最后,我们尝试打印 `[' 🍍' ], [' 🍊' , ' 🍌' ]` 的子数组 `[' 🍊' , ' 🍌' ]` 的第2个元素。子数组索引值为 `1`的位置为 `🍌` ,因此它被打印出了。
4777
+
4778
+ </p>
4779
+ </details>
4780
+
4781
+ ---
4782
+
4783
+ ###### 147. 输出什么?
4784
+
4785
+ ```javascript
4786
+ class Calc {
4787
+ constructor() {
4788
+ this.count = 0
4789
+ }
4790
+
4791
+ increase() {
4792
+ this.count ++
4793
+ }
4794
+ }
4795
+
4796
+ const calc = new Calc()
4797
+ new Calc().increase()
4798
+
4799
+ console.log(calc.count)
4800
+ ```
4801
+
4802
+ - A: `0`
4803
+ - B: `1`
4804
+ - C: `undefined`
4805
+ - D: `ReferenceError`
4806
+
4807
+ <details><summary><b>答案</b></summary>
4808
+ <p>
4809
+
4810
+ #### 答案: A
4811
+
4812
+ 我们设置 `calc` 变量为 `Calc` 类的一个新实例。 然后,我们初始化一个 `Calc` 的新实例,而且调用了这个实例的 `increase` 方法。因为count属性是在 `Calc` class的constructor内部的,所以count属性不会在 `Calc` 的原型链上共享出去。这就意味着calc实例的count值不会被更新,count仍然是 `0`。
4813
+
4814
+ </p>
4815
+ </details>
4816
+
4817
+ ---
4818
+
4819
+ ###### 148. 输出什么?
4820
+
4821
+ ```javascript
4822
+ const user = {
4823
+
4824
+ password: "12345"
4825
+ }
4826
+
4827
+ const updateUser = ({ email, password }) => {
4828
+ if (email) {
4829
+ Object.assign(user, { email })
4830
+ }
4831
+
4832
+ if (password) {
4833
+ user.password = password
4834
+ }
4835
+
4836
+ return user
4837
+ }
4838
+
4839
+ const updatedUser = updateUser({ email: "[email protected] " })
4840
+
4841
+ console.log(updatedUser === user)
4842
+ ```
4843
+
4844
+ - A: `false`
4845
+ - B: `true`
4846
+ - C: `TypeError`
4847
+ - D: `ReferenceError`
4848
+
4849
+ <details><summary><b>答案</b></summary>
4850
+ <p>
4851
+
4852
+ #### 答案: B
4853
+
4854
+ `updateUser` 函数更新user的 `email` 和 `password` 属性的值, 如果它们的值传入函数, 函数返回的就是 `user` 对象。 `updateUser` 函数的返回值是 `user` 对象,意味着updatedUser的值与 `user` 指向的是同一个 `user` 对象。`updatedUser === user` 为 `true`.
4855
+
4856
+ </p>
4857
+ </details>
4858
+
4859
+ ---
4860
+
4861
+ ###### 149. 输出什么?
4862
+
4863
+ ```javascript
4864
+ const fruit = [' 🍌' , ' 🍊' , ' 🍎' ]
4865
+
4866
+ fruit.slice(0, 1)
4867
+ fruit.splice(0, 1)
4868
+ fruit.unshift(' 🍇' )
4869
+
4870
+ console.log(fruit)
4871
+ ```
4872
+
4873
+ - A: `[' 🍌' , ' 🍊' , ' 🍎' ]`
4874
+ - B: `[' 🍊' , ' 🍎' ]`
4875
+ - C: `[' 🍇' , ' 🍊' , ' 🍎' ]`
4876
+ - D: `[' 🍇' , ' 🍌' , ' 🍊' , ' 🍎' ]`
4877
+
4878
+ <details><summary><b>答案</b></summary>
4879
+ <p>
4880
+
4881
+ #### 答案: C
4882
+
4883
+ 首先,我们在fruit数组上调用 `slice` 方法。 slice方法不会修改原始数组,但是会返回从数组切片下来的值:香蕉emoji。
4884
+ 其次,我们在fruit数组上调用 `splice` 方法。 splice方法会修改原始数组,也就意味着fruit数组此时为 `[' 🍊' , ' 🍎' ]`。
4885
+ 最后,我们在fruit数组上调用 `unshift` 方法,通过添加一个值的方式改变了原始数组,添加的是' 🍇' ,它成为了数组的第一个元素。现在fruit数组的组成为 `[' 🍇' , ' 🍊' , ' 🍎' ]`。
4886
+
4887
+ </p>
4888
+ </details>
4889
+
4890
+ ---
4891
+
4892
+ ###### 150. 输出什么?
4893
+
4894
+ ```javascript
4895
+ const animals = {};
4896
+ let dog = { emoji: ' 🐶' }
4897
+ let cat = { emoji: ' 🐈' }
4898
+
4899
+ animals[dog] = { ...dog, name: "Mara" }
4900
+ animals[cat] = { ...cat, name: "Sara" }
4901
+
4902
+ console.log(animals[dog])
4903
+ ```
4904
+
4905
+ - A: `{ emoji: "🐶", name: "Mara" }`
4906
+ - B: `{ emoji: "🐈", name: "Sara" }`
4907
+ - C: `undefined`
4908
+ - D: `ReferenceError`
4909
+
4910
+ <details><summary><b>答案</b></summary>
4911
+ <p>
4912
+
4913
+ #### 答案: B
4914
+
4915
+ 对象的键会被转换为字符串。
4916
+
4917
+ 因为 `dog` 的值是一个对象, `animals[dog]` 实际上意味着我们创建了一个叫做 `"object Object"` 的属性来代表新的对象。 `animals["object Object"]` 现在等于 `{ emoji: "🐶", name: "Mara"}`。
4918
+
4919
+ `cat` 也是一个对象,`animals[cat]` 实际上意味着我们在用新的cat的属性覆盖 `animals[``"``object Object``"``]` 的值。
4920
+
4921
+ 打印 `animals[dog]`,实际上是`animals["object Object"]`,这是因为转化`dog`对象为一个字符串结果 `"object Object"` ,所以返回 `{ emoji: "🐈", name: "Sara" }`。
4922
+
4923
+ </p>
4924
+ </details>
4925
+
4926
+ ---
4927
+
4928
+ ###### 151. 输出什么?
4929
+
4930
+ ```javascript
4931
+ const user = {
4932
+
4933
+ updateEmail: email => {
4934
+ this.email = email
4935
+ }
4936
+ }
4937
+
4938
+ user.updateEmail("[email protected] ")
4939
+ console.log(user.email)
4940
+ ```
4941
+
4942
+
4943
+
4944
+ - C: `undefined`
4945
+ - D: `ReferenceError`
4946
+
4947
+ <details><summary><b>答案</b></summary>
4948
+ <p>
4949
+
4950
+ #### 答案: A
4951
+
4952
+ `updateEmail` 函数是一个箭头函数,它没有和 `user` 对象绑定。这就意味着 `this` 关键字不会引用到 `user` 对象,但是会引用到全局对象。 `user` 对象内部的 `email` 的值不会更新。当打印 `user.email` 的时候, 原始值 `[email protected] ` 被返回。
4953
+
4954
+ </p>
4955
+ </details>
4956
+
4957
+ ---
4958
+
4959
+ ###### 152. 输出什么?
4960
+
4961
+ ```javascript
4962
+ const promise1 = Promise.resolve(' First' )
4963
+ const promise2 = Promise.resolve(' Second' )
4964
+ const promise3 = Promise.reject(' Third' )
4965
+ const promise4 = Promise.resolve(' Fourth' )
4966
+
4967
+ const runPromises = async () => {
4968
+ const res1 = await Promise.all([promise1, promise2])
4969
+ const res2 = await Promise.all([promise3, promise4])
4970
+ return [res1, res2]
4971
+ }
4972
+
4973
+ runPromises()
4974
+ .then(res => console.log(res))
4975
+ .catch(err => console.log(err))
4976
+ ```
4977
+
4978
+ - A: `[[' First' , ' Second' ], [' Fourth' ]]`
4979
+ - B: `[[' First' , ' Second' ], [' Third' , ' Fourth' ]]`
4980
+ - C: `[[' First' , ' Second' ]]`
4981
+ - D: `' Third' `
4982
+
4983
+ <details><summary><b>答案</b></summary>
4984
+ <p>
4985
+
4986
+ #### 答案: D
4987
+
4988
+ `Promise.all` 方法可以并行式运行promise。如果其中一个promise失败了,`Promise.all` 方法会带上被reject的promise的值_rejects_。在这个例子中, `promise3` 带着 `"Third"` 值reject。我们在调用 `runPromises` 时在 `runPromises` 函数内部的 `catch` 方法去捕获任意error从而捕获到被reject的值。因为 `promise3` 带着 `"Third"` 被reject,所以只有 `"Third"` 打印。
4989
+
4990
+ </p>
4991
+ </details>
4992
+
4993
+ ---
4994
+
4995
+ ###### 153. 哪个作为`method`的值可以打印`{ name: "Lydia", age: 22 }`?
4996
+
4997
+ ```javascript
4998
+ const keys = ["name", "age"]
4999
+ const values = ["Lydia", 22]
5000
+
5001
+ const method = /* ?? */
5002
+ Object[method](keys.map((_, i) => {
5003
+ return [keys[i], values[i]]
5004
+ })) // { name: "Lydia", age: 22 }
5005
+ ```
5006
+
5007
+ - A: `entries`
5008
+ - B: `values`
5009
+ - C: `fromEntries`
5010
+ - D: `forEach`
5011
+
5012
+ <details><summary><b>答案</b></summary>
5013
+ <p>
5014
+
5015
+ #### 答案: C
5016
+
5017
+ `fromEntries` 方法可以将二维数组转换为对象。在每个子数组的第一个元素是key,在每个子数组的第二个元素是value。在这个例子中,我们映射了 `keys` 数组,它返回了一个数组,数组的第一个元素为keys数组当前索引的值,第二个元素为values数组当前索引的值。
5018
+
5019
+ 这样就创建了一个包含正确keys和values的子数组的数组,因此结果为`{ name: "Lydia", age: 22 }`。
5020
+
5021
+ </p>
5022
+ </details>
5023
+
5024
+ ---
5025
+
5026
+ ###### 154. 输出什么?
5027
+
5028
+ ```javascript
5029
+ const createMember = ({ email, address = {}}) => {
5030
+ const validEmail = /.+\@ .+\. .+/.test(email)
5031
+ if (!validEmail) throw new Error("Valid email pls")
5032
+
5033
+ return {
5034
+ email,
5035
+ address: address ? address : null
5036
+ }
5037
+ }
5038
+
5039
+ const member = createMember({ email: "[email protected] " })
5040
+ console.log(member)
5041
+ ```
5042
+
5043
+ - A: `{ email: "[email protected] ", address: null }`
5044
+ - B: `{ email: "[email protected] " }`
5045
+ - C: `{ email: "[email protected] ", address: {} }`
5046
+ - D: `{ email: "[email protected] ", address: undefined }`
5047
+
5048
+ <details><summary><b>答案</b></summary>
5049
+ <p>
5050
+
5051
+ #### 答案: C
5052
+
5053
+ `address` 的默认值是一个空对象 `{}`。当我们设置 `member` 变量为 `createMember` 函数返回的对象,我们没有为address参数传值,意味着address的值为默认的空对象 `{}`。一个空对象是一个truthy值,意味着 `address ? address : null` 条件会返回 `true`。address的值为空对象 `{}`。
5054
+
5055
+ </p>
5056
+ </details>
5057
+
5058
+ ---
5059
+
5060
+ ###### 155. 输出什么?
5061
+
5062
+ ```javascript
5063
+ let randomValue = { name: "Lydia" }
5064
+ randomValue = 23
5065
+
5066
+ if (!typeof randomValue === "string") {
5067
+ console.log("It' s not a string! " )
5068
+ } else {
5069
+ console.log(" Yay it' s a string!")
5070
+ }
5071
+ ```
5072
+
5073
+ - A: `It' s not a string! `
5074
+ - B: ` Yay it' s a string!`
5075
+ - C: `TypeError`
5076
+ - D: `undefined`
5077
+
5078
+ <details><summary><b>答案</b></summary>
5079
+ <p>
5080
+
5081
+ #### 答案: B
5082
+
5083
+ `if` 语句的条件判断 `!typeof randomValue` 的值是否等于 `"string"`。 `!` 操作符将这个值转化为一个布尔值。如果值是truthy的话,返回值会是 `false`,如果值是falsy,返回值会是 `true`。在这里, `typeof randomValue` 的返回值是一个truthy值 `"number"`,意味着 `!typeof randomValue` 的值是一个布尔值 `false`。
5084
+
5085
+ `!typeof randomValue === "string"` 总是返回false,因为我们实际上是在执行 `false === "string"`。因为条件返回的是 `false`,所以 `else` 语句中的代码块会被运行,因此打印 `Yay it' s a string! ` 。
5086
+
5087
+ </p>
5088
+ </details>
0 commit comments