99% 的前端开发都无法答对的 10 个面试问题

617 阅读4分钟

今天跟大家分享 10 道有(奇)趣(怪)的前端面试题,这里每道题都有一些有趣的知识点。回答之前仔细思考一下,看看你能答对几题吧~

Q1: 使用对象作为 key

下面这段代码会输出什么?

const x = {}
const y = { key: 'y' }
const z = { key: 'z' }
x[y] = 'fatfish'
x[z] = 'medium'
console.log(x[y])

分析

你现在心里是不是在想:这不写着 x[y] = 'fatfish',那输出肯定就是 'fatfish'啦。

然而众所周知,如果使用一个对象作为属性键,最终会是这样的。实际的关键是[object Object]

const objKey = { key: 'fatfish' }
const obj = {
  [ objKey ]: 'fatfish'
}
console.log(obj) // { [object Object]: "fatfish" }

可以在控制台中试一试:

image.png

答案

是的,medium 才是最终的答案。

const x = {}
const y = { key: 'y' }
const z = { key: 'z' }
x[y] = 'fatfish' // x => { [object Object]: "fatfish" }
x[z] = 'medium' // x => { [object Object]: "medium" }
console.log(x[y]) // medium

Q2:nums 的值是多少?

下面这段代码,nums 会输出什么?

const len = 5
const nums = []
for (var i = 0; i < len; i++);{
  nums.push(i + 1)
}
 
console.log(nums)

分析

其实这道题考的不是你的编程能力,更多的是考察你的眼神。如果你没有仔细留意 ; 的位置,那么得出的答案一定是 [1,2,3,4,5]

答案

; 的位置决定了 for 循环语句是先执行的。因此,最终输出的结果是 [6]

const len = 5
const nums = []
for (var i = 0; i < len; i++);
// At this time, i has become 6
{
  nums.push(i + 1)
}
 
console.log(nums) // [ 6 ]

Q3:小心 Array.sort

下面这段代码的排序结果是什么?

const arr = [1, 30, 4, 21, 100000]
console.log(arr.sort())

分析

从直觉上来看,你应该会认为答案显而易见是 [1, 4, 21, 30, 100000]。但实际上这里有个隐藏的坑,这段代码中的 arr.sort 并没有传递比较函数。

MDN 中对 Array.sort 的介绍是这样的:

TIPS:指定定义排序顺序的函数。如果省略,数组元素将转换为字符串,然后根据每个字符的 Unicode 值进行排序。

答案

因此这里并不是简单的元素大小排序,而是转换成 unicode 之后的大小排序。

const arr = [1, 30, 4, 21, 100000]
// the array elements are converted to strings, then sorted according to each character's Unicode code point value
const charCodesOfArr = arr.map((num) => `${num}`.charCodeAt()) // [49, 51, 52, 50, 49]
// so the answer is [1, 100000, 21, 30, 4]
console.log(arr.sort())

Q4: 变量声明中的隐藏陷阱

下面这段代码会输出什么?

const fn = () => {
  let x = y = 1000
  x++
  return x
}
 
fn()
console.log(typeof x)
console.log(typeof y)

分析

99% 的开发者会说两个输出都是 undefined,因为 x 和 y 都不是全局变量。

但实际上这段代码中的变量声明是有隐藏的坑的:

const fn = () => {
 // let x = y = 1000
 // 这段代码等同于如下代码;
 let x = 1000
 // 在这里,我们其实是声明了一个全局变量 y  
 y === 1000
}

答案

因此答案如下:

const fn = () => {
 // let x = y = 1000   
 // it is equivalent to the following code
 let x = 1000
 // Note that here, we define a global variable y  
 y === 1000
  x++
  return x
}
fn()
console.log(typeof x) // undefined
console.log(typeof y) // y equals 1000, so typeof y is number

Q5: 一些隐式转换规则

下面这段代码会输出什么?

console.log(+true)
console.log(!'fatfish')

分析

这里设计到两个隐式转换规则:

  • + 号运算符会将 boolean 类型转换为 number 类型;
  • 非空字符串转换为 boolean 的值是 true;

答案

// The + operator converts the Boolean to a number, true is converted to 1, and false is converted to 0
console.log(+true) // 1
// The string "fatfish" is a true value, use ! It will become false
console.log(!'fatfish')

Q6: 变量提升

下面这段代码的 4 个输出分别是什么?

var x = 'fatfish'
const fn = () => {
  // No.3
  console.log(x)
  var x = 'medium'
  // No.4
  console.log(x)
}
// No.1
console.log(x)
fn()
// No.2
console.log(x)

分析与答案

答案如下:这也是为什么目前绝大多数项目中都禁止使用 var,声明变量必须使用 let / const

var x = 'fatfish'
const fn = () => {
  // No.3
  // var 声明变量会有变量提升问题
  var x = undefined
  // 因此这次打印 x 的值是 undefined
  console.log(x) // undefined
  // var x = 'medium'
  x = 'medium'
  // No.4
  // 这一次打印 x 被赋值为 medium,所以输出就是 medium
  console.log(x) // medium
}
// No.1
console.log(x) // fatfish
fn()
// No.2
console.log(x) // fatfish

Q7:数组的长度

下面这段代码会输出什么?

const nums = [ 10, 18, 0, 11, 9 ]
nums.length = 0
 
console.log(nums[3])

分析

如果你的答案是 11,那说明你对数组的 length 属性还不够了解。

当你使用 nums.length = 0 时,意味着 nums 会变空。

答案

所以正确的答案是 undefined

const nums = [ 10, 18, 0, 11, 9 ]
nums.length = 0 // it causes nums to become []
 
console.log(nums[3]) // undefined

Q8:for循环中SetTimeout?

下面这段代码会输出什么?

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i)
  }, 1000)
}

分析与答案

1秒后是否打印 0,1,2?

答案是不会,1秒后1变成了3,所以3会连续打印3次。

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) // 3 3 3
  }, 1000)
}

那如果就是想要 1 秒后打印 0,1,2,可以这么做:

// 1. 使用 let 代替 var
for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) // 0 1 2
  }, 1000)
}
// 2. 使用闭包
for (var i = 0; i < 3; i++) {
  ((n) => {
    setTimeout(() => {
      console.log(n) //  0 1 2
    }, 1000)
  })(i)
}

Q9: 原型

下面这段代码会输出什么?

const Animal = function (){ 
  this.type = 'animal'
}
   
const Cat = function (){ 
  this.name = 'cat'
}
 
Cat.prototype = new Animal()
 
const cat = new Cat(); 
 
console.log(cat.__proto__ === Cat.prototype)
console.log(Cat.prototype.__proto__ === Animal.prototype)

分析与答案

看看下面的图片,我想你就会知道答案。

image.png

const Animal = function (){ 
  this.type = 'animal'
}
   
const Cat = function (){ 
  this.name = 'cat'
}
 
Cat.prototype = new Animal()
 
const cat = new Cat(); 
 
console.log(cat.__proto__ === Cat.prototype) // true
console.log(Cat.prototype.__proto__ === Animal.prototype) // true

Q10:ES6模块导入导出知识

下面这段代码会输出什么?

// a.js 
export default () => "Hello medium"
export const name = "fatfish"
// b.js 
import * as data from "./a.js"
console.log(data)

答案

相信这道题对熟悉 ES6 模块的开发者来讲应该没什么难度,直接写答案吧!

// a.js 
export default () => "Hello medium"
export const name = "fatfish"
// b.js 
import * as data from "./a.js"
console.log(data) // { default: function default (), name: "fatfish" }

最后

本文翻译自: fatfish.medium.com/10-front-en…