转载请注明出处: [https://github.com/qiu-deqing...](https://github.com/qiu-deqing...javascript
我的收集的前端知识点、面试题和答案,参考答案仅表明我的观点,方便复习,目录以下,经过文档内搜索目录可快速定位章节css
html
常见 dotype:前端
参考资料:[MDN: html global attribute](https://developer.mozilla.org..._attributes)或者[W3C HTML global-attributes](http://www.w3.org/TR/html-mar...java
web 语义化是指经过 HTML 标记表示页面包含的信息,包含了 HTML 标签的语义化和 css 命名的语义化。
HTML 标签的语义化是指:经过使用包含语义的标签(如 h1-h6)恰当地表示文档结构
css 命名的语义化是指:为 html 标签添加有意义的 class,id 补充未表达的语义,如[Microformat](http://en.wikipedia.org/wiki/... class 描述信息
为何须要语义化:node
浏览器查看**缓存**,若是请求资源在缓存中而且新鲜,跳转到转码步骤git
检验新鲜一般有两个 HTTP 头进行控制`Expires`和`Cache-Control`:github
浏览器**获取主机 ip 地址**,过程以下:web
**打开一个 socket 与目标 IP 地址,端口创建 TCP 连接**,三次握手以下:面试
浏览器接收 HTTP 响应,而后根据状况选择**关闭 TCP 链接或者保留重用,关闭 TCP 链接的四次握手以下**:
**构建 DOM 树**:
构建**CSSOM 树**:
**[根据 DOM 树和 CSSOM 树构建渲染树](https://developers.google.com...**:
**js 解析以下**:

[rfc2616](http://www.w3.org/Protocols/r...:
```
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 GMT
name=qiu&age=25
```
[rfc2616](http://www.w3.org/Protocols/r...:
```
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](https://developer.yahoo.com/p...:
content 方面
Server 方面
Cookie 方面
css 方面
Javascript 方面
图片方面
移动方面
渐进加强是指在 web 设计时强调可访问性、语义化 HTML 标签、外部样式表和脚本。保证全部人都能访问页面的基本内容和功能同时为高级浏览器和高带宽用户提供更好的用户体验。核心原则以下:
参考[RFC 2616](http://www.w3.org/Protocols/r...
1XX:信息状态码
2XX:成功状态码
3XX:重定向
4XX:客户端错误
5XX: 服务器错误
概念:将多个小图片拼接到一个图片中。经过 background-position 和元素尺寸调节须要显示的背景图案。
优势:
缺点:
联系:它们都能让元素不可见
区别:
原理:利用**不一样浏览器对 CSS 的支持和解析结果不同**编写针对特定浏览器样式。常见的 hack 有 1)属性 hack。2)选择器 hack。3)IE 条件注释
```js
<!--[if IE 6]>
Special instructions for IE 6 here
<![endif]-->
```
```css
/***** Selector Hacks ******/
/* IE6 and below */
* html #uno {
color: red;
}
/* 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 */
* + html #dieciocho {
color: red;
}
/* Firefox only. 1+ */
x:-moz-any-link {
color: red;
}
/* Firefox 3.0+ */
x:-moz-any-link,
x:default {
color: red;
}
```
```
/* IE6 */
/* IE6, IE7 */
/* Everything but IE6 */
/* IE6, IE7, IE8 */
/* IE7, IE8 */
/* IE6, IE7 -- acts as an !important */
```
specified value: 计算方法以下:
used value:属性计算后的最终值,对于大多数属性能够经过 window.getComputedStyle 得到,尺寸值单位为像素。如下属性依赖于布局,
`block`元素特色:
1.处于常规流中时,若是`width`没有设置,会自动填充满父容器 2.能够应用`margin/padding` 3.在没有设置高度的状况下会扩展高度以包含常规流中的子元素 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.浮动或绝对定位时会转换为`block` 7.`vertical-align`属性生效
参考资料: [选择正确的图片格式](http://www.yuiblog.com/blog/2...
**GIF**:
**JPEG**:
**PNG**:
关于文字排版的属性如:
```
.target {
min-height: 100px; height: auto !important; height: 100px; // IE6下内容高度超过会自动扩展高度
}
```
```
<style type="text/css">
.outer {
width: 215px; height: 100px; border: 1px solid red; overflow: auto; position: relative; /\* 修复bug \*/
}
.inner {
width: 100px; height: 200px; background-color: purple; position: relative;
}
</style>
<div class="outer">
<div class="inner"></div>
</div>
```
```
<style type="text/css">
.p:hover,
.hover {
background: purple;
}
</style>
<p class="p" id="target">aaaa bbbbb<span>DDDDDDDDDDDd</span> aaaa lkjlkjdf j</p>
<script type="text/javascript">
function addClass(elem, cls) {
if (elem.className) { elem.className += ' ' + cls; } else { elem.className = cls; }
}
function removeClass(elem, cls) {
var className = ' ' + elem.className + ' '; var reg = new RegExp(' +' + cls + ' +', 'g'); elem.className = className.replace(reg, ' ').replace(/^ +| +$/, '');
}
var target = document.getElementById('target');
if (target.attachEvent) {
target.attachEvent('onmouseenter', function () { addClass(target, 'hover'); }); target.attachEvent('onmouseleave', function () { removeClass(target, 'hover'); })
}
</script>
```
```
.opacity {
opacity: 0.4 filter: alpha(opacity=60); /\* for IE5-7 \*/ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; /\* for IE 8\*/
}
```
```
display: inline-block; \*display: inline; \*zoom: 1;
```
```
/**
* 在标准浏览器下使用
* 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;
}
/**
* IE 6/7下使用
* 经过触发hasLayout实现包含浮动
**/
.clearfix {
\*zoom: 1;
}
```
Flash Of Unstyled Content:用户定义样式表加载以前浏览器使用默认样式显示文档,用户样式加载渲染以后再重新显示文档,形成页面闪烁。**解决方法**:把样式表放到文档的`head`
建立规则:
做用:
毗邻的两个或多个`margin`会合并成一个 margin,叫作外边距折叠。规则以下:
若是元素`position`为`absolute`,它的包含块由祖先元素中最近一个`position`为`relative`,`absolute`或者`fixed`的元素产生,规则以下:
若是找不到定位的祖先元素,包含块为**初始包含块**
z 轴上的默认层叠顺序以下(从下到上):
如何建立 stacking context:
```
<body>
<div class="content"> aaaaaa aaaaaa a a a a a a a a </div>
</body>
<style>
body { background: #DDD; text-align: center; /\* 3 \*/ } .content { width: 500px; /\* 1 \*/ text-align: left; /\* 3 \*/ margin: 0 auto; /\* 2 \*/ background: purple; }
</style>
```
```
<body>
<div class="content"> aaaaaa aaaaaa a a a a a a a a </div>
</body>
<style>
body { background: #DDD; } .content { width: 500px; /\* 1 \*/ float: left; position: relative; /\* 2 \*/ left: 50%; /\* 3 \*/ margin-left: -250px; /\* 4 \*/ background-color: purple; }
</style>
```
```
<body>
<div class="content"> aaaaaa aaaaaa a a a a a a a a </div>
</body>
<style>
body { background: #DDD; position: relative; } .content { width: 800px; position: absolute; left: 50%; margin-left: -400px; background-color: purple; }
</style>
```
```
<body>
<div class="content"> aaaaaa aaaaaa a a a a a a a a </div>
</body>
<style>
body { background: #DDD; position: relative; } .content { width: 800px; position: absolute; margin: 0 auto; left: 0; right: 0; background-color: purple; }
</style>
```
参考资料:[6 Methods For Vertical Centering With CSS](http://www.vanseodesign.com/c...。 [盘点 8 种 CSS 实现垂直居中](http://blog.csdn.net/freshlov...
```
<p class="text">center text</p>
<style>
.text {
line-height: 200px;
}
</style>
```
[Measuring Element Dimension and Location with CSSOM in Windows Internet Explorer 9](http://msdn.microsoft.com/en-...)

可得到焦点的元素:
例子:鼠标从 div#target 元素移出时进行处理,判断逻辑以下:
<div id="target"><span>test</span></div> <script type="text/javascript"> var target = document.getElementById('target'); if (target.addEventListener) { target.addEventListener('mouseout', mouseoutHandler, false); } else if (target.attachEvent) { target.attachEvent('onmouseout', mouseoutHandler); } function mouseoutHandler(e) { e = e || window.event; var target = e.target || e.srcElement; // 判断移出鼠标的元素是否为目标元素 if (target.id !== 'target') { return; } // 判断鼠标是移出元素仍是移到子元素 var relatedTarget = event.relatedTarget || e.toElement; while (relatedTarget !== target && relatedTarget.nodeName.toUpperCase() !== 'BODY') { relatedTarget = relatedTarget.parentNode; } // 若是相等,说明鼠标在元素内部移动 if (relatedTarget === target) { return; } // 执行须要操做 //alert('鼠标移出'); } </script>
同源:两个文档同源需知足
跨域通讯:js 进行 DOM 操做、通讯时若是目标与当前窗口不知足同源条件,浏览器为了安全会阻止跨域操做。跨域通讯一般有如下方法
六种基本数据类型
一种引用类型
**闭包是在某个做用域内定义的函数,它能够访问这个做用域内的全部变量**。闭包做用域链一般包括三个部分:
闭包常见用途:
重要参考资料:[MDN:Functions_and_function_scope](https://developer.mozilla.org..._and_function_scope)
HTML5 新增应用程序缓存,容许 web 应用将应用程序自身保存到用户浏览器中,用户离线状态也能访问。 1.为 html 元素设置 manifest 属性:`<html manifest="myapp.appcache">`,其中后缀名只是一个约定,真正识别方式是经过`text/cache-manifest`做为 MIME 类型。因此须要配置服务器保证设置正确
2.manifest 文件首行为`CACHE MANIFEST`,其他就是要缓存的 URL 列表,每一个一行,相对路径都相对于 manifest 文件的 url。注释以#开头
3.url 分为三种类型:`CACHE`:为默认类型。`NETWORK`:表示资源从不缓存。 `FALLBACK`:每行包含两个 url,第二个 URL 是指须要加载和存储在缓存中的资源, 第一个 URL 是一个前缀。任何匹配该前缀的 URL 都不会缓存,若是从网络中载入这样的 URL 失败的话,就会用第二个 URL 指定的缓存资源来替代。如下是一个文件例子:
```
CACHE MANIFEST
CACHE:
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](https://github.com/qiu-deqing...:本身写的 cookie 操做工具
1. 若是对象有valueOf()方法而且返回元素值,javascript将返回值转换为数字做为结果 2. 不然,若是对象有toString()而且返回原始值,javascript将返回结果转换为数字做为结果 3. 不然,throws a TypeError
全部比较运算符都支持任意类型,可是**比较只支持数字和字符串**,因此须要执行必要的转换而后进行比较,转换规则以下:
var args = Array.prototype.slice.call(arguments, 0);
```
/**
* 跨浏览器事件处理工具。只支持冒泡。不支持捕获
* @author (qiu_deqing@126.com)
*/
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);
}
```
```
function create(obj) {
if (Object.create) { return Object.create(obj); } function f() {}; f.prototype = obj; return new f();
}
```

```
<style>
width: 200px; height: 300px; margin: 40px; background-color: tomato;
}
</style>
<div id="target"></div>
<script>
function addMask(elem, opacity) {
opacity = opacity || 0.2; var rect = elem.getBoundingClientRect(); var style = getComputedStyle(elem, null); var mask = document.createElement('div'); mask.style.position = 'absolute'; var marginLeft = parseFloat(style.marginLeft); mask.style.left = (elem.offsetLeft - marginLeft) + 'px'; var marginTop = parseFloat(style.marginTop); mask.style.top = (elem.offsetTop - marginTop) + 'px'; mask.style.zIndex = 9999; mask.style.opacity = '' + opacity; mask.style.backgroundColor = '#000'; mask.style.width = (parseFloat(style.marginLeft) + parseFloat(style.marginRight) + rect.width) + 'px'; mask.style.height = (parseFloat(style.marginTop) + parseFloat(style.marginBottom) + rect.height) + 'px'; elem.parentNode.appendChild(mask);
}
var target = document.getElementById('target');
addMask(target);
target.addEventListener('click', function () {
console.log('click');
}, false);
</script>
```
```
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);
<!doctype html> <html> <head> <meta charset="utf-8"> <title>TEst</title> </head> <body> <div> <input type="button" id ="button1" value="1" /> <input type="button" id ="button2" value="2" /> </div> <script type="text/javascript"> var btn1 = document.getElementById('button1'); var btn2 = document.getElementById('button2'); addListener(btn1, 'click', function (event) { btn1.parentNode.insertBefore(btn2, btn1); }); function addListener(elem, type, handler) { if (elem.addEventListener) { elem.addEventListener(type, handler, false); return handler; } else if (elem.attachEvent) { function wrapper() { var event = window.event; event.target = event.srcElement; handler.call(elem, event); } elem.attachEvent('on' + type, wrapper); return wrapper; } } </script> </body> </html>
<!doctype html> <html> <head> <meta charset="utf-8"> <title>TEst</title> </head> <body> <span id="target"></span> <script type="text/javascript"> // 为了简化。每个月默认30天 function getTimeString() { var start = new Date(); var end = new Date(start.getFullYear() + 1, 0, 1); var elapse = Math.floor((end - start) / 1000); var seconds = elapse % 60 ; var minutes = Math.floor(elapse / 60) % 60; var hours = Math.floor(elapse / (60 \* 60)) % 24; var days = Math.floor(elapse / (60 \* 60 \* 24)) % 30; var months = Math.floor(elapse / (60 \* 60 \* 24 \* 30)) % 12; var years = Math.floor(elapse / (60 \* 60 \* 24 \* 30 \* 12)); return start.getFullYear() + '年还剩' + years + '年' + months + '月' + days + '日' + hours + '小时' + minutes + '分' + seconds + '秒'; } function domText(elem, text) { if (text == undefined) { if (elem.textContent) { return elem.textContent; } else if (elem.innerText) { return elem.innerText; } } else { if (elem.textContent) { elem.textContent = text; } else if (elem.innerText) { elem.innerText = text; } else { elem.innerHTML = text; } } } var target = document.getElementById('target'); setInterval(function () { domText(target, getTimeString()); }, 1000) </script> </body> </html>
如:[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 事件绑定
优势:
缺点:
改进:
```
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; };
```
<ul id="target">
<li>1</li> <li>2</li> <li>3</li> <li>4</li>
</ul>
<script>
var target = document.getElementById('target'); var i; var frag = document.createDocumentFragment(); for (i = target.children.length - 1; i >= 0; --i) { frag.appendChild(target.children\[i\]); } target.appendChild(frag);
</script>
```
```
// 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('<p><a href="{0}">{1}</a><span>{2}</span></p>'); console.log(t.format('http://www.alibaba.com', 'Alibaba', 'Welcome'));
})();
```
define 部分定义一个简单的模板类,使用{}做为转义标记,中间的数字表示替换目标,format 实参用来替换模板内标记
横线处填:
<form id="target"> <select name="age"> <option value="aaa">aaa</option> <option value="bbb" selected>bbb</option> </select> <select name="friends" multiple> <option value="qiu" selected>qiu</option> <option value="de">de</option> <option value="qing" selected>qing</option> </select> <input name="name" value="qiudeqing"> <input type="password" name="password" value="11111"> <input type="hidden" name="salery" value="3333"> <textarea name="description">description</textarea> <input type="checkbox" name="hobby" checked value="football">Football <input type="checkbox" name="hobby" value="basketball">Basketball <input type="radio" name="sex" checked value="Female">Female <input type="radio" name="sex" value="Male">Male </form> <script> /\*\* \* 将一个表单元素序列化为可提交的字符串 \* \* @param {FormElement} form 须要序列化的表单元素 \* @return {string} 表单序列化后的字符串 \*/ function serializeForm(form) { if (!form || form.nodeName.toUpperCase() !== 'FORM') { return; } var result = \[\]; var i, len; var field, fieldName, fieldType; for (i = 0, len = form.length; i < len; ++i) { field = form.elements\[i\]; fieldName = field.name; fieldType = field.type; if (field.disabled || !fieldName) { continue; } // enf if switch (fieldType) { case 'text': case 'password': case 'hidden': case 'textarea': result.push(encodeURIComponent(fieldName) + '=' + encodeURIComponent(field.value)); break; case 'radio': case 'checkbox': if (field.checked) { result.push(encodeURIComponent(fieldName) + '=' + encodeURIComponent(field.value)); } break; case 'select-one': case 'select-multiple': for (var j = 0, jLen = field.options.length; j < jLen; ++j) { if (field.options\[j\].selected) { result.push(encodeURIComponent(fieldName) + '=' + encodeURIComponent(field.options\[j\].value || field.options\[j\].text)); } } // end for break; case 'file': case 'submit': break; // 是否处理? default: break; } // end switch } // end for return result.join('&'); } var form = document.getElementById('target'); console.log(serializeForm(form)); </script>
```
<ul id="nav">
<li><a href="http://11111">111</a></li> <li><a href="http://2222">222</a></li> <li><a href="http://333">333</a></li> <li><a href="http://444">444</a></li>
</ul>
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);
```