收集的前端面试题和答案
转载请注明出处: https://github.com/qiu-deqing/FE-interview
Table of Contents generated with DocToc
的
title和
alt有什么区别
display: none;与
visibility: hidden;的区别
link与
@import的区别
display: block;和
display: inline;的区别
个人收集的前端知识点、面试题和答案,参考答案仅代表个人观点,方便复习,目录如下,通过文档内搜索目录可快速定位章节
的
title和
alt有什么区别
title是global attributes之一,用于为元素提供附加的 advisory information。通常当鼠标滑动到元素上的时候显示。
alt是
的特有属性,是图片内容的等价描述,用于图片无法加载时显示、读屏器阅读图片。可提图片高可访问性,除了纯装饰图片外都必须设置有意义的值,搜索引擎会重点分析。
声明必须处于 HTML 文档的头部,在标签之前,HTML5 中不区分大小写
声明不是一个 HTML 标签,是一个用于告诉浏览器当前 HTMl 版本的指令
声明指向一个 DTD,由于 HTML4.01 基于 SGML,所以 DTD 指定了标记规则以保证浏览器正确渲染内容
常见 dotype:
参考资料:MDN: html global attribute或者W3C HTML global-attributes
accesskey:设置快捷键,提供快速访问元素如aaa在 windows 下的 firefox 中按
alt + shift + a可激活元素
class:为元素设置类标识,多个类名用空格分开,CSS 和 javascript 可通过 class 属性获取元素
contenteditable: 指定元素内容是否可编辑
contextmenu: 自定义鼠标右键弹出菜单内容
data-*: 为元素增加自定义属性
dir: 设置元素文本方向
draggable: 设置元素是否可拖拽
dropzone: 设置元素拖放类型: copy, move, link
hidden: 表示一个元素是否与文档。样式上会导致元素不显示,但是不能用这个属性实现样式效果
id: 元素 id,文档内唯一
lang: 元素内容的的语言
spellcheck: 是否启动拼写和语法检查
style: 行内 css 样式
tabindex: 设置元素可以获得焦点,通过 tab 可以导航
title: 元素相关的建议信息
translate: 元素和子孙节点内容是否需要本地化
web 语义化是指通过 HTML 标记表示页面包含的信息,包含了 HTML 标签的语义化和 css 命名的语义化。 HTML 标签的语义化是指:通过使用包含语义的标签(如 h1-h6)恰当地表示文档结构 css 命名的语义化是指:为 html 标签添加有意义的 class,id 补充未表达的语义,如Microformat通过添加符合规则的 class 描述信息 为什么需要语义化:
Expires和
Cache-Control:
script,
meta这样本身不可见的标签。2)被 css 隐藏的节点,如
display: none
rfc2616中进行了定义:
GET /Protocols/rfc2616/rfc2616-sec5.html HTTP/1.1 Host: www.w3.org Connection: keep-alive Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 Referer: https://www.google.com.hk/ Accept-Encoding: gzip,deflate,sdch Accept-Language: zh-CN,zh;q=0.8,en;q=0.6 Cookie: authorstyle=yes If-None-Match: "2cc8-3e3073913b100" If-Modified-Since: Wed, 01 Sep 2004 13:24:52 GMTname=qiu&age=25
rfc2616中进行了定义:
HTTP/1.1 200 OK Date: Tue, 08 Jul 2014 05:28:43 GMT Server: Apache/2 Last-Modified: Wed, 01 Sep 2004 13:24:52 GMT ETag: "40d7-3e3073913b100" Accept-Ranges: bytes Content-Length: 16599 Cache-Control: max-age=21600 Expires: Tue, 08 Jul 2014 11:28:43 GMT P3P: policyref="http://www.w3.org/2001/05/P3P/p3p.xml" Content-Type: text/html; charset=iso-8859-1{"name": "qiu", "age": 25}
雅虎 Best Practices for Speeding Up Your Web Site:
渐进增强是指在 web 设计时强调可访问性、语义化 HTML 标签、外部样式表和脚本。保证所有人都能访问页面的基本内容和功能同时为高级浏览器和高带宽用户提供更好的用户体验。核心原则如下:
参考RFC 2616
概念:将多个小图片拼接到一个图片中。通过 background-position 和元素尺寸调节需要显示的背景图案。
优点:
缺点:
display: none;与
visibility: hidden;的区别
联系:它们都能让元素不可见
区别:
原理:利用不同浏览器对 CSS 的支持和解析结果不一样编写针对特定浏览器样式。常见的 hack 有 1)属性 hack。2)选择器 hack。3)IE 条件注释
/***** Selector Hacks ******//* IE6 and below */
/* IE7 */ *:first-child + html #dos { color: red; }
/* IE7, FF, Saf, Opera */ html > body #tres { color: red; }
/* IE8, FF, Saf, Opera (Everything but IE 6,7) */ html>/**/body #cuatro { color: red; }
/* Opera 9.27 and below, safari 2 */ html:first-child #cinco { color: red; }
/* Safari 2-3 / html[xmlns=''] body:last-child #seis { color: red; }
/* safari 3+, chrome 1+, opera9+, ff 3.5+ */ body:nth-of-type(1) #siete { color: red; }
/* safari 3+, chrome 1+, opera9+, ff 3.5+ */ body:first-of-type #ocho { color: red; }
/* saf3+, chrome1+ */ @media screen and (-webkit-min-device-pixel-ratio: 0) { #diez { color: red; } }
/* iPhone / mobile webkit */ @media screen and (max-device-width: 480px) { #veintiseis { color: red; } }
/* Safari 2 - 3.1 / html[xmlns='']:root #trece { color: red; }
/* Safari 2 - 3.1, Opera 9.25 */ |html[xmlns=''] #catorce { color: red; }
/* Everything but IE6-8 */ :root * > #quince { color: red; }
/* IE7 */
/* Firefox only. 1+ */ #veinticuatro, x:-moz-any-link { color: red; }
/* Firefox 3.0+ */ #veinticinco, x:-moz-any-link, x:default { color: red; }
/* IE6 */ #once { _color: blue }/* IE6, IE7 */ #doce { color: blue; / or #color: blue */ }
/* Everything but IE6 */ #diecisiete { color/**/: blue }
/* IE6, IE7, IE8 */ #diecinueve { color: blue\9; }
/* IE7, IE8 / #veinte { color/\/: blue\9; }
/* IE6, IE7 -- acts as an !important / #veintesiete { color: blue !ie; } / string after ! can be anything */
computed value: 以 specified value 根据规范定义的行为进行计算,通常将相对值计算为绝对值,例如 em 根据 font-size 进行计算。一些使用百分数并且需要布局来决定最终值的属性,如 width,margin。百分数就直接作为 computed value。line-height 的无单位值也直接作为 computed value。这些值将在计算 used value 时得到绝对值。computed value 的主要作用是用于继承
used value:属性计算后的最终值,对于大多数属性可以通过 window.getComputedStyle 获得,尺寸值单位为像素。以下属性依赖于布局,
link与
@import的区别
link是 HTML 方式,
@import是 CSS 方式
link最大限度支持并行下载,
@import过多嵌套导致串行下载,出现FOUC
link可以通过
rel="alternate stylesheet"指定候选样式
link支持早于
@import,可以使用
@import对老浏览器隐藏样式
@import必须在样式规则之前,可以在 css 文件中引用其他文件
display: block;和
display: inline;的区别
block元素特点:
1.处于常规流中时,如果
width没有设置,会自动填充满父容器 2.可以应用
margin/padding3.在没有设置高度的情况下会扩展高度以包含常规流中的子元素 4.处于常规流中时布局时在前后元素位置之间(独占一个水平空间) 5.忽略
vertical-align
inline元素特点
1.水平方向上根据
direction依次布局 2.不会在元素前后进行换行 3.受
white-space控制 4.
margin/padding在竖直方向上无效,水平方向上有效 5.
width/height属性对非替换行内元素无效,宽度由元素内容决定 6.非替换行内元素的行框高由
line-height确定,替换行内元素的行框高由
height,
margin,
padding,
border决定 6.浮动或绝对定位时会转换为
block7.
vertical-align属性生效
参考资料: 选择正确的图片格式 GIF:
JPEG:
PNG:
.target { min-height: 100px; height: auto !important; height: 100px; // IE6下内容高度超过会自动扩展高度 }
ol内
li的序号全为 1,不递增。解决方法:为 li 设置样式
display: list-item;
未定位父元素
overflow: auto;,包含
position: relative;子元素,子元素高于父元素时会溢出。解决办法:1)子元素去掉
position: relative;; 2)不能为子元素去掉定位时,父元素
position: relative;
a标签的
:hover伪类,解决方法:使用 js 为元素监听 mouseenter,mouseleave 事件,添加类实现效果:
aaaa bbbbbDDDDDDDDDDDd aaaa lkjlkjdf j
opacity,解决办法:
.opacity { opacity: 0.4 filter: alpha(opacity=60); /* for IE5-7 */ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; /* for IE 8*/ }
height小于
font-size时高度值为
font-size,解决办法:
font-size: 0;
display: inline-block解决办法:设置 inline 并触发 hasLayout
display: inline-block; *display: inline; *zoom: 1;
display: inline;这样解决问题且无任何副作用:css 标准规定浮动元素 display:inline 会自动调整为 block
text-align: center;
clear: both
/** * 在标准浏览器下使用 * 1 content内容为空格用于修复opera下文档中出现 * contenteditable属性时在清理浮动元素上下的空白 * 2 使用display使用table而不是block:可以防止容器和 * 子元素top-margin折叠,这样能使清理效果与BFC,IE6/7 * zoom: 1;一致 **/.clearfix:before, .clearfix:after { content: " "; /* 1 / display: table; / 2 */ }
.clearfix:after { clear: both; }
/**
Flash Of Unstyled Content:用户定义样式表加载之前浏览器使用默认样式显示文档,用户样式加载渲染之后再从新显示文档,造成页面闪烁。解决方法:把样式表放到文档的
head
创建规则:
float不是
none)
position取值为
absolute或
fixed)
display取值为
inline-block,
table-cell,
table-caption,
flex,
inline-flex之一的元素
overflow不是
visible的元素
作用:
display为 none,那么 position 和 float 都不起作用,这种情况下元素不产生框
display
毗邻的两个或多个
margin会合并成一个 margin,叫做外边距折叠。规则如下:
position为
relative或者
static的元素,它的包含块由最近的块级(
display为
block,
list-item,
table)祖先元素的内容框组成
position为
fixed。对于连续媒体,它的包含块为 viewport;对于 paged media,包含块为 page area
position为
absolute,它的包含块由祖先元素中最近一个
position为
relative,
absolute或者
fixed的元素产生,规则如下:
如果找不到定位的祖先元素,包含块为初始包含块
z 轴上的默认层叠顺序如下(从下到上):
如何创建 stacking context:
text-align: center;即可实现
text-align: center;,再给子元素恢复需要的值
aaaaaa aaaaaa a a a a a a a a
position: relative;,3)浮动方向偏移量(left 或者 right)设置为 50%,4)浮动方向上的 margin 设置为元素宽度一半乘以-1
aaaaaa aaaaaa a a a a a a a a
aaaaaa aaaaaa a a a a a a a a
aaaaaa aaaaaa a a a a a a a a
参考资料:6 Methods For Vertical Centering With CSS。 盘点 8 种 CSS 实现垂直居中
font-size的
line-height:
center text
link中 href 属性,转换成 property 的时候需要通过转换得到完整 URL
Measuring Element Dimension and Location with CSSOM in Windows Internet Explorer 9
readyState:表示请求状态的整数,取值:
onreadystatechange:readyState 改变时调用的函数
status:服务器返回的 HTTP 状态码(如,200, 404)
statusText:服务器返回的 HTTP 状态信息(如,OK,No Content)
responseText:作为字符串形式的来自服务器的完整响应
responseXML: Document 对象,表示服务器的响应解析成的 XML 文档
abort():取消异步 HTTP 请求
getAllResponseHeaders(): 返回一个字符串,包含响应中服务器发送的全部 HTTP 报头。每个报头都是一个用冒号分隔开的名/值对,并且使用一个回车/换行来分隔报头行
getResponseHeader(headerName):返回 headName 对应的报头值
open(method, url, asynchronous [, user, password]):初始化准备发送到服务器上的请求。method 是 HTTP 方法,不区分大小写;url 是请求发送的相对或绝对 URL;asynchronous 表示请求是否异步;user 和 password 提供身份验证
setRequestHeader(name, value):设置 HTTP 报头
send(body):对服务器请求进行初始化。参数 body 包含请求的主体部分,对于 POST 请求为键值对字符串;对于 GET 请求,为 null
tabindex属性的元素被点击或键盘操作
例子:鼠标从 div#target 元素移出时进行处理,判断逻辑如下:
test
同源:两个文档同源需满足
跨域通信:js 进行 DOM 操作、通信时如果目标与当前窗口不满足同源条件,浏览器为了安全会阻止跨域操作。跨域通信通常有以下方法
,,,元素,通过 src,href 属性设置为目标 url。实现跨域请求
Access-Control-Allow-Origin: *即可像普通 ajax 一样访问跨域资源
六种基本数据类型
一种引用类型
闭包是在某个作用域内定义的函数,它可以访问这个作用域内的所有变量。闭包作用域链通常包括三个部分:
闭包常见用途:
重要参考资料:MDN:Functionsandfunction_scope
HTML5 新增应用程序缓存,允许 web 应用将应用程序自身保存到用户浏览器中,用户离线状态也能访问。 1.为 html 元素设置 manifest 属性:
,其中后缀名只是一个约定,真正识别方式是通过text/cache-manifest作为 MIME 类型。所以需要配置服务器保证设置正确 2.manifest 文件首行为
CACHE MANIFEST,其余就是要缓存的 URL 列表,每个一行,相对路径都相对于 manifest 文件的 url。注释以#开头 3.url 分为三种类型:
CACHE:为默认类型。
NETWORK:表示资源从不缓存。
FALLBACK:每行包含两个 url,第二个 URL 是指需要加载和存储在缓存中的资源, 第一个 URL 是一个前缀。任何匹配该前缀的 URL 都不会缓存,如果从网络中载入这样的 URL 失败的话,就会用第二个 URL 指定的缓存资源来替代。以下是一个文件例子:
CACHE MANIFESTCACHE: myapp.html myapp.css myapp.js
FALLBACK: videos/ offline_help.html
NETWORK: cgi/
localStorage.setItem('x', 1); // storge x->1 localStorage.getItem('x); // return value of x// 枚举所有存储的键值对 for (var i = 0, len = localStorage.length; i < len; ++i ) { var name = localStorage.key(i); var value = localStorage.getItem(name); }
localStorage.removeItem('x'); // remove x localStorage.clear(); // remove all data
document.cookie = 'name=qiu; max-age=9999; path=/; domain=domain; secure';document.cookie = 'name=aaa; path=/; domain=domain; secure'; // 要改变cookie的值,需要使用相同的名字、路径和域,新的值 // 来设置cookie,同样的方法可以用来改变有效期
// 设置max-age为0可以删除指定cookie
//读取cookie,访问document.cookie返回键值对组成的字符串, //不同键值对之间用'; '分隔。通过解析获得需要的值
cookieUtil.js:自己写的 cookie 操作工具
var obj = {};
var obj = new Object();
var obj = Object.create(Object.prototype);
1. 如果对象有valueOf()方法并且返回元素值,javascript将返回值转换为数字作为结果 2. 否则,如果对象有toString()并且返回原始值,javascript将返回结果转换为数字作为结果 3. 否则,throws a TypeError
所有比较运算符都支持任意类型,但是比较只支持数字和字符串,所以需要执行必要的转换然后进行比较,转换规则如下:
var args = Array.prototype.slice.call(arguments, 0);
/** * 跨浏览器事件处理工具。只支持冒泡。不支持捕获 * @author ([email protected]) */var EventUtil = { getEvent: function (event) { return event || window.event; }, getTarget: function (event) { return event.target || event.srcElement; }, // 返回注册成功的监听器,IE中需要使用返回值来移除监听器 on: function (elem, type, handler) { if (elem.addEventListener) { elem.addEventListener(type, handler, false); return handler; } else if (elem.attachEvent) { var wrapper = function () { var event = window.event; event.target = event.srcElement; handler.call(elem, event); }; elem.attachEvent('on' + type, wrapper); return wrapper; } }, off: function (elem, type, handler) { if (elem.removeEventListener) { elem.removeEventListener(type, handler, false); } else if (elem.detachEvent) { elem.detachEvent('on' + type, handler); } }, preventDefault: function (event) { if (event.preventDefault) { event.preventDefault(); } else if ('returnValue' in event) { event.returnValue = false; } }, stopPropagation: function (event) { if (event.stopPropagation) { event.stopPropagation(); } else if ('cancelBubble' in event) { event.cancelBubble = true; } }, /** * keypress事件跨浏览器获取输入字符 * 某些浏览器在一些特殊键上也触发keypress,此时返回null **/ getChar: function (event) { if (event.which == null) { return String.fromCharCode(event.keyCode); // IE } else if (event.which != 0 && event.charCode != 0) { return String.fromCharCode(event.which); // the rest } else { return null; // special key } } };
function Shape() {}function Rect() {}
// 方法1 Rect.prototype = new Shape();
// 方法2 Rect.prototype = Shape.prototype;
// 方法3 Rect.prototype = Object.create(Shape.prototype);
Rect.prototype.area = function () { // do something };
方法 1:
方法 2:
方法 3:
改进:
function Rect() { Shape.call(this); }
Rect.prototype.constructor = Rect;保证一致性
function create(obj) { if (Object.create) { return Object.create(obj); }function f() {}; f.prototype = obj; return new f();
}
var days = ['日','一','二','三','四','五','六']; var date = new Date();console.log('今天是星期' + days[date.getDay()]);
for (var i = 0; i < 5; ++i) { setTimeout(function () { console.log(i + ' '); }, 100); }
不能输出正确结果,因为循环中 setTimeout 接受的参数函数通过闭包访问变量 i。javascript 运行环境为单线程,setTimeout 注册的函数需要等待线程空闲才能执行,此时 for 循环已经结束,i 值为 5.五个定时输出都是 5 修改方法:将 setTimeout 放在函数立即调用表达式中,将 i 值作为参数传递给包裹函数,创建新闭包
for (var i = 0; i < 5; ++i) { (function (i) { setTimeout(function () { console.log(i + ' '); }, 100); }(i)); }
function Page() {}Page.prototype = { constructor: Page,
postA: function (a) { console.log('a:' + a); }, postB: function (b) { console.log('b:' + b); }, postC: function (c) { console.log('c:' + c); }, check: function () { return Math.random() > 0.5; } }
function checkfy(obj) { for (var key in obj) { if (key.indexOf('post') === 0 && typeof obj[key] === 'function') { (function (key) { var fn = obj[key]; obj[key] = function () { if (obj.check()) { fn.apply(obj, arguments); } }; }(key)); } } } // end checkfy()
checkfy(Page.prototype);
var obj = new Page();
obj.postA('checkfy'); obj.postB('checkfy'); obj.postC('checkfy');
function deepClone(obj) { var _toString = Object.prototype.toString;// null, undefined, non-object, function if (!obj || typeof obj !== 'object') { return obj; } // DOM Node if (obj.nodeType && 'cloneNode' in obj) { return obj.cloneNode(true); } // Date if (_toString.call(obj) === '[object Date]') { return new Date(obj.getTime()); } // RegExp if (_toString.call(obj) === '[object RegExp]') { var flags = []; if (obj.global) { flags.push('g'); } if (obj.multiline) { flags.push('m'); } if (obj.ignoreCase) { flags.push('i'); } return new RegExp(obj.source, flags.join('')); } var result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : {}; for (var key in obj ) { result[key] = deepClone(obj[key]); } return result;
}
function A() { this.a = a; }
var a = { name: 'qiu', birth: new Date(), pattern: /qiu/gim, container: document.body, hobbys: ['book', new Date(), /aaa/gim, 111] };
var c = new A(); var b = deepClone(c); console.log(c.a === b.a); console.log(c, b);
<meta charset="utf-8"> <title>TEst</title>
<meta charset="utf-8"> <title>TEst</title> <span id="target"></span>
如:[1, [2, [ [3, 4], 5], 6]] => [1, 2, 3, 4, 5, 6]
var data = [1, [2, [ [3, 4], 5], 6]];function flat(data, result) { var i, d, len; for (i = 0, len = data.length; i < len; ++i) { d = data[i]; if (typeof d === 'number') { result.push(d); } else { flat(d, result); } } } var result = []; flat(data, result); console.log(result);
如果浏览器支持 Array.isArray()可以直接判断否则需进行必要判断
/** * 判断一个对象是否是数组,参数不是对象或者不是数组,返回false * * @param {Object} arg 需要测试是否为数组的对象 * @return {Boolean} 传入参数是数组返回true,否则返回false */ function isArray(arg) { if (typeof arg === 'object') { return Object.prototype.toString.call(arg) === '[object Array]'; } return false; }
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); }); }; }
作用:浏览器功能检测实现跨浏览器 DOM 事件绑定
优点:
listener.apply(el)解决 IE 下监听器 this 与标准不一致的地方
缺点:
listener.apply使 this 与标准一致但监听器无法移除
改进:
var addListener;if (window.addEventListener) { addListener = function (el, type, listener, useCapture) { el.addEventListener(type, listener, useCapture); return listener; }; } else if (window.attachEvent) { addListener = function (el, type, listener) { // 标准化this,event,target var wrapper = function () { var event = window.event; event.target = event.srcElement; listener.call(el, event); };
el.attachEvent('on' + type, wrapper); return wrapper; // 返回wrapper。调用者可以保存,以后remove
}; }
/** * 判断对象是否为函数,如果当前运行环境对可调用对象(如正则表达式) * 的typeof返回'function',采用通用方法,否则采用优化方法 * * @param {Any} arg 需要检测是否为函数的对象 * @return {boolean} 如果参数是函数,返回true,否则false */ function isFunction(arg) { if (arg) { if (typeof (/./) !== 'function') { return typeof arg === 'function'; } else { return Object.prototype.toString.call(arg) === '[object Function]'; } } // end if return false; }
/** * 解析query string转换为对象,一个key有多个值时生成数组 * * @param {String} query 需要解析的query字符串,开头可以是?, * 按照application/x-www-form-urlencoded编码 * @return {Object} 参数解析后的对象 */ function parseQuery(query) { var result = {};// 如果不是字符串返回空对象 if (typeof query !== 'string') { return result; } // 去掉字符串开头可能带的? if (query.charAt(0) === '?') { query = query.substring(1); } var pairs = query.split('&'); var pair; var key, value; var i, len; for (i = 0, len = pairs.length; i < len; ++i) { pair = pairs[i].split('='); // application/x-www-form-urlencoded编码会将' '转换为+ key = decodeURIComponent(pair[0]).replace(/\+/g, ' '); value = decodeURIComponent(pair[1]).replace(/\+/g, ' '); // 如果是新key,直接添加 if (!(key in result)) { result[key] = value; } // 如果key已经出现一次以上,直接向数组添加value else if (isArray(result[key])) { result[key].push(value); } // key第二次出现,将结果改为数组 else { var arr = [result[key]]; arr.push(value); result[key] = arr; } // end if-else } // end for return result;
}
function isArray(arg) { if (arg && typeof arg === 'object') { return Object.prototype.toString.call(arg) === '[object Array]'; } return false; } /** console.log(parseQuery('sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8')); */
/** * 解析一个url并生成window.location对象中包含的域 * location: * { * href: '包含完整的url', * origin: '包含协议到pathname之前的内容', * protocol: 'url使用的协议,包含末尾的:', * username: '用户名', // 暂时不支持 * password: '密码', // 暂时不支持 * host: '完整主机名,包含:和端口', * hostname: '主机名,不包含端口' * port: '端口号', * pathname: '服务器上访问资源的路径/开头', * search: 'query string,?开头', * hash: '#开头的fragment identifier' * } * * @param {string} url 需要解析的url * @return {Object} 包含url信息的对象 */ function parseUrl(url) { var result = {}; var keys = ['href', 'origin', 'protocol', 'host', 'hostname', 'port', 'pathname', 'search', 'hash']; var i, len; var regexp = /(([^:]+:)\/\/(([^:\/\?#]+)(:\d+)?))(\/[^?#]*)?(\?[^#]*)?(#.*)?/;var match = regexp.exec(url); if (match) { for (i = keys.length - 1; i >= 0; --i) { result[keys[i]] = match[i] ? match[i] : ''; } } return result;
}
/** * 查询指定窗口的视口尺寸,如果不指定窗口,查询当前窗口尺寸 **/ function getViewportSize(w) { w = w || window;// IE9及标准浏览器中可使用此标准方法 if ('innerHeight' in w) { return { width: w.innerWidth, height: w.innerHeight }; } var d = w.document; // IE 8及以下浏览器在标准模式下 if (document.compatMode === 'CSS1Compat') { return { width: d.documentElement.clientWidth, height: d.documentElement.clientHeight }; } // IE8及以下浏览器在怪癖模式下 return { width: d.body.clientWidth, height: d.body.clientHeight };
}
/** * 获取指定window中滚动条的偏移量,如未指定则获取当前window * 滚动条偏移量 * * @param {window} w 需要获取滚动条偏移量的窗口 * @return {Object} obj.x为水平滚动条偏移量,obj.y为竖直滚动条偏移量 */ function getScrollOffset(w) { w = w || window; // 如果是标准浏览器 if (w.pageXOffset != null) { return { x: w.pageXOffset, y: w.pageYOffset }; }// 老版本IE,根据兼容性不同访问不同元素 var d = w.document; if (d.compatMode === 'CSS1Compat') { return { x: d.documentElement.scrollLeft, y: d.documentElement.scrollTop } } return { x: d.body.scrollLeft, y: d.body.scrollTop };
}
function richText(text) { var div = document.createElement('div'); div.innerHTML = text; var p = div.getElementsByTagName('p'); var i, len;for (i = 0, len = p.length; i < len; ++i) { if (p[i].getElementsByTagName('img').length === 1) { p[i].classList.add('pic'); } } return div.innerHTML;
}
function Event() { if (!(this instanceof Event)) { return new Event(); } this._callbacks = {}; } Event.prototype.on = function (type, handler) { this_callbacks = this._callbacks || {}; this._callbacks[type] = this.callbacks[type] || []; this._callbacks[type].push(handler);return this;
};
Event.prototype.off = function (type, handler) { var list = this._callbacks[type];
if (list) { for (var i = list.length; i >= 0; --i) { if (list[i] === handler) { list.splice(i, 1); } } } return this;
};
Event.prototype.trigger = function (type, data) { var list = this._callbacks[type];
if (list) { for (var i = 0, len = list.length; i < len; ++i) { list[i].call(this, data); } }
};
Event.prototype.once = function (type, handler) { var self = this;
function wrapper() { handler.apply(self, arguments); self.off(type, wrapper); } this.on(type, wrapper); return this;
};
// define (function (window) { function fn(str) { this.str = str; }fn.prototype.format = function () { var arg = __1__; return this.str.replace(__2__, function (a, b) { return arg[b] || ''; }); }; window.fn = fn;
})(window);
// use (function () { var t = new fn('
{1}{2}
'); console.log(t.format('http://www.alibaba.com', 'Alibaba', 'Welcome')); })();
define 部分定义一个简单的模板类,使用{}作为转义标记,中间的数字表示替换目标,format 实参用来替换模板内标记 横线处填:
Array.prototype.slice.call(arguments, 0)
/\{\s*(\d+)\s*\}/g
Object: { "index": 1, "name": "111", "link": "http://1111" }
script:
var EventUtil = { getEvent: function (event) { return event || window.event; }, getTarget: function (event) { return event.target || event.srcElement; }, // 返回注册成功的监听器,IE中需要使用返回值来移除监听器 on: function (elem, type, handler) { if (elem.addEventListener) { elem.addEventListener(type, handler, false); return handler; } else if (elem.attachEvent) { function wrapper(event) { return handler.call(elem, event); }; elem.attachEvent('on' + type, wrapper); return wrapper; } }, off: function (elem, type, handler) { if (elem.removeEventListener) { elem.removeEventListener(type, handler, false); } else if (elem.detachEvent) { elem.detachEvent('on' + type, handler); } }, preventDefault: function (event) { if (event.preventDefault) { event.preventDefault(); } else if ('returnValue' in event) { event.returnValue = false; } }, stopPropagation: function (event) { if (event.stopPropagation) { event.stopPropagation(); } else if ('cancelBubble' in event) { event.cancelBubble = true; } } }; var DOMUtil = { text: function (elem) { if ('textContent' in elem) { return elem.textContent; } else if ('innerText' in elem) { return elem.innerText; } }, prop: function (elem, propName) { return elem.getAttribute(propName); } };var nav = document.getElementById('nav');
EventUtil.on(nav, 'click', function (event) { var event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event);
var children = this.children; var i, len; var anchor; var obj = {}; for (i = 0, len = children.length; i < len; ++i) { if (children[i] === target) { obj.index = i + 1; anchor = target.getElementsByTagName('a')[0]; obj.name = DOMUtil.text(anchor); obj.link = DOMUtil.prop(anchor, 'href'); } } alert('index: ' + obj.index + ' name: ' + obj.name + ' link: ' + obj.link);
});
/** * 数组去重 **/ function normalize(arr) { if (arr && Array.isArray(arr)) { var i, len, map = {}; for (i = arr.length; i >= 0; --i) { if (arr[i] in map) { arr.splice(i, 1); } else { map[arr[i]] = true; } } } return arr; }/** * 用100个随机整数对应的字符串填充数组。 **/ function fillArray(arr, start, end) { start = start == undefined ? 1 : start; end = end == undefined ? 100 : end; if (end <= start) { end = start + 100; } var width = end - start; var i; for (i = 100; i >= 1; --i) { arr.push('' + (Math.floor(Math.random() * width) + start)); } return arr; } var input = []; fillArray(input, 1, 100); input.sort(function (a, b) { return a - b; }); console.log(input); normalize(input); console.log(input);