一道有趣的 JavaScript 面试题
一道测试题,考察 ES6 的掌握程度和思维灵活程度
保持良好的编码风格
更详细的编码规范,可以来这: Developer code guide
Spaghetti code (面条代码)的特征
代码没有组织,且多处出现重复的代码块
多个代码块之间高度耦合,跳来跳去,使其难以调试
代码不会分解成条件块或标签,使其难以阅读。
避免面条代码的方法
优秀的代码组织应该是清晰的树状结构,自上而下分解任务, 自下而上完成任务。
防止 over-engineering (过度设计)
过度设计是指,太过于考虑今后代码的扩展性、复用性,或太过于考虑测试的便利性,导致系统被过度设计为难以理解、难以重用的复杂结构。
世界上有两种 “没有 BUG” 的代码。一种是“没有明显 BUG 的代码”,另一种是 “明显没有 BUG 的代码”。
第一种情况,由于代码复杂不堪,加上很多测试,各种 coverage,看起来测试都通过了,所以就认为代码是正确的。
第二种情况,由于代码简单直接,就算没写很多测试,你一眼看去就知道它不可能有 BUG。
你钟爱哪一种?
防止过度设计的方法:
代码规范可以参考上面链接就可以了,可以根据自己的情况修改规范以建立自己的标准,下面分享一些平日较为不易理解的代码片段。
==
和 !=
操作符会在需要的情况下自动转换数据类型;
===
和 !==
不会,它们会同时比较值和数据类型,也称为严格比较。
[10] === 10 // false
[10] == 10 // true
'10' == 10 // true
'10' === 10 // false
[] == 0 // true
[] === 0 // false
'' == false // true (but true == "a" is false,因为true隐式转换为字符串为'1')
'' === false // false
// 正常流程
var a
if (b) {
a = b
} else {
a = c
}
// 三目运算
var a = b ? b : c
// 利用短路运算判断赋值
var a = b || c
typeof
和 instanceof
/* typeof 会返回一个变量的基本类型,针对数组和对象均返回 'object' */
typeof 666 // 'number'
typeof Date() // 'string'
typeof [] // 'object'
typeof {} // 'object'
typeof false // 'boolean'
typeof new Function() // 'function'
typeof undefined // 'undefined'
typeof null // 'object'
/*
instanceof 仅检测对象的原型链是否指向构造函数的 prototype 对象
由于 JavaScript 中万物皆对象,故一切用 new 关键字实例的对象最深原型永远指向 Object
*/
666 instanceof Number // false
new Number(666) instanceof Number // true
new Number(666) instanceof Object // true
'666' instanceof String // false
new String('666') instanceof String // true
new Object() instanceof Object // true
[] instanceof Object // true
[] instanceof Array // true
new Date() instanceof Date // true
new Date() instanceof Object // true
// eval 能做的事真的太多了
var nums = [1, 2, 3, 4, 5, 6...]
console.log('和:', eval(nums.join('+')))
// 标准判断(推荐)
if (a) {
b()
}
// 简写
if (a) b()
// 利用短路运算简写
a && b()
// 或者(极力不推荐)
var foo = 10
foo == 10 && doSomething()
foo == 5 || doSomething()
var obj = { name: 'xxx' }
with (obj) {
console.log(name) // 'xxx'
}
// 一种不太好的情况
if (a) {
doSomethingA()
} else if (b) {
doSomethingB()
} else if (c) {
doSomethingC()
} else if (d || e) {
doSomethingDE()
} else if (f) {
doSomethingF()
} //...
// 可以用switch/case来代替
switch (true) {
case a:
doSomethingA()
break
case b:
doSomethingB()
break
case c:
doSomethingC()
break
case d || e:
doSomethingDE()
break
case f:
doSomethingF()
break
default:
doSomethingDefault()
break
}
完
「过度设计是指,太过于考虑今后代码的扩展性、复用性,或太过于考虑测试的便利性,导致系统被过度设计为难以理解、难以重用的复杂结构。」关于这个就有点感触,我们的java组长就是这样的人,每次和他讲咱们的功能界面上看,一定是要方便用户使用的,大部分用户你不把功能设计的简单到不行,他们根本无法理解和使用,但他每次都说要兼容以后的功能,现有多框架大家都熟悉了,不大可能更换。离谱的是很多功能用他的思路看,我居然觉得也可行,害。他坚决不改,我只好文档写写明白,但其实写的在明白,部署的时候还是要人去蹲很久,手把手教也不行。