<ul id="list" class="foo">
<li>#0</li>
<li><span>#1</span></li>
<li>#2</li>
<li>#3</li>
<li><ul><li>#4</li></ul></li>
...
<li><a href="//v2ex.com">#99998</a></li>
<li>#99999</li>
<li>#100000</li>
</ul>
<ul>
添加一个类 bar
<li>
<li>
后面增加一个 <li>
, 其文字内容为 <v2ex.com />
<li>
弹窗显示其为当前列表中的第几项。最近又来了个资深工程师面试,结果现场写代码环节写不出上面类似的题目。🌚
讲道理这题真的不难啊,就是简单的 DOM 操作,没有任何奇技淫巧,现场写:一台 MBP / 30 分钟 / 允许 Google ,只要基本功够扎实应该都能写出来吧。
其实现场考的版本比这个还简单,这个是为了发帖稍微整理后的版本,大家来喷一波。
(顺便补个广告,招前端,薪资对标阿里 P6 ,可年后入职,年前入职可以补偿年终奖,因为不是招聘结点我就不放邮箱了,有兴趣私我哈)
1
sagaxu 2016-12-20 18:21:05 +08:00
可以用 jquery 吗?可以的话,我这个后端也会啊
|
2
weegc 2016-12-20 18:24:05 +08:00
感觉可以试试,工作地点在哪里?
|
3
ByZHkc3 2016-12-20 18:27:11 +08:00 via Android
还好,考察了不少基础知识点。谷歌都做不出来的人不招也罢~
但是招人不得贴待遇吗 |
4
v1024 2016-12-20 18:30:26 +08:00 via iPhone
能做出来.. 搭车问下 p6 啥概念..?
|
5
heeexy 2016-12-20 18:31:08 +08:00 8
这道题想必考察的是会不会用 MBP...
|
6
reus 2016-12-20 18:38:37 +08:00
能 google 都做不出来,水平也太差了……
工作地点哪里? |
7
sudoz 2016-12-20 18:41:31 +08:00 1
我就是那个坐在电脑前半小时没憋出来的资深前端……哈哈
|
8
forgcode 2016-12-20 18:45:26 +08:00
阿里 P6 是啥级别!这个面试题是什么级别!
|
9
RE 2016-12-20 18:47:33 +08:00
同问工作地点在哪
|
10
leega0 2016-12-20 18:47:42 +08:00 via iPhone
我怎么没遇到可以用 Google 的面试
|
12
xcodebuild 2016-12-20 18:57:40 +08:00 1
允许 Google 都写不出来不可能吧。。
|
13
ByZHkc3 2016-12-20 18:59:50 +08:00 via Android
@codefalling 只能说面试者差劲啊,哪怕基础不好,会 Google 都能写出个大概
|
14
helloccav 2016-12-20 19:02:29 +08:00
允许 Google 还写不出?
弱问一下,允许加载 jquery 吗?我不懂原生 js ,逃^^^^ |
15
ClassicOldSong 2016-12-20 19:08:59 +08:00
这题有什么难度。。。。。
不过要说奇技淫巧的话还是有的,就看你想不想用了 |
17
ZhaoMiing 2016-12-20 19:09:31 +08:00
老题啊, DOM 操作和闭包
|
18
bramblex 2016-12-20 19:23:29 +08:00
操作 DOM 那么脏的事情不干
|
19
Septembers 2016-12-20 19:34:49 +08:00 1
document.querySelector('#list').classList.add('bar')
document.querySelector('#list:nth-of-type(10n)').remove() document.querySelector('#list:nth-of-type(500n)').appendChild(() => { const element = document.createElement('li') element.innerText = '<v2ex.com />' return element }) document.querySelector('#list').addEventListener('click', event => { const target = event.target alert(Array.from(target.parentElement.childNodes).findIndex(ele => ele === target)) }) |
20
ljcarsenal 2016-12-20 19:37:15 +08:00
@v1024 25w+ 的吧
|
21
MrFireAwayH 2016-12-20 19:37:44 +08:00 via Android
@bramblex 活捉我家 Kevin 酱~
|
22
ljcarsenal 2016-12-20 19:40:42 +08:00
刚想看看是哪个公司 发现有前同事在你厂
|
23
lijsh 2016-12-20 19:59:35 +08:00
|
24
lijsh 2016-12-20 20:00:10 +08:00
上面的题目是: js 中如何获得 <ul> 下的第一个 <li>
|
25
dxcqcv 2016-12-20 20:45:56 +08:00
第 3 道挺难的,我也超过时间了,果然还是技术不行
贴一波答案 ```javascript var u = document.querySelector('.foo'); u.classList.add('bar'); var li = u.querySelectorAll('li'); console.log(li.length); li[9].parentNode.removeChild(li[9]); var t = '<v2ex.com />'; li[499].insertAdjacentHTML('afterend','<li>'+t+'</li>'); for(var i =0, l = li.length; i < l; i++) { (function(i){ li[i].onclick =function(){ alert(i) } ; }(i)) } ``` 最后贴个简历,(简历地址)[https://dxcqcv.github.io/resume/html/index.html], 楼主招不招中级前端,哈哈 |
26
otakustay 2016-12-20 20:46:41 +08:00
这题就是个应届生级别,有 querySelector 直接上 nth-child 没有就 for 一把的事情……
|
27
kisnows 2016-12-20 20:50:00 +08:00
P6 对应的是级别是 资深 呀。
那 P5 对应的是 高级 ? |
28
wmc 2016-12-20 20:55:02 +08:00
校招题目都比这难了。。。😂
|
29
alvie 2016-12-20 21:22:21 +08:00
作为一个后端工程师表示都会做...
|
30
wly19960911 2016-12-20 22:10:58 +08:00 via Android
这难度几乎没有吧,考察了几个 dom 操作,上面说会超过时间我明天看看,不知道会不会超过时间,毕竟标签这么多,原来做过一个很垃圾的代码整个运行效率都被脱累过。。
|
32
murmur 2016-12-20 23:53:43 +08:00
考点难道是 IE8/9 下不能直接删除元素必须先找到元素然后用父节点删子节点?
|
33
oglop 2016-12-21 00:57:10 +08:00 via Android
我觉得这道题的内涵在于测试面试者如何自举翻 wall 上 google
|
34
wdhwg001 2016-12-21 02:12:18 +08:00 via iPhone
内啥… V2EX 没有私信功能…
|
37
skydiver 2016-12-21 02:37:45 +08:00 via Android
这题目我一个后端都会…
|
38
emric 2016-12-21 04:35:45 +08:00
题目不错, ie9+ 还算简单。
1. classList 2, 3. list.children or querySelector + css 4. 事件委托 + indexOf + 阻止冒泡 |
39
DWabo 2016-12-21 04:42:35 +08:00 via Android
我一个学了 2 个月的初级前端也能做出来。
|
40
justyy 2016-12-21 05:17:43 +08:00
可以 google 根本就不难。我记不住,但是我会用 google, 三两下就能找到答案。。
问题是 国内面试的时候 能上 google 么? |
41
xcv58 2016-12-21 05:36:11 +08:00
竟然直接操作 DOM ,这公司我不去。
|
42
des 2016-12-21 08:21:40 +08:00 via iPhone
这也难?你们都不是前端吧?
说监听事件多的什么情况?难道你们不知道事件冒泡机制?? 还有说闭包的,难道你们没考虑插入和删除会改变排序? 只不过计算是第几项,没有什么好办法,为了快速解决这个题目,我会选择遍历。 就这题目还能谷歌,你们要求也太低了吧? 如果换我,我也会觉得是在考验我使用 MBP 的能力,因为我也不会用, lol |
43
coolair 2016-12-21 08:25:58 +08:00 via Android
有 google 可以写出任何代码,只要自己有思路
|
44
halden 2016-12-21 08:26:17 +08:00
招前端考原始 js 意义不大吧,现在做什么不都是用第三方库的
|
45
sxd 2016-12-21 08:27:50 +08:00
饿了么还考操作 dom 啊 不都用 Element 么 (手动滑稽
|
47
Ahri 2016-12-21 08:41:43 +08:00
可以 google 应该能做出来,不过这问题跟茴香豆的茴字有几种写法差不多,无用的知识。
|
48
Felldeadbird 2016-12-21 09:14:48 +08:00
这道题很简单啊,我这个后端看一眼就知道了。 当然,我是说用 JQ 的情况下。 23333 。不过用原生 JS 写,也没啥压力啊。面试过程如果时间不够,就不考虑兼容呗。
|
49
ybh37 2016-12-21 09:19:30 +08:00
百度就能搞定,还用 Google
|
50
Mcatt 2016-12-21 09:36:27 +08:00
好简单喔
|
51
haocity 2016-12-21 09:49:43 +08:00
var ul=document.getElementById('list');
ul.className+=' foo'; var li=ul.getElementsByTagName('li'); ul.removeChild(li[9]); li[499].insertAdjacentHTML('afterend', '<li>v2ex.com </>'); for(var i =0, l = li.length; i < l; i++) { x(i)} function x(i){ li[i].onclick =function(){alert(i)} } 应该能兼容 IE6 ..还没实验 |
52
ajan 2016-12-21 09:52:21 +08:00
这题这么简单,还有 Mac 答题机器,答不上来对不住自己。
BTW ,我前些时间面试碰到有家鸟公司给了三页笔试题,题多得连答题的空间都没,在纸上写代码,真是日了狗了,记得有道题是 CSS 绘制他们公司的 logo, 很简单,但是连稿子或答题空间都不留,这垃圾公司,我坐了 2 分钟毅然离开。 |
55
SilentDepth 2016-12-21 10:09:46 +08:00
@ajan CSS 画 logo 确定不是他们美工塞的题? 2333
|
56
SilentDepth 2016-12-21 10:12:13 +08:00
@lynth 如果只包含根级<ul>的<li>, children 就好了;如果要包含所有可能的<li>, querySelectorAll('li')。我觉得是后者
|
57
Nutlee 2016-12-21 10:13:30 +08:00
遍历操作 li ,同时把 li 索引缓存到自己身上,用事件委托绑定事件。。 是我想简单了么 ??
|
59
tomwei7 2016-12-21 10:15:03 +08:00
我觉得我这个后端都能写出来,当然要靠 chrome console 强大的代码不全功能
|
60
funnuy 2016-12-21 10:21:51 +08:00
用 NodeIterator 写了一个
|
61
wungqiang 2016-12-21 10:24:48 +08:00 1
考察点:
- 会考虑到特性检测吗 if ('querySelectorAll' in xxx) {} - 选择器会用 id selector 还是 class selector - 闭包实现,深入问其它方法 - DOM 基本操作 - 性能及其它 |
62
hanyang 2016-12-21 10:30:32 +08:00
不管用什么库 这些操作 DOM 的基本知识都是要掌握吧
|
63
homfen 2016-12-21 10:31:48 +08:00
贵公司的资深工程师要求好低
|
65
henryxie2093 2016-12-21 10:49:36 +08:00
帖子标题本来就说明白了,为什么大家还要说这题没难度
|
66
chemzqm 2016-12-21 10:55:03 +08:00
@Septembers 最后写错了, e.target 会找到 li 下的 span
|
68
haocity 2016-12-21 11:34:08 +08:00
@lynth
额 审题不严 当时在上别的课 就看了一遍题目 记不清了 写了直接发上来来了 ul.className+=' foo';这里也写错了 应该是加上 bar ul.className+=' bar'; li 改成这样方法来取 var li=[]; for (var i = ul.childNodes.length - 1; i >= 0; i--) { if(ul.childNodes[i].nodeName=='LI') { li.push(ul.childNodes[i]) } } |
69
hoosin 2016-12-21 11:36:48 +08:00
居然没有一个人封装一下
```js var $ = document.querySelector.bind(document) ``` |
70
ZoomZhao 2016-12-21 11:41:50 +08:00
|
71
echol 2016-12-21 11:43:36 +08:00
不是很懂
(function(){ const rootNode = document.querySelector('#list'); /*#1*/ rootNode.classList.add('bar'); rootNode.querySelectorAll('ul').classList.add('bar'); /*#2*/ const delindex = 10, addindex = 500; const liNodes = rootNode.querySelectorAll('li'); rootNode.removeChild(liNodes[delindex - 1]); /*#3*/ const escapeHtml = function(string) { var entityMap = { "&": "&", "<": "<", ">": ">", '"': '"', "'": ''', "/": '/' }; return String(string).replace(/[&<>"'\/]/g, function (s) { return entityMap[s]; }); } const addnode = document.createElement('li'); addnode.innerHTML = escapeHtml('<v2ex.com />'); if(liNodes[addindex -1].nextElementSibling == null){ liNodes[addindex -1].parentElement.appendChild(addnode); } else{ liNodes[addindex -1].nextElementSibling.insertBefore(addnode); } /*#4*/ for(let i = 0, max = liNodes.length; i < max; i++){ liNodes[i].setAttribute('data-index', i); } rootNode.addEventListener('click', (e) => { if(e.target.nodeName !== 'LI') return; alert(e.target.getAttribute('data-index')); }, false); }) |
73
Septembers 2016-12-21 12:13:48 +08:00
@chemzqm event.target.closest('li') 就对啦 不过没有考虑深度嵌套
|
74
Septembers 2016-12-21 12:16:08 +08:00
|
76
Septembers 2016-12-21 12:17:55 +08:00
@ZoomZhao see http://mdn.io/closest
@echol escapeHtml 用不着这样 textContent 就好啦 see http://mdn.io/textContent |
77
ahkxhyl 2016-12-21 12:21:06 +08:00
jquery 可以搞搞 纯 js 查资料可以~~ 非前端人员 打酱油后端 php 路过~~
|
78
exoticknight 2016-12-21 12:52:35 +08:00
后悔没去饿了么校招……
1. classList.add 或者 className 2. children[9] 或者 nth-of-type(10), removeChild 3. insertAdjacentElement('afterend', '<li><v2ex.com /></>'),不想转码就老老实实 createElement + innerText / textContent ,再 insertAdjacentElement 4. 事件委托大家都会了……重点代码就是 [].slice.call(ul.children).indexOf(e.target),不过 indexOf 可能有兼容问题,换 for 循环也可以 |
79
Anshi 2016-12-21 13:08:10 +08:00
会这道题不代表满足这个职位的其他要求啊。。。囧
|
80
echol 2016-12-21 13:14:27 +08:00
@Septembers 印象里有这个作用的 api 就是没想到,多谢
|
82
mqtt 2016-12-21 13:32:38 +08:00
还资深前端,我这 php 、前端都做的人都会写。
|
83
Rsl 2016-12-21 14:00:32 +08:00
这都不需要会吧, 会 google 就行...
|
84
Tonni 2016-12-21 14:26:59 +08:00
不巧,前段时间去饿了么面试被问到了这个问题,不过上机时并没有让我做这道题,看到楼主把这件事发到 V2 上面了,吃过午饭花了四十分钟写完的: http://codepen.io/HouCoder/pen/MbxXVm 。
|
85
Lothar OP @Tonni 给点小建议哈,题干里的 li 里面可能还有嵌套 ul ,#3 的文字内容不对,#4 同理, event.target 并不一定就是 li ,需要向上查找判断下。
|
87
a40049 2016-12-21 16:54:34 +08:00
这个很简单啊,饿了么的面试题如果这么简单的话感觉我也可以去啊。就算不用 DOM 库也只是简单的 classlist(如果不支持 classlist 就用 className & Regular Expression) parentNode removeChild createElement addEventListener appendChild ,返回 index 稍微棘手点,需要配合 children 遍历。干脆你把全部的职位要求写出来,说不定我这次有机会呢。
|
88
davidzd 2016-12-21 17:17:49 +08:00
@Septembers 额删完了 第 500 个还是第 500 个么
|
89
spring5413 2016-12-21 17:31:22 +08:00
var oUl = document.getElementById("list");
oUl.className = oUl.className + " bar"; oUl.removeChild(oUl.getElementsByTagName("li")[3]); document.body.addEventListener("click", function(e) { if (e.target.tagName.toLowerCase() != "li") { return; } var self = e.target || e.srcElement, oParent = self.parentNode, children = oParent.children; for (var i = 0, l = children.length; i < l; i++) { if (children[i] == self) { alert(i); break; } } }, false); |
90
davidzd 2016-12-21 18:01:36 +08:00
其实 ES6 里面就这么简单啊
let listTest = document.getElementById('list'); listTest.className = 'bar'; listTest.children[9].remove(); listTest.children[498].innerHTML += 'v2ex'; listTest.addEventListener('click', event => { alert(Array.from(event.target.parentNode.children).indexOf(event.target)+1) }) 这题目唯一的陷阱就是不要让前面的操作打乱了序号啊。。 |
91
Septembers 2016-12-21 18:47:56 +08:00
@davidzd
注意措辞是 "删除第 10 个" "在第 500 个" 可以解释成 操作位于某个位置的元素 并 进行操作 并且没一段都没有上下文进行限定 如果带有这个限定的话 实现则可写成 const nth10 = document.querySelector('#list:nth-of-type(10n)') const nth500 = document.querySelector('#list:nth-of-type(500n)') 然后分别进行操作 |
92
bobsam 2016-12-21 22:34:58 +08:00
这道题。。。不是应届生标准题吗。。。做出来能有 P6 啦?
|
93
halden 2016-12-22 00:53:34 +08:00
@Rice 我在美国面试了这么多,考察原生 js 的一般只涉及代码阅读,因为这里关于 js 的基础知识,要你写代码的至少给了 jQuery
|
95
tidewind 2016-12-22 10:13:43 +08:00
用不用 jquery 也无所谓,原生 js 也可以搞啊,半小时,还可以 google ,我作为一个后端都可以去搞定。确定这是对标 P6 的面试题么...
|
96
davidzd 2016-12-22 11:21:19 +08:00
@Septembers 对啊,肯定是跟着#No. 走的啊,不过这可能也不是考察重点哈哈哈
|
97
davidzd 2016-12-22 11:21:52 +08:00
这题用 jquery 干毛?
|
98
501956430 2016-12-22 11:45:24 +08:00 via iPhone
用 jq 挺简单的
|
99
banxi1988 2016-12-22 11:53:58 +08:00 1
我也来参与一下:
解与说明: 1. 添加类. - 经典写法 `node.className = node.className + " bar"` - 新式写法 (IE10+) `node.classList.add("bar")` 拓展: `classList` 是一个只读属性,指向 `DOMTokenList` 还有如下方法: `add(String [,String])`, `remove(String[,String])`,`item(Number)`,`toggle(String[, force])` 2. 删除第 10 个 `<li>` - 经典写法: ```js var lilist = document.getElementsByTagName("li"); var li10 = lilist[9]; li10.parentNode.removeChild(li10); ``` - 新式写法: ```js var li10 = document.querySelector("li:nth-of-type(10)"); li10.parentNode.removeChild(li10); ``` 需要注意的是: nth 是以 1 based index. 而 数组是 0 based index. 3. 在第 500 个 <li> 后面增加一个 <li> , 其文字内容为 <v2ex.com /> ```js var v2exNode = document.createElement("li"); v2exNode.textContent = "<V2EX.com />"; var li501 = document.getElementsByTagName("li")[500]; li501.parentNode.insertBefore(v2exNode,li501); ``` 值得注意的是, DOM API 只有 insertBefore 没有 insertAfter 所以要先取到第 501 个. 4. 点击任意 <li> 弹窗显示其为当前列表中的第几项。 ```js var ul = document.getElementById("list"); ul.addEventListener("click",function(event){ var target = event.target; if(target.nodeName === "LI"){ var parentUl = target.parentNode; var children = parentUl.childNodes; var count = 0; for(var i = 0; i < children.length;i++){ var node = children[i]; if(node.nodeName === "LI"){ count += 1; if(node === target){ alert("是当前第"+(count)+"项"); break; } } } } }); ``` 我这里 给 `ul#list` 添加 click 方法然后判断 `target` 来实现的. 因为我不想添加太多的 eventListener. 值得注意的是: 需要通过 `childNodes` 来遍历. 因为 `li` 中还是可以再嵌套 `ul>li` 附: 生成测试 html 的脚本: ```py # -*- coding: utf-8 -*- import random __author__ = 'banxi' index = -1 def make_index(): global index index += 1 if random.uniform(1, 10) > 8: return '<span>#%d</span>' % index else: return "#%d" % index def make_ul(): html = '<ul>' for i in range(0, random.randint(1, 5)): html += make_li() html += '</ul>' return html def make_li(): if random.uniform(1, 10) < 1.5: inner_html = make_ul() else: inner_html = make_index() return "<li>%s</li>" % inner_html if __name__ == '__main__': import codecs with codecs.open('ele.html', 'w', encoding='utf-8') as f: html = '<ul id="list" class="foo">' while index < 100000: html += make_li() html += "</ul>" f.write(html) ``` |
100
galenyuan 2016-12-22 12:52:04 +08:00
http://jsbin.com/filecaw/edit?html,js,output
简单答一波=。= 第三题用到 insertAdjacentHTML 是现搜的,其他的基本都手答了 |