2015-淘宝秋招

1.按照CommonJS规范,在任何模块代码的作用域下内置了以下哪些变量?
       A, module
       B,context
       C, require
       D,exports  
答:A,C,D
可以参考:
阮一峰commjs文章:输出模块变量的最好方法是使用module.exports对象,加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的module.exports对象
var i = 1;
var max = 30;

module.exports = function () {
  for (i -= 1; i++ < max; ) {
    console.log(i);
  }
  max *= 1.1;
};
使用require方法,加载example.js。

// main.js

var example = require('./example.js');

 


2.以下关于application cache的说法,哪些是不正确的?
·       A,对于目标页面而言,可以通过来启用application cache。
·       B, 对于启用了application cache的页面,该页面默认不会被缓存。
·       C,manifest文件仅在初次访问站点时才会被下载。//每次都会下载minifest
·       D, 对于manifest中列出的资源文件,只要它们被修改,下次访问站点时就会被重新下载。//修改了不会重新下载
答:BCD(A没有写全)
解析:application cache是HTML5的一种新技术,应用缓存,HTML5 使用ApplicationCache 接口解决了由离线带来的部分难题。前提是你需要访问的web页面至少被在线访问过一次。

3.下面哪些技术可用于优化 CSS 图片加载 ?
·      A CSSSprite
·      B SVGSprite
·      C,Iconfont
·      D Base64
 
答:ABCD
 
4。程序员小马对某 Git 仓库执行一系列操作,请写出每个步骤对应的 Git 命令:
1. 从当前分支hotfix 切换到分支 feature
2. 添加新文件 feature.js
3. 提交文件 feature.js,日志消息为“添加新文件”
4. 将 feature 分支衍合(变基)到 master 分支(不考虑文件冲突)
5. 推送feature 分支到远程服务器 origin 的同名分支
git checkout feature
git add feature.js
git commit -m '添加新文件'
git rebase master
git push origin feature:feature 
5.从前端工程师的角度如何提高页面的用户体验。

 加载速度快
兼容各种浏览器
http://www.iteye.com/news/24291

 

6.
<divclass='mod-spm'data-spmid='123'>
       <divclass='child_a'></div>
       <divclass='child_b'></div>
       <divclass='child_c'></div>
       <divclass='child_d'></div>
    </div>
    <divclass='mod-spm'data-spmid='456'>
       <divclass='child_a'></div>
       <divclass='child_b'></div>
       <divclass='child_c'></div>
       <divclass='child_d'></div>
    </div>
    <divclass='mod-spm'data-spmid='789'>
       <divclass='child_a'></div>
       <divclass='child_b'></div>
       <divclass='child_c'></div>
       <divclass='child_d'></div>
    </div>
有dom结构如上,请用原生代码(禁用jQuery作答)实现以下功能:
(a)计算鼠标在mod-spm区域内的停留时长,data-spm不同视为不同区域
(b)尽量减少性能损耗
(c)重复进入计时累加





7。有这样一个URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e,请写一段JS程序提取URL中的各个GET参数(参数名和参数个数不确定),将其按key-value形式返回到一个json结构中,如{a:'1', b:'2', c:'', d:'xxx', e:undefined}。

 

function getQuery(url) {
    var query = url.split('?')[1];
    if (!query) {
        return {};
    }
    query = query.split('&');

    var arr = {};

    for (var i = 0, l = query.length; i < l; i++) {
        var temp = query[i].split('=');
        var key = decodeURIComponent(temp[0]);//
        var value = decodeURIComponent(temp[1] == null ? '' : temp[1]);//value可能是空
        if (key in arr) {           //这段if else是处理key重复
            var valArr = arr[key];
            if (typeof valArr === 'string') {
                valArr = [valArr];
            }
            valArr.push(value);
            arr[key] = valArr;
        }
        else {
            arr[key] = value;
        }
    }

    return arr;
}

 

8.简述浏览器中使用js跨域获取数据的几种方法

jsonp 加载script脚本来跨域
通过修改document.domain来跨子域
使用window.name来进行跨域
使用HTML5中新引进的window.postMessage方法来跨域传送数据
flash

9.如何配置让 nginx 对 js、html、css 文件进行 gzip 压缩输出?




10.请填写个人github地址

https://github.com/QingFlye

11.编写一个JavaScript函数,输入指定类型的选择器(仅需支持id,class,tagName三种简单CSS选择器,无需兼容组合选择器)可以返回匹配的DOM节点,需考虑浏览器兼容性和性能。
/*** @param selector {String} 传入的CSS选择器。* @return{Array}*/
var query = function(selector){
//返回查找到的节点数组return [];}

 

  1 /**
  2  * 用于表示标识符
  3  *
  4  * @type {string}
  5  */
  6 var identifier = '(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+';
  7 
  8 /**
  9  * 用于表示空白字符
 10  *
 11  * @type {string}
 12  */
 13 var whitespace = '[\\x20\\t\\r\\n\\f]';
 14 
 15 /**
 16  * 基本选择器
 17  *
 18  * @type {Object}
 19  */
 20 var expr = {
 21 
 22     /**
 23      * ID选择器
 24      *
 25      * @type {RegExp}
 26      */
 27     'ID': new RegExp('^#(' + identifier + ')'),
 28 
 29     /**
 30      * 类选择器
 31      *
 32      * @type {RegExp}
 33      */
 34     'CLASS': new RegExp('^\\.(' + identifier + ')'),
 35 
 36     /**
 37      * 标签选择器
 38      *
 39      * @type {RegExp}
 40      */
 41     'TAG': new RegExp('^(' + identifier + '|[*])')
 42 };
 43 
 44 /**
 45  * 用于匹配CSS属性转义字符
 46  *
 47  * @type {RegExp}
 48  */
 49 var runescape = new RegExp('\\\\([\\da-f]{1,6}' + whitespace + '?|(' + whitespace + ')|.)', 'ig');
 50 
 51 /**
 52  * 用于处理CSS属性转义字符的替换函数
 53  *
 54  * @param {*} _ 此参数仅占位
 55  * @param {string} escaped 转义后的字符
 56  * @param {string} escapedWhitespace 是否转义
 57  * @return {*} 返回处理结果
 58  */
 59 var funescape = function (_, escaped, escapedWhitespace) {
 60     var high = '0x' + escaped - 0x10000;
 61 
 62     // NaN表示不转义
 63     if (isNaN(high) || escapedWhitespace) {
 64         return escaped;
 65     }
 66 
 67     if (high < 0) {
 68         return String.fromCharCode(high + 0x10000);
 69     }
 70 
 71     return String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00);
 72 };
 73 
 74 
 75 /**
 76  * 解码CSS属性转义字符
 77  *
 78  * @param {string} str 要解码的字符串
 79  * @return {string} 解码后的字符串
 80  */
 81 function unescape(str) {
 82     return str.replace(runescape, funescape);
 83 }
 84 
 85 /**
 86  * 对选择器进行词法分析
 87  *
 88  * @param {string} selector 选择器字符串
 89  * @return {Array|null} 如果为空表示解析失败
 90  */
 91 function tokenize(selector) {
 92 
 93     var tokens = [];
 94 
 95     while (selector) {
 96 
 97         var matched = false;
 98 
 99         // 处理基本选择器
100         for (var type in expr) {
101 
102             var match;
103             if (expr.hasOwnProperty(type) && (match = expr[type].exec(selector))) {
104 
105                 matched = match.shift();
106 
107                 tokens.push({
108                     matched: matched,
109                     value: match,
110                     type: type
111                 });
112 
113                 selector = selector.slice(matched.length);
114             }
115         }
116 
117         if (!matched) {
118             break;
119         }
120     }
121 
122     if (selector) {
123         throw new Error(selector + '解析失败');
124     }
125 
126     return  tokens;
127 }
128 
129 /**
130  * 进行兼容性检测
131  *
132  * @type {Object}
133  */
134 var support = (function () {
135 
136     var support = {};
137 
138     // 检查IE9以下不支持getElementsByClassName的问题
139     support.getByClass = !!document.getElementsByClassName;
140 
141     // 检查IE67getElementById会返回Name的问题
142     var div = document.createElement('div');
143     var expando = 'selector-' + new Date().getTime();
144     document.body.appendChild(div).id = expando;
145     support.getById = !document.getElementsByName(expando).length;
146 
147     // 释放多余的元素
148     document.body.removeChild(div);
149     div = null;
150 
151     return support;
152 })();
153 
154 /**
155  * 用于生成过滤器的函数
156  *
157  * @type {Object}
158  */
159 var filter = {
160 
161     /**
162      * 类选择器
163      *
164      * @param {string} className 类名
165      * @return {Function} 过滤函数
166      */
167     'CLASS': function (className) {
168 
169         var pattern = new RegExp('(^|' + whitespace + ')' + className + '(' + whitespace + '|$)');
170 
171         return  function (elem) {
172             return pattern.test(typeof elem.className === 'string' && elem.className || '');
173         };
174     },
175 
176     /**
177      * ID选择器
178      *
179      * @param {string} id 要匹配的ID
180      * @return {Function} 过滤函数
181      */
182     'ID': support.getById ? function (id) {
183 
184         var attrId = unescape(id);
185 
186         return function (elem) {
187             return elem.getAttribute('id') === attrId;
188         };
189     } : function (id) {
190 
191         var attrId = unescape(id);
192 
193         return function (elem) {
194             var node;
195             return (node = elem.getAttributeNode('id')) && node.value === attrId;
196         };
197     },
198 
199     /**
200      * 标签选择器
201      *
202      * @param {string} nodeNameSelector 要过滤的标签名
203      * @return {Function} 过滤函数
204      */
205     'TAG': function (nodeNameSelector) {
206 
207         var nodeName = unescape(nodeNameSelector).toLowerCase();
208 
209         return nodeNameSelector === '*' ? function () {
210             return true;
211         } : function (elem) {
212             return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
213         };
214     }
215 
216 };
217 
218 /**
219  * 将当前一个匹配数组打包成一个匹配函数
220  *
221  * @param {Array} matchers 匹配数组
222  * @return {Function} 匹配函数
223  */
224 function elementMatcher(matchers) {
225 
226     if (matchers.length > 1) {
227 
228         return function (elem, context) {
229             var i = matchers.length;
230             while (i--) {
231                 if (!matchers[i](elem, context)) {
232                     return false;
233                 }
234             }
235             return true;
236         };
237     }
238 
239     return matchers[0];
240 }
241 
242 /**
243  * 使用一组token生成一个匹配函数
244  *
245  * @param {Array} tokens 一组token
246  * @return {Function}
247  */
248 function tokenMatcher(tokens) {
249 
250     var matchers = [];
251 
252     for (var i = 0, len = tokens.length; i < len; i++) {
253         matchers.push(filter[tokens[i].type].apply(null, tokens[i].value));
254     }
255 
256     return elementMatcher(matchers);
257 }
258 
259 /**
260  * 合并两个数组或类数组到第一个数组
261  *
262  * @param {Array} target 数组或类数组
263  * @param {Array} args 数组或类数组
264  * @return {*} 返回first
265  */
266 function merge(target, args) {
267     target = target || [];
268 
269     var i = 1;
270 
271     // 只传进来target时候直接返回target
272     if (arguments.length === i) {
273         return target;
274     }
275 
276     var l = target.length;
277 
278     for (; i < arguments.length; i++) {
279         args = arguments[i];
280 
281         if (args != null) {
282             var len = +args.length;
283             var j = 0;
284 
285             while (j < len) {
286                 target[l++] = args[j++];
287             }
288 
289             // 修复IE8下可能造成length失效的问题
290             if (isNaN(len)) {
291                 while (args[j] !== undefined) {
292                     target[l++] = args[j++];
293                 }
294             }
295         }
296     }
297 
298     target.length = l;
299 
300     return target;
301 
302 }
303 
304 /**
305  * 使用选择器找出相关的元素
306  *
307  * @param {string} selector 选择器字符串
308  * @param {HTMLElement|HTMLDocument} [context] 上下文对象
309  * @return {Array} 查询结果
310  */
311 function query(selector, context) {
312 
313     var results = [];
314     context = context || document;
315 
316     if (!selector || typeof selector !== 'string') {
317         return results;
318     }
319 
320     // 如果context不存在,表示查询非法
321     var nodeType;
322     if ((nodeType = context.nodeType) !== 1 && nodeType !== 9) {
323         return results;
324     }
325 
326     // 处理单标签的情况
327     var match;
328     if ((match = rquickExpr.exec(selector))) {
329 
330         var m;
331         // 处理selector是ID的情况
332         if ((m = match[1])) {
333             var elem;
334             if (nodeType === 9) {
335                 if ((elem = context.getElementById(m)) && elem.id === m) {
336                     results.push(elem);
337                     return results;
338                 }
339             }
340             else {
341                 if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m))
342                     && contains(context, elem) && elem.id === m) {
343 
344                     results.push(elem);
345                     return results;
346                 }
347             }
348         }
349         // 匹配selector是TAG的情况
350         else if (match[2]) {
351             return merge(results, context.getElementsByTagName(selector));
352         }
353         // 匹配selector是CLASS的情况
354         else if ((m = match[3]) && support.getByClass) {
355             return merge(results, context.getElementsByClassName(m));
356         }
357     }
358 
359     var seed = [];
360     var found = false;
361     var tokens = tokenize(selector);
362 
363     for (var i = 0, l = tokens.length; i < l && !found; i++) {
364         var token = tokens[i];
365         if (support.getByClass && token.type === 'CLASS') {
366             merge(seed, context.getElementsByClassName(token.value[0]));
367             found = true;
368         }
369         else if (support.getById && token.type === 'ID' && context.nodeType === 9) {
370             var ele = document.getElementById(token.value[0]);
371             ele && seed.push(ele);
372             found = true;
373         }
374         else if (token.type === 'TAG') {
375             seed = context.getElementsByTagName(token.value[0]);
376             found = true;
377         }
378     }
379 
380     !found && merge(seed, context.getElementsByTagName('*'));
381 
382     if (!seed.length) {
383         return results;
384     }
385 
386     var matcher = tokenMatcher(tokens);
387 
388     for (var j = 0, len = seed.length; j !== len && (elem = seed[j]) != null; j++) {
389         if (elem && elem.nodeType === 1 && matcher(elem, context)) {
390             results.push(elem);
391         }
392     }
393 
394     return results;
395 }

 

 

 

 

 

 
posted @ 2015-02-15 17:26  青青flye  阅读(259)  评论(0编辑  收藏  举报