JS高级程序设计2

时间:2024-04-16 22:06:11

面向对象 ,基本模式、对象字面量模式、工厂模式、构造函数模式、原型模式、组合构造函数和原型模式、其他模式见电子书:动态原型模式、寄生构造函数模式(不推荐)、稳妥构造函数模式(要求安全的环境,不使用new 和 this)

//面向对象
/* 【 数据属性】
* configurable true 通过 delete删除属性来修改属性
* enumberable true 通过 for-in 返回属性
* writable true 修改属性值
* value 数据值
* es5 通过 Object.defineProperty(obj,属性名,对象{} ) 可对以上修改
* 属性名为 configurable/enumerable/writable/value
* 把 configurable 设置为 false后,就无法再设置为true 了,
* 调用 Object.defineProperty() 默认属性名都为 false
* */
var person = {}
Object.defineProperty(person,"name",{
writable: false, // 阻止修改属性值
value:'xiaoming'
})
console.log(person.name)
person.name = 'xxx';
console.log(person.name)
/* 【访问器属性】
* configurable false
* enumerable
* get函数 默认 undefined
* set函数 默认 undefined
* 添加get set函数
* */
var book = {
_year: 2014, // 下划线表示只能通过对象方法访问的属性,可直接访问
edition:1
}
Object.defineProperty(book,'year',{
get:function () {
return this._year
},
set:function (val) {
if(val> 2014){
this._year = val
this.edition += val - 2004
}
}
})
book.year = 2015;
console.log(book.edition);
console.log(book._year);
/* 同时定义多个属性用 Object.defineProperties() 复数 */
/* 通过 Object.getOwnPropertyDescriptor() 可查看 数据属性和 访问器属性各个值
* js中任何对象,包括DOM对象和BOM对象都有 Object.getOwnPropertyDescriptor() 方法
*
* */
var desc =Object.getOwnPropertyDescriptor(book,'_year')
console.log(desc.value);
console.log(desc.configurable);
var desc2 =Object.getOwnPropertyDescriptor(book,'year')
console.log(desc2.value); // undefined
console.log(desc2.configurable); // false /* 【1.一般模式 】*/
var obj = new Object()
obj.name='name'
console.log('name: '+obj.name); /* 2.对象字面量 */
var obj2 = {
name: 'mama'
}
console.log('mama: '+obj2.name); /*【 3.工厂模式】 */
function cretePerson(name,age) {
var o = new Object();
o.name = name;
o.age = age;
o.sayName =function () {
console.log('xx: ' + this.name);
}
return o;
}
var person1 = cretePerson('kang',22)
person1.sayName()
/* 【4.构造函数模式】*/
function Person(name, age) {
this.name=name;
this.age=age;
this.sayName2=function () {
console.log(this.name + 'abccde') // 等同于 this.sayName2 = new Function('...') 每次实例化都会 new Function(),这是缺陷
}
}
var per2 = new Person('xiao',33) // Person() 当成构造函数用,有 new
per2.sayName2()
console.log(per2 instanceof Person); // Person('kangddd',44) // Person() 当成普通函数用,
// window.sayName2(); var per3 = new Person('aa',33)
var per4 = new Person('bb',33) // 实例化两个对象,里面有 sayName() 方法,ECMAScript中函数也是对象,每定义一个函数,就是实例化一个对象
console.log('ddd333' + (per3 == per4)); // + 号优先级比 == 高
console.log('eeefff' + false); /* 【5.原型模式】
* 每个函数都有 prototype(原型)属性,是一个指针,指向一个对象
* 对象实例共享 prototype 定义的属性和方法
* */
function PersonSix() { }
PersonSix.prototype.name = 'li'
PersonSix.prototype.sayName3=function () {
console.log(this.name);
}
var per10 = new PersonSix();
per10.sayName3() // 先查找 per10有没有sayName3()方法,有则返回,没有则查找 prototype是否有 sayname3()方法 /* 每创建一个函数,都有prototype */
function test() {
return 1
}
console.log(test); // 输入函数 function test(){}
console.log(test.prototype); // 返回一个对象 每创建一个函数,都有 prototype
console.log(test.prototype.constructor); // 返回 函数 function test(){} function Person100() { }
Person100.prototype.name='100name'
Person100.prototype.age='100age'
var p100 = new Person100()
var p101 = new Person100()
p100.name = '110name' // 实例中新增同名属性覆盖 原型中的 name
console.log(p100.name); // '110name'
console.log(p101.name); // '100name'
delete p100.name; // 通过 delete 可以找回 原型中的 name
console.log(p100.name); // '100name' console.log(p100.hasOwnProperty('name')); // 判断实例是否有某属性 hasOwnProperty
console.log('name' in p100); // name存在于实例或者原型都会返回 true
console.log(Object.keys(Person100.prototype)); // ['name','age'] 拿到所有原型属性的数组
console.log(Object.getOwnPropertyNames(Person100.prototype)); // ['constructor','name','age'] 拿到所有原型属性的数组
console.log('ok ? ' + (p100.constructor == Person100)); // 简化前 这里是 true /* 简化原型语法*/
function Car() { }
Car.prototype={
constructor: Car, // 手动指定 constructor ,省略后, car.constructor 就不再指向 Car
name:'baoma',
age:22
}
var car = new Car()
console.log(car.name);
console.log(Car.prototype.constructor);
console.log(car.constructor == Car); // 简化后,这里返回 false /* 在 String.prototype中可以找到 substring() 方法 */ /* 原型模式的缺陷是 如果对象中的属性是引用类型,如 数组 , 那么某个实例修改了数组,另一个实例也拿到了修改后的数据 */ function Dog() { }
Dog.prototype={
constructor:Dog,
friends:['kang','jia']
}
var f1 = new Dog()
var f2 = new Dog()
f1.friends.push('hehe')
console.log(f1.friends); // ['kang','jia','hehe']
console.log(f2.friends); // ['kang','jia','hehe'] /* 【组合使用构造函数械和原型原式 】*/
function Pig(name,age) { // 属性写在构造函数中
this.name = name;
this.age= age;
this.friends = ['dd','ee']
}
Pig.prototype={ // 方法写在原型中
constructor: Person,
sayName:function () {
console.log(this.name);
}
}
var pig1 = new Pig('piga',11)
var pig2 = new Pig('pigb',12)
pig1.friends.push('ff')
console.log(pig1.friends);
console.log(pig2.friends);
console.log(pig1.friends === pig2.friends); // false
console.log(pig1.sayName === pig2.sayName); // true

闭包

/* 面向对象继承方法 见 6.3.4原型式继承,一个对象继承另一个不同的对象 更好的是 6.3.6寄生组合式继承 */
var a = function () {
return 5;
}
console.log(a());
/* 递归 严格模式下不能用 arguments.callee时的写法,加多了一个括号,加多一个函数名 */
var factorial = (function f(num) {
if (num <= 1) {
return 1;
} else {
return num * f(num - 1)
}
})
console.log(factorial(5));
/* 普通函数fn被调用时,会创建一个包含 this/arguments/参数val的活动对象, 全局执行环境的变量对象(包含this、res、fn)在执行环境的作用域链中则处于第二位*/
function fn(val) {
return 5 + val
}
var res = fn(4) /* 闭包:指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,就是在一个函数内部创建另一个函数*/
function createComparison() {
return function (obj1, obj2) { // 内部函数会将外部函数 createComparison的活动对象 this等都添加到它的作用域链中,因此闭包比一般函数会占用更多内存,少用
// ...
}
}
// 闭包作用域链使闭包只能取得包含函数中任何变量的最后一个值
function fn2() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function () {
return i;
}
}
return result;
}
console.log(fn2()); // 不懂
// 闭包中的 this 指向 window, this一般情况下,谁调用指代谁
var name = 'window'
var obj = {
name: 'obj',
getName: function () {
return function () {
return this.name
}
}
}
console.log(obj.getName()); // function(){ return this.name} 调用 getName() 返回一个函数 ,
console.log(obj.getName()()); // 'window' 调用 getName()() 就会立即调用它返回的函数,即返回一个字符串 function assign() {
var element = document.getElementById('a');
var id = element.id
element.onclick = function () {
console.log(id);
}
element = null; // 把 element 设置为 null , 手动在闭包中释放内存
} function f2() {
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // undefined 还可以访问,i是定义在f2()函数的活动对象中的
// console.log(j); // error not defined
}
console.log(f2()); function f3() {
(function () {
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // 10 (function(){ ... })() 块级作用域,外部访问不到,可以使用自己定义的变量,不受其他干扰
})()
// console.log(i); // error not defined i 在块级作用域中,外部访问不到,
}
f3() function Test() {
var num = 1078;
return num;
}
console.log(Test()); // 函数名可以大写、中文,
/*
* 特权方法
* */
function f4() {
var num4 = 4;
function getNum() {
return false
}
// 特权方法
this.publicNum = function () {
return num4
}
// 特权方法
this.publicMothod = function () {
return getNum()
}
// return num4; 不想返回,可以写个方法返回 ,并用对象的构造函数模式返回
}
console.log(f4());
console.log(new f4().publicMothod());
console.log(new f4().publicNum()); var f6 = function () {
console.log(666);
}()

setTimeout()    少用setInterval()   history()  location.replace()  不能后退到当前页面

var age = 29; // 使用var 定义后,把 configurable 设置为false 阻止 delete 【面向对象 数据属性 configurable 】
window.color='red'
delete window.age;
delete window.color;
console.log(window.age); //
console.log(window.color); // undefined 使用window来定义变量color,可以被 delete
// ECMAScript 是 js的核心,在web中使用js,则BOM是web(window location navigator )核心 // 使用 setTimeout() 超时调用, 少用间歇调用setInterval() ,需要 clearInterval
var num = 0;
var max = 60;
function minute() {
max--;
console.log(max);
if (max > num) {
setTimeout(minute, 1000)
} else {
console.log('ok');
}
}
setTimeout(minute, 1000) // 倒计时效果
/* location.search */
var url = 'http://www.baidu.com?name=kang&age=12'
console.log(location.search); // ?name=kang&age=12
/* 取消后退按钮用 location.replace() */
setTimeout(function () {
location.replace('http://www.baidu.com') // 不能后退到之前的页面
},1000)
location.reload() // 重新加载 (有可能从缓存中加载 )
location.reload(true) // 重新加载 (从服务器中加载 )
history.go(1) // 前进一页 history.forward()
history.go(-1) //后退一页 history.back()
//
if(history.length == 0){
// 这是用户打开窗口后的第一个页面
}

倒计时 setTimeout()   不用 setInterval()

倒计时
<p id="num">60</p>
<script>
var max = document.getElementById('num').innerHTML
var num = 0;
function minute() {
max--;
document.getElementById('num').innerHTML = max
console.log(max);
if (max > num) {
setTimeout(minute, 1000)
} else {
console.log('ok');
}
}
// setTimeout(minute, 1000)
</script>

document  getElementByClassName classList  readyState  compatMode  outerHTML

console.log(document.title);  // 标题
console.log(window.location.href);
console.log(document.URL); // 网址
console.log(document.domain); // 域名
/*
* document.forms 所有<form>元素
* document.images 所有 <img>元素
* document.links 所有带 href的<a>元素
* document.anchors 所有带 name的<a>元素 描点
* */
document.write('<script src = "1.js"></script>')
/* 文本 节点分割 */
var element = document.createElement("div")
var textNode = document.createTextNode('hello world')
element.appendChild(textNode)
document.body.appendChild(element)
var newNode = element.firstChild.splitText(5) // 文本节点分割
console.log(element.firstChild.nodeValue);
console.log(newNode.nodeValue); /*
* <div class="a"></div>
* */
document.getElementsByTagName('div')[0].innerHTML = 444
document.querySelector('.a').innerHTML = 123
document.getElementsByClassName('a')[0].innerHTML = 888 // h5 新增 getElementsByClassName /*
* h5 增加 classList 方法 for(var i = 0;i<div.classList.length; i++){...}
* <div class = 'a b c'>ddd</div>
* div.classList.remove('a') // 删除a 样式 add() 添加 toggle('c') 切换样式 contains('d') 包含样式
* */ /*
* h5 DOM焦点功能
* document.activeElement 判断获得焦点是哪个元素
* document.hasFocus() 是否获得焦点了
* */
var button = document.getElementById('mybtn')
button.focus();
console.log(document.activeElement === button); // true
console.log(document.hasFocus()); // true /*
* h5 文档加载属性 readyState loading 加载中 complete 加载完成
* if(document.readyState == 'complete'){ ... // 文档加载完成 }
* */ /*
* 渲染模式
*
* */
if(document.compatMode == 'CSS1Compat'){
console.log('standards mode'); // 标准模式
}else {
console.log('quirks mode'); // 混杂模式
}
console.log(document.charset); // utf-8
// h5 新增 document.head (chrome和 safari5 实现了)
var head = document.head || document.getElementsByTagName('head')[0];
/*
* outerHTML
* <div id="mydiv" data-apptest = '12345' data-appName="hehe">div</div>
* */
document.getElementById('mydiv').outerHTML="<p>this is p</p>"
/* 把 mydiv整个html片断 替换为 新的内容 */
/*
* <div id="mydiv" data-apptest = '12345' data-appName="hehe">div</div>
* 在 div同级之前、之后插入元素,在div里面内容之前、之后插入元素 beforebegin afterbegin beforeend afterend
* 使用 innerHTML outerHTML insertAdjacentHTML 要先把原来的元素相关的事件给删除,减少内存占用
* */
document.getElementById('mydiv').insertAdjacentHTML('beforebegin','<p>pppp</p>')

js删除元素的行内样式 removeProperty()    cssText 添加多个样式

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>abc</title>
</head>
<style>
.p3{
position: absolute;top:22px;left:33px;
color: red;
}
</style>
<body>
<div id="test">d</div>
<div style="border: 1px solid green;width:200px;height: 300px;position: relative;" >
<p style="position: absolute;top:22px;left:33px;color:blue;" id="test2">dddddd</p>
<p style="" class="p3" id="test3">dddddd</p> </div>
<script src="0.js"></script>
原型对象 p167
<script>
/* 删除样式,取得默认属性
* cssText 批量添加样式、 removeProperty() 删除样式 h5的classList 也可以删除样式
* removeProperty() 在不确定某个给定的CSS属性拥有什么默认值的情况下,可以移除相应的属性,就可以为元素应用默认值
* */
var test = document.getElementById('test')
test.style.color='red'
test.style.cssText='font-size:50px;color:blue;' //添加多个样式
var prop,val
for(var i =0;i<test.style.length;i++){
// console.log(test.style[i]);
prop = test.style[i]
val = test.style.getPropertyValue(prop)
console.log(prop + " : " + val);
}
test.style.removeProperty('color') document.getElementById('test2').style.removeProperty('position')
document.getElementById('test2').style.removeProperty('color')
document.getElementById('test3').style.removeProperty('color') // 只能删除行内式,样式选择器的删除不了 /* getComputedStyle(a,b) a:元素, b:伪元素字符串,如 :after ,没有传 null ie不支持,用currentStyle 其他浏览器返回值,如border值不一致*/
var computedStyle = document.defaultView.getComputedStyle(test,null)
</script>
</body>
</html>

js 读取样式表的属性  可以动态添加 样式 insertRule ie用addRule    删除样式 deleteRule() ie用 removeRule() 不常用

<style>
.test{
background: blue;
width:110px;
height:220px;
}
.box{
background: red;
width:100px;
height:200px;
}
</style>
<body>
<script>
var sheet = document.styleSheets[0];
var rules = sheet.cssRules || sheet.rules;
console.log(rules[0].selectorText); // 读取样式表的属性值
console.log(rules[1].style.cssText);
console.log(rules[0].style.background);
console.log(rules[0].style.width);
console.log(rules[0].style.height);
</script>

偏移量 offset  客户区大小  client 滚动大小 scrollTop

偏移量
offset 内容+padding+border
offsetHeight offsetWidth offsetLeft offsetTop p12.2.3 元素大小 客户区大小
client 内容+padding
clientHeight clientWidth document.documentElement.clientWidth 低版本用 document.body.clientWidth 滚动大小
scrollHeight 元素内容高度
scrollWidth 元素内容宽度 document.documentElement.scrollWidth
scrollLeft
scrollTop

getBoundingClientRect()  DOM遍历、DOM范围

每个元素都有 getBoundingClientRect() , 返回一个矩形对象 left top right bottom   ie8不一致
DOM遍历 p12.3 NodeIterator、TreeWalker ie不支持
DOM范围 p12.4

事件 event对象  currentTarget target this

<script>
/* 事件都会传 event对象 , ie8以前由 window.event 获得,如果ie使用 <input type='text' onclick="alert(event.type)"> 这里的event就可以直接获取 ,跟DOM一样
currentTarget target this
一般情况下,currentTarget === this === target , 当点击区域变大了后, target会变成点击目标,如body,如button等,而 this和currentTarget永远表示调用的对象,这里是body*/
document.body.onclick=function (e) {
console.log(e.type); // 'click' 'mouseover'等
console.log(e.currentTarget === this);
console.log(e.target === this);
console.log(e.target); // 点哪个是哪个 button 或 body
console.log(this); // 谁调用是谁 body
} </script>

js访问form元素简写 、 addEventListener()   事件冒泡 stopPropagation()

<body>
<form action="" name="form1">
<input type="text" name="username">
<input type="button" onclick="console.log(username.value)" value="click"> <!-- 输入的值 表单简写 -->
<input type="button" onclick="console.log(this.value)" value="btn"> <!-- btn -->
<input type="button" onclick="console.log(value)" value="btn22"> <!-- btn22 表单简写 -->
</form>
<!-- addEventListener('click',function(){},false)
false 表示在冒泡阶段调用事件处理程序,即从当前元素,如div 往上一级,body 等促发
true 表示在捕获阶段调用事件处理程序,即从body-> div 再到 body的促发,先由外到内的捕获,再由内到外的冒泡 -->
<!--
/* 取消链接的默认行为,如链接跳转,使用 e.preventDefault()
* 取消事件冒泡,使用 stopPropagation()
* */
-->
<div id="mydiv" style="border: 1px solid green;width: 200px;height: 200px;">
<button id="btn">btn</button>
</div>
<script>
// 只有在事件处理期间,event对象才会存在,一旦事件处理完成,event对象就会被销毁
document.getElementById('btn').onclick=function (e) {
e.stopPropagation() // 阻止后,就不影响
console.log('btn'); // 点击btn时,也会点到外面的mydiv,会输入两行
}
document.getElementById('mydiv').onclick=function () {
console.log('mydiv');
}
</script>
</body>

事件   event

/* 【电子书 13.4】
* load 页面加载后 window.onload , 所有框架加载完,在框架上触发, 图片加载完,在img上触发, object嵌入内容加载完在 object上触发
* unload 页面卸载 window.unload ,所有框架卸载完,在框架上触发, object嵌入内容卸载完在 object上触发 ,从一个页面切换到另一个页面就会发生 unload事件,多用于清除引用,避免内存泄漏
* abort 用户停止下载过程时,如果嵌入的内容没有加载完,在<object>上触发
* error 当发生javascript错误时在window上面触发,当无法加载图像在img触发,当无法加载嵌入内容在<object>触发
* select 当选择文本框input 或 textarea 中一或多个字符时触发
* resize 当窗口或框架大小变化在 window 触发, 最大化、最小化也会触发
* scroll 当滚动带滚动条的元素中的内容时,在该元素上面触发 body元素包含所加载页面的滚动条
*
* <script> 在ie9+ 中,只有设置了script的src属性,并添加该元素到文档后,才会开始加载js文件
* 事件中的 shift ctrl alt meta(指windows键盘中的windows键,在苹果机 Cmd键 )
* e.shiftKey e.ctrlKey e.altKey e.metaKey
* 鼠标左中右键 e.button 0 表示左键 1 表示鼠标滚轮 2表示鼠标右键
* mousewheel 鼠标滚轮事件 有一个 e.wheelDelta 属性,当用户向前滚动鼠标时 wheelDelta是120的倍数,向后滚动鼠标,wheelDelta是-120的倍数
* 火狐用 e.DOMMouseScroll 保存在 e.detail 当用户向前滚动鼠标时 wheelDelta是 -3 的倍数,向后滚动鼠标,wheelDelta是3的倍数
*
* 触摸设备 ios 和 android 没有鼠标, 没有 dbclick
* 轻击可触发 mousemove事件,如果该操作会导致内容变化,将不再有其他事件发生,如果屏幕没有因此变化,那么会依次发生 mousedown mouseup 和 click 事件
* mousemove事件也触发 mouseover mouseout事件
* 两个手指在屏幕上且页面随手指移动而滚动时会触发mousewheel和scroll事件 (好像没啥用)
*
* keydown 用户按下键盘任意键触发,按住不放,会重复触发
* keypress 键盘字符键、esc键触发,按住不放,会重复触发
* textInput 文本事件,对keypress的补充,在文本插入文本框之前触发textInput 事件
* 用户按下键盘的字符键后,先触发 keydown事件、再触发 keypress事件,再触发 keyup事件, keydown和keypress是在文本框发生变化之前触发的。 keyup是文本框发生变化之后触发的。
* 【电子书 13.4.4】
* */

pageX  offsetX  screenX clientX  鼠标左中右键,滚轮事件 页面切换事件 unload

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>abc</title>
</head>
<body>
this is 0.html
<script>
window.onunload=function () {
console.log('unload'); // 页面跳转,离开当前页面会执行,页面刷新也会执行
}
</script>
<div id="a" style="border: 6px solid green;width:200px;height: 200px;padding:10px;">div</div>
<div id="b" style="border: 6px solid green;width:200px;height: 200px;padding:10px;">div</div>
<div id="c" style="border: 6px solid green;width:200px;height: 200px;padding:10px;">div</div>
<script>
document.getElementById('a').onclick=function (e) {
console.log(e.clientX);
console.log(e.pageX); // 以浏览器为起点,页面不滚动,两者一致, 页面滚动,pageX包括滚动条的值
console.log(e.screenX); // 相对当前屏幕,以PC桌面左上角为起点
console.log(e.offsetX); // 限制在点击区域内的位置,除去边框和外边距
}
document.getElementById('b').addEventListener('mousedown',function (e) {
console.log(e.button); // 判断鼠标左中右键 e.button的值 0 是左键 1 是鼠标滚轮 2是右键
},false)
document.getElementById('c').addEventListener('mousewheel',function (e) {
console.log(e.wheelDelta);
},false)
document.getElementById('c').addEventListener('DOMMouseScroll',function (e) {
console.log(e.detail); // 火狐用 DOMMouseScroll
},false)
</script>
</body>
</html>

contextmenu冒泡事件 右键菜单

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>abc</title>
</head>
<body>
contextmenu冒泡事件 上下文菜单(右键菜单) <div id="mydiv" style="border: 1px solid green;width:800px;height: 1000px;">右键菜单</div>
<div id="mymenu" style="border: 1px solid green;width:200px;height:200px;display:none;position: absolute;top:80px;left:20px;">右键菜单
</div> <script>
// 右键菜单
var mydiv = document.getElementById('mydiv')
var mymenu = document.getElementById('mymenu')
mymenu.addEventListener('contextmenu', function (e) {
e.preventDefault() // 阻止默认的浏览器右键菜单
})
mydiv.addEventListener('contextmenu', function (e) {
e.preventDefault() // 阻止默认的浏览器右键菜单
mymenu.style.left = e.clientX + 'px'
mymenu.style.top = e.clientY + 'px'
mymenu.style.display = 'block'
})
document.addEventListener('click', function () {
mymenu.style.display = 'none'
})
</script>
<script>
window.addEventListener('beforeunload',function (e) { // 窗口关闭时,弹窗是否关闭
var res = 'abc'
e.returnValue=res // ie可以
return res // chrome 返回不了'abc'
})
</script>
load事件会在页面中一切都加载完毕时触发,包括一堆外部资源
DOMContentLoaded事件则在形成完整的DOM树之后就会触发,不理会图像、JS文件、css文件是否已经下载完毕,用户可以早点与页面进行交互 ie9+支持
不支持的浏览器,处理如下 setTimeout(function(){ ... },0); // 不一定有效
readystatechange事件 chrome不支持! ie、firefox支持
pageshow和pagehide事件 在浏览器后退和前进按钮时缓存数据,不会用 ,ie9不兼容
hashchange事件 url中'#'号后面的字符串发生变化时,监听事件
window.addEventListener('hashchange',function(e){console.log(location.hash);}) ie8+ 支持
手机设备旋转事件 deviceorientation devicemotion android版 webkit ?
触摸事件 touchstart touchmove(调用 preventDefault()可以阻止滚动 ) touchend
触摸事件(包括鼠标事件的顺序,会冒泡)
touchstart / moseover / mousemove(一次) / mousedown / mouseup /click/ touchend
手势事件(要两个手指在元素范围内才触发,会冒泡,只放一个手指会触发 touchstart事件) ios才支持
gesturestart
gesturechange
gestureend
</body>
</html>