今天跟大家分享 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" }
可以在控制台中试一试:
答案
是的,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)
分析与答案
看看下面的图片,我想你就会知道答案。
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" }