面试题----不定时更新

2018-03-07

1. 实现一个函数 isObjectEqual 满足以下 Test Case:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* test case - expect */
isObjectEqual(null) // false
isObjectEqual(null, 0) // false
isObjectEqual(1, true) // false
isObjectEqual(1, '1') // false

isObjectEqual() // true
isObjectEqual(null, null) // true
isObjectEqual(0, 0) // true
isObjectEqual(true, true) // true
isObjectEqual('1', '1') // true

isObjectEqual([], []) // true
isObjectEqual([1, 2], [1, 2]) // true
isObjectEqual([1, 2], [2, 1]) // false
isObjectEqual([1, {}, null], [1, {}, null]) // true

isObjectEqual({}, {}) // true
isObjectEqual({ a: 1 }, { a: 1 }) // true
isObjectEqual({ a: [1, 2] }, { a: [2, 1] }) // false
isObjectEqual({ a: 1, b: { c: [2] } }, { a: 1, b: { c: [2] } }) // true

这道题的要求就是实现一个函数,用来判断两个值是否相等。其中,需要注意的是要能够对对象类型的数据进行深层比较。下面梳理一下题目的要求:

  1. 对于基本类型的值,需要进行全等比较,即用 === 来判断。
  2. 对于对象类型的值:如果是两个数组进行比较,需要判断数组内的每一项及其索引分别对应相等,如果数组内的值是对象类型或数组类型,需要一直进行比较;如果是两个对象进行比较,需要判断对象的属性和值对应相等,如果属性的值不是基本类型的,需要继续比较。
    下面是我的答案,对于以上情景均能通过。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
const isObjectEqual = (...args) => {
if (args.length === 0) {
return true
}

if (args.length === 1) {
if (args[0] === null) {
return false
}
}

const isPrimitry = arg => {
return (typeof arg !== 'object' && typeof arg !== 'function') || arg === null
}

const isObj = arg => {
return typeof arg === 'object' && arg !== null && !Array.isArray(arg)
}

const isArr = arg => {
return arg instanceof Array
}

const isObjEqual = (...objs) => {
let val = '', res = true,
prev = objs[0],
next = objs[1]

if (Object.keys(prev).length !== Object.keys(next).length) {
return false
}

for (let key in prev) {
if (!res) return res
val = prev[key]
if (isPrimitry(val)) {
if (val !== next[key]) res = false
} else if (isArr(val)) {
res = isArrEqual(val, next[key])
} else if (isObj(val)) {
res = isObjEqual(val, next[key])
}
}

return res
}

const isArrEqual = (...arrs) => {
let res = true
arrs[0].forEach((val, idx) => {
if (!res) return res

if (isPrimitry(val)) {
if (val !== arrs[1][idx]) res = false
} else if (isArr(val)) {
res = isArrEqual(val, arrs[1][idx])
} else if (isObj(val)) {
res = isObjEqual(val, arrs[1][idx])
}
})

return res
}

if (args.length === 2) {
// 非对象类型的
if (isPrimitry(args[0]) && isPrimitry(args[1])) {
return args[0] === args[1]
}

if (({}).toString.call(args[0]) !== ({}).toString.call(args[1])) {
return false
}

if (isArr(args[0]) && isArr([args[1]])) {
if (args[0].length !== args[1].length) {
return false
}

return isArrEqual(args[0], args[1])
}

if (isObj(args[0]) && isObj(args[1])) {
return isObjEqual(args[0], args[1])
}

}
}

2. 为以下列表添加 click 监听,在点击任一 li 时触发 alert 弹窗,内容为当前li在列表中的索引(进阶: 如果 li 的数量特别多应该怎么优化,如果 li 中还含有别的元素应该怎么处理)。

这个题简直就是面试题中的经典了,去年暑假面试实习生的时候碰到了这个题,结果不出意外地没做出来,归根到底还是对dom的理解不够。
话不多说,just coding…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<ul id="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li></li>
<li></li>
<li></li>
<li></li>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<li></li>
<li></li>
<li></li>
<li></li>
<p>6</p>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>

<script type="text/javascript">
window.onload = function () {
let oUl = document.querySelector('#list'), index,
aLi = [].slice.call(oUl.getElementsByTagName('li'));

oUl.addEventListener('click', e => {
index = aLi.indexOf(e.target)
if (index < 0) {
return;
}
alert(index)
}, false)
}
</script>
</body>
</html>