2014年3月31日晚,我怀着略微忐忑的心情(第一次在线笔试^_^!!)进行了笔试,阿里巴巴的笔试题共有10道,几乎包含了Web前端开发的各个方面,有程序题、有叙述题,时间非常紧张,只完成了大概6道题。下面把遇到的题目跟大家分享一下!
1、
<!doctype html> <html> <head> <style type="text/css"> div:not(.outer) p { color: purple; } div.outer p { color: orange; } </style> </head> <body> <div class="outer"> <p> 我是 outer 里面的字 </p> <div class="inner"> <p> 我是 inner 里面的字 </p> </div> </div> </body> </html>
问:为什么以上两个<p> 标签中的文字颜色都是橙色的?
这里涉及到了CSS中的层叠和特殊性问题,首先按照上下顺序,第一个<p>元素它的样式很明显是由div.outer p 定义的,所以是橙色。第二个<p>元素的样式是由样式表中的两个样式同时定义,而且同样是color样式。根据《CSS权威指南》中的介绍,当CSS样式发生层叠时,要通过层叠规则来安排最终元素匹配的样式。
【需要理解成:not(.outer)和.outer的特殊性是相同的,一个是类,一个是伪类】
CSS2.1的层叠规则中的规定,在没有!important标志时,要按照特殊性排序,如果还不能比较完,就后面覆盖前面。
可以参考:CSS层叠规则
2、请实现一个Event类,继承自此类的对象都会拥有两个方法on和trigger,类声明如下,请写出完整代码:
function Event() {} Event.prototype.on = function(eventName, callback) { //注册事件监听 } Event.prototype.trigger = function(eventName, data) { //触发事件 }
参考代码:
<!DOCTYPE html> <html> <head> <title>Event</title> <meta charset="utf-8"> <script type="text/javascript"> var Event = function () { if (!(this instanceof Event)) { return new Event(); } this._callbacks = {}; } Event.prototype.on = function (eventName, callback) { //注册事件监听 this._callbacks = this._callbacks || {}; this._callbacks[eventName] = this._callbacks[eventName] || []; this._callbacks[eventName].push(callback); return this; } Event.prototype.trigger = function (eventName, data) { //触发事件 var list, ev, callback, args, i, l; var both = 2; var calls = this._callbacks; while (both--) { ev = both ? eventName : 'all'; list = calls[ev]; if (list) { for (i = 0, l = list.length; i < l; i++) { if (!(callback = list[i])) { list.splice(i, 1); i--; l--; } else { args = both ? Array.prototype.slice.call(arguments, 1) : arguments; callback.apply(this, args); } } } } return this; } var sayevent = new Event(); sayevent.on("sayhello",function(name){ alert("hello,"+name); }); sayevent.on("sayhello",function(){ alert("I miss you!"); }); sayevent.trigger("sayhello","gebin"); </script> </head> <body> </body> </html>
参考:http://html5ify.com/eventproxy/eventproxy.html
3、
要求实现一个多行文本输入框,固定宽度。可根据用户输入的内容多少进行高度自适应变化。如,用户输入了1行文字,则输入框显示为1行,而有2行文字,就显示2行。如微博的评论回复。
<!DOCTYPE html> <html> <head> <title>文本框换行</title> <meta charset="utf-8"> <style> .txt { border: 1px solid #CCC; width: 200px; padding: 3px; font: 12px/16px Simsun; outline: none; resize: none; word-wrap: break-word; word-break: break-all; overflow: hidden; } </style> <script> window.addEventListener('load', function () { (function (o, e, t) { //创建一个pre标签,用来计算文字应有高度 e = document.createElement("pre"); //给pre添加上和文本域一样的样式 e.className = "txt"; //设置绝对定位到屏幕外来隐藏它 e.style.position = "absolute"; e.style.left = "-9999px"; //创建一个文本节点来操作,避免直接操作HTML e.appendChild(t = document.createTextNode("")); //给pre的末尾添加一个换行,因为pre会吞掉末尾的一个换行 e.appendChild(document.createTextNode("\n")); //把pre放入文档中 document.body.appendChild(e); //文本域键盘事件时计算高度 o.onkeydown = o.onkeyup = function () { //IE8下\r\n在PRE标签中会被解析为两行,所以需要一个替换 //如果觉得这样会影响效率可以先判断浏览器 t.data = o.value.replace(/\r\n/g, "\n"); o.style.height = e.offsetHeight - 8 + "px"; }; //初始时计算一次 o.onkeydown(); //为了避免换行时闪的太厉害,稍微阻止下滚动 o.onscroll = function () { o.scrollTop = 0 }; })(document.getElementById("o")); }, false); </script> </head> <body> <textarea id="o" class="txt">来呀,来编辑我呀~</textarea> </body> </html>
4、
编写一个JavasSript函数,给定一个DOM节点node和一个正整数n,返回node的所有第n代后代节点(直接子节点为第1代)
function getDescendants(node, n) { // return an Array }
<script type="text/javascript" > function getDescendants(node, n) { //node, n var childArr = []; var len,tempArr,childNodelist; childArr.push(node); for(var i = 0; i<n ; i++){ len = childArr.length; tempArr = []; for(var j = 0;j<len;j++){ childNodeList = makeArray(childArr[j].childNodes); tempArr = tempArr.concat(childNodeList); } childArr = tempArr; } return childArr; } var makeArray = function(obj){ return Array.prototype.slice.call(obj,0); } var result = getDescendants(document.getElementById("content"),2); alert(result); </script>
5、有2个int型已经去重的数组a和b,都是已经从小到大排序好的。要求遍历b数组的数字,如果这个数字出现在a中,就将其从a删去;反之将其插入到a的适当位置,使a保持排序状态。
<script type="text/javascript" charset="utf-8"> //有2个int型已经去重的数组a和b,都是已经从小到大排序好的。要求遍历b数组的数字, //如果这个数字出现在a中,就将其从a删去;反之将其插入到a的适当位置,使a保持排序状态。 var mySort = {}; mySort.sortArr = function(a, b) { var pos = 0; for (var i = 0; i < b.length; i++) { pos = mySort.checkRepeat(a, b[i],pos); } } mySort.checkRepeat = function(a, v, pos) { var isChanged = false; if (a != null && a != undefined && a.length > 0) { for (var j = pos; j < a.length; j++) { if (a[j] == v) { a.splice(j, 1); break; } else if (a[j] > v) { a.splice(j, 0, v); break; } } if(j == a.length){ a.push(v); } return j; } } var a = [2,7,12,25,36,64]; var b = [2,3,9,32,36,56,87]; document.write("合并前数组a为:"+a.toString()+"<br>"); document.write("合并前数组b为:"+b.toString()+"<br>"); mySort.sortArr(a,b); document.write("合并后数组a为:"+a.toString());//结果是:
合并前数组a为:2,7,12,25,36,64
合并前数组b为:2,3,9,32,36,56,87
合并后数组a为:3,7,9,12,25,32,56,64,87
6、请描述一下从用户输入网址开始,到网页最后呈现出来的全过程,越详细越好,包括各种事件等。
if (window.addEventListener) { var addListener = function (el, type, listener, useCapture) { el.addEventListener(type, listener, useCapture); }; } else if (document.all) { addListener = function (el, type, listener) { el.attachEvent("on" + type, function () { listener.apply(el); }); }; }
参考答案:(网友提供)
a) 功能:事件注册
b) 优点:跨浏览器,特性探测,性能优化。缺点:document.all
c) 作用:使得IE中listener的this 为 el,与其它浏览器一致
d) 改进:document.all改成window.attachEvent; useCapture的默认值
9、你最近看的前端相关技术书是什么?常关注的博客是哪些?你觉着哪个网站的交互做的好,为什么?
《JavaScript权威指南》、《JavaScript语言精粹》
W3cfuns、阮一峰、前端前沿、WebHek、前端开发,等等
当时就写了淘宝的交互,从购物车、商品分类、响应式设计等方面讲了一下。
10、阅读如下代码:
var dog = function () { return '汪'; }; var cat = function () { return '喵'; }; (function () { if (cat() === '喵喵') { dog = function () { return '汪汪'; } } function cat() { return '喵喵'; } })(); for (var i = 0; i < 10; i++) { setTimeout(function () { for (var j = 1; j <= i; j++) { console.log(dog()); } }, 1000 * i); }
问:1、为什么最终小狗叫了200声汪?请详细说明为什么。2、修改代码setTimeout部分代码,实现每隔1秒调用i(从1到10递增)次dog()。
1、第一题重点在于函数作用域的问题。
2、 修改后的setTimeout函数是
for (var i = 0; i < 10; i++) { (function(a) { setTimeout(function() { for (var j = 1; j <= a; j++) { document.write(dog()+" "+a+"<br>"); } }, 1000); })(i+1); }