5个JavaScript问题和答案来测试你的技能

102 阅读5分钟

测试你的技能的5个JavaScript问题和答案

今天我们将继续学习我们心爱的JavaScript语言,在这一版中,我们将通过回答一些JavaScript小挑战来测试我们的技能。

尽管我会在每个问题的结尾处给出答案和解释,但还是要先试着自己弄清楚,然后用我的答案来验证你的答案。

问题#1:数组排序比较

考虑以下数组和条件,你认为结果会是什么?

const arr1 = ['a', 'b', 'c']
const arr2 = ['c', 'b', 'a']

console.log(
    arr1.sort() === arr1,
    arr2 === arr2.sort(),
    arr1.sort() === arr2.sort()
)

答案

true true false

现在我们知道了结果,让我们解释一下原因。对于前两个输出,解释相当简单,sort() 方法对原始数组进行排序,并返回对同一对象的引用,所以arr1.sort() 实际上是对同一对象的引用arr1

对于第三个输出,arr1.sort() === arr2.sort() ,尽管每一个数组上的元素都是一样的,但=== 操作符不会测试数组的元素,而是测试每个对象的引用,在这种情况下,引用是不同的,因此返回false


问题#2:对象互斥性

在这个场景中,我想模拟一个对象,它代表一个作者,以及他的网站信息。然后我们将使用Object.freeze() ,所以它不能被改变,我们将对它进行测试。你认为结果会是什么?

const author = {
  name: 'Juan',
  website: {
    type: 'blog',
    url: 'https://livecodestream.dev',
  }
}

Object.freeze(author)

author.website.type = 'test'

console.log(author.website.type)

答案

test

如果你答对了,恭喜你!如果没有,别担心,我也在那里。我们来解释一下发生了什么。

当我们调用方法Object.freeze() ,我们冻结了对象,这意味着对象不能再被改变;冻结对象可以防止新的属性被添加到对象中,现有的属性被删除或改变。

但是,为什么我们能够改变这个对象呢?实际上我们没有,这就是诀窍。就所有目的而言,在变量author 网站是对一个对象的引用,并且这个引用在整个代码中保持不变。我们确实改变了website 对象内部的一个属性,但这并没有改变对该对象本身的引用。

如果你想知道如果我们试图改变author 对象的一个直接属性会发生什么,有两个可能的答案。让我们从第一种情况开始。

author.name = 'Laura'
console.log(author.name)

---------
Output
---------
"Juan"

在第一种情况下,即使我们改变了属性name ,也没有什么真正的改变,我们没有得到错误,没有警告,就像那行代码永远不会被执行。第二个方案是在严格模式下

"use strict"; author.name = 'Laura'
Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Object>'
    at <anonymous>:1:27

在严格模式下,如果我们试图修改一个冻结的对象,我们会得到一个TypeError 。比以前好多了。


问题#3:递归

给出以下递归函数,当我们以 "blog "为参数调用它时,你认为结果会是什么?

const recursive = str => {
  if (str.length > 1) {
      return recursive(str.slice(1))
  }

  return str
}

console.log(recursive('blog'))

答案

g

对于这个问题,没有什么诀窍,只是递归函数的一个基本用法,它将继续调用自己,直到字符串中只有一个元素str ,从而打印出原始字符串的最后一个字符,在这个例子中是g 。递归函数很重要,可以用非常有趣的方式解决问题,我们了解它们很重要。


问题#4:作用域

你认为输出到控制台的结果会是什么,为什么?

(function(){
  const a = b = 3
})()

console.log("a defined? " + (typeof a !== 'undefined'))
console.log("b defined? " + (typeof b !== 'undefined'))

答案

a defined? false
b defined? true

奇怪的警报!由于ab 都是在函数的包围范围内定义的,你会认为ab 实际上都是undefined

然而,情况并非如此。这里的问题是常见的误解,即:const a = b = 3 是对:const a = 3; const b = 3; 的速记,但事实上,它是对

b = 3;
const a = b;

但是,b 怎么能包围函数的范围之外被定义呢?诀窍是:b 最终成为一个全局变量(因为前面没有let,constvar )。但是a 仍然在函数的包围范围内。

注意,在严格模式下,这将产生一个ReferenceError: b is not defined


问题5:关于闭包的更多信息

下面的片段是一个实际流行的面试问题,问题是,你认为输出会是什么?

for (var i = 0; i < 5; i++) {
  setTimeout(function() { console.log(i); }, i * 1000 );
}

答案是

5
5
5
5
5

和你想象的不太一样?原因是在循环中执行的每个函数都会在整个循环完成后执行,因此都会引用存储在i 中的最后一个值,也就是5

闭包可以用来防止这个问题,为每个迭代创建一个唯一的范围,在其范围内存储变量的每个唯一值,如下所示。

for (var i = 0; i < 5; i++) {
    (function(x) {
        setTimeout(function() { console.log(x); }, x * 1000 );
    })(i);
}

从ES2015开始的另一个选择是使用let ,而不是var

for (let i = 0; i < 5; i++) {
	setTimeout(function() { console.log(i); }, i * 1000 );
}

总结

我希望你和我一样从中获得乐趣和学习,这篇文章写得特别有意思,我以后可能会做更多类似的文章。