面向对象 ,基本模式、对象字面量模式、工厂模式、构造函数模式、原型模式、组合构造函数和原型模式、其余模式见电子书:动态原型模式、寄生构造函数模式(不推荐)、稳妥构造函数模式(要求安全的环境,不使用new 和 this)javascript
//面向对象 /* 【 数据属性】 * 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
闭包css
/* 面向对象继承方法 见 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() 不能后退到当前页面html
var age = 29; // 使用var 定义后,把 configurable 设置为false 阻止 delete 【面向对象 数据属性 configurable 】 window.color='red' delete window.age; delete window.color; console.log(window.age); // 29 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() java
倒计时 <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 outerHTMLnode
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 添加多个样式android
<!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() 不经常使用ios
<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 web
偏移量
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范围chrome
每一个元素都有 getBoundingClientRect() , 返回一个矩形对象 left top right bottom ie8不一致
DOM遍历 p12.3 NodeIterator、TreeWalker ie不支持
DOM范围 p12.4
事件 event对象 currentTarget target thiswindows
<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>