1. DOM(文档对象) 获取元素 根据ID获取:document.getElementById(id)
# id 为大小写严格区分的字符串 注:因为文档页面从上往下加载,所以先得有标签,所以 script 写到有 id标签的下面
根据标签名获取:document.getElementsByTagName('标签名')
# 返回的是元素对象的集合,以伪数组的形式存储 这样获取的是整个页面的该标签元素,也可以获取某个元素内部所指定标签的子元素,见下element.getElementsByTagName('标签名')
# element 是父元素
注:因为返回元素以伪数组的形式存储,使用时也应是具体数组元素值: ol[0].getElementsByTagName('li')
H5新增的方法获取:document.getElementsByClassName('类名')
# 根据类名返回元素对象集合document.querySelector('选择器')
# 根据指定选择器返回第一个元素对象(‘.box’,’#nav’,’li’)document.querySelectorAll('选择器')
# 返回指定选择器的所有元素对象集合(多了个All嘛)
获取特殊标签: body: document.body
; html: document.documentElement
;
事件基础 事件源 事件类型 事件处理程序
1 2 3 4 var div = document .getElementsByTagName('div' ); div.onclick = function ( ) {alert('你好!' );}
常见事件类型
.onclick
鼠标点击触发
.onmouseover
鼠标经过触发
.onmouseout
鼠标离开触发
.onfocus
获得鼠标焦点触发
.onblur
失去鼠标焦点触发
.onmousemove
鼠标移动触发
.onmouseup
鼠标弹起触发
.onmousedown
鼠标按下触发
操作元素 修改元素内容:element.innerText
从起始位置到终止位置的内容,不识别html标签,同时空格和换行也会去掉element.innerHTML
从起始位置到终止位置的全部内容,识别html标签,同时保留空格和换行
样式属性操作:element.style
行内样式操作element.className
类名样式操作 (换一个类名指定)
注:JS里的样式均采用驼峰命名法,如:div.style.backgroundColor = 'pink';
获取属性值: element.属性 获取内置属性 element.getAttribute(‘属性’); 主要获取自定义的属性
设置属性值: element.属性 = ‘值’ element.setAttribute(‘属性’, ‘值’); element.removeAttribute(‘属性’) 移除属性
H5自定义属性: 以 data- 开头 # 更容易区分自定义属性和内置属性 新增获取属性值: element.dataset.属性 / element.dataset['属性']
注:dataset
是一个集合 里面存放了所有以 data开头的自定义属性如果自定义属性里面有多个 - 连接的单词,获取时采用 驼峰命名法 如:class="data-list-name"
element.dataset.listName;
节点操作 概述: 节点至少拥有 nodeType
(节点名称)、nodeName
(节点类型)、nodeValue
(节点值)这三个基本属性 元素节点 / 属性节点 / 文本节点(包含文字、空格、换行) nodeType 反别为 1 / 2 / 3
node.parentNode
父节点 # 得到的是离元素最近的父级节点。若没有,则返回 nullparentNode.childNodes
子节点 # 返回包含指定节点的子节点的集合,子节点还包含 元素节点、文本节点等
来个栗子
1 2 3 4 5 6 7 var ul = document .querySelector('ul' );for (var i = 0 ; i < ul.childNodes.length; i++) { if (ul.childNodes[i].nodeType == 1 ) { console .log(ul.childNodes[i]); } }
parentNode.children
子节点 # 直接获取所有的子元素节点
parentNode.firstChild
第一个子节点 (包括文本节点)
parentNode.lastChild
最后一个子节点
parentNode.firstElementChild
第一个子元素节点 (不包括文本节点)
parentNode.lastElementChild
最后一个子元素节点
但这又有兼容性的问题,实际中常用:
1 2 3 4 console .log(ol.children[0 ]);console .log(ol.children.length - 1 );
node.nextSibling
下一个兄弟节点 (包括文本节点等)
node.previousSibling
上一个兄弟节点
node.nextElementSibling
下一个兄弟元素节点
node.previousElementSibling
上一个兄弟元素节点
document.createElement('tagName')
创建元素节点
document.write('<div>123</div>')
创建元素,如果页面文档加载完毕再调用这句话会导致页面重绘
node.appendChild(child)
添加节点 (末尾添加)
node.insertBefore(child, 指定元素)
添加节点 (添加到父节点的指定子节点前面)
实栗
1 2 3 4 5 var li = document .createElement('li' );var ul = document .querySelector('ul' );ul.appendChild(li);
node.removeChild(child)
删除节点 (返回删除的节点)
node.cloneNode(true)
复制节点 (注:括号为空或false为浅拷贝,只复制标签)
事件高级 注册事件 前有多个button标签省略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var btns = document .querySelectorAll('button' );btns[0 ].onclick = function ( ) { alert('hi' ); } btns[1 ].addEventListener('click' , function ( ) { alert(22 ); }) btns[2 ].attachEvent('onclick' , function ( ) { alert(11 ); }
删除事件 来个栗子吧:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var divs = document .querySelectorAll('div' );divs[0 ].onclick = function ( ) { alert(11 ); divs[0 ].onclick = null ; } divs[1 ].addEventListener('click' , fn) function fn ( ) { alert(22 ); divs[1 ].removeEventListener('click' , fn); } divs[2 ].attachEvent('onclick' , fn1) function fn1 ( ) { alert(33 ); divs[2 ].detachEvent('onclick' , fn1);
DOM 事件流 捕获阶段 —> 当前目标阶段 —> 冒泡阶段
JS 代码中只能执行捕获或者冒泡其中的一个阶段。
onclick 和 attachEvent(ie) 只能得到冒泡阶段。
捕获阶段: 如果addEventListener
第三个参数是 true 那么则处于捕获阶段 document -> html -> body -> father -> son
1 2 3 4 5 6 7 8 9 var son = document .querySelector('.son' );son.addEventListener('click' , function ( ) { alert('son' ); }, true ); var father = document .querySelector('.father' );father.addEventListener('click' , function ( ) { alert('father' ); }, true );
冒泡阶段: 如果addEventListener
第三个参数是 false 或者 省略 那么则处于冒泡阶段 son -> father ->body -> html -> document
1 2 3 4 5 6 7 8 9 10 11 12 13 var son = document .querySelector('.son' );son.addEventListener('click' , function ( ) { alert('son' ); }, false ); var father = document .querySelector('.father' );father.addEventListener('click' , function ( ) { alert('father' ); }, false ); document .addEventListener('click' , function ( ) { alert('document' ); })
事件对象 (event、evt、e) e.target
返回的是触发事件的对象(元素); this
返回的是绑定事件的对象(元素) 区别 : e.target
点击了那个元素,就返回那个元素; this
哪个元素绑定了这个点击事件,那么就返回谁
(了解) 跟 this 有个非常相似的属性 currentTarget
ie678不认识
e.type
返回事件类型
e.preventDefault()
阻止默认事件 (让链接不跳转 或者让提交按钮不提交)
1 2 3 4 var a = document .querySelector('a' );a.addEventListener('click' , function (e ) { e.preventDefault(); })
利用return false 也能阻止默认行为 没有兼容性问题 特点: return 后面的代码不执行了, 而且只限于传统的注册方式
e.stopPropagation()
阻止冒泡
e.cancelBubble = true;
非标准 cancel 取消 bubble 泡泡
事件委托 事件委托的核心原理:给父节点添加 侦听器,利用事件冒泡影响每一个子节点 作用:不是给每个子节点单独设置事件监听器,提高程序的性能
常用鼠标事件 (补充)contextmenu
可以禁用右键菜单
1 2 3 document .addEventListener('contextmenu' , function (e ) { e.preventDefault(); })
selectstart
可禁止选中文字
1 2 3 document .addEventListener('selectstart' , function (e ) { e.preventDefault(); })
e.clientX/Y
鼠标在可视区的x和y坐标
e.pageX/Y
鼠标在页面文档的x和y坐标
e.screenX/Y
鼠标在电脑屏幕的x和y坐标
常用键盘事件 onkeyup
某个键盘按键松开时触发
1 2 3 4 5 6 document .onkeyup = function ( ) { console .log('我弹起了' ); } document .addEventListener('keyup' , function ( ) { console .log('我弹起了' ); })
onkeydown
某个键盘按键被按下时触发onkeypress
某个键盘按键被按下时触发,但不识别功能键
三个事件的执行顺序 keydown – keypress – keyup
keyCode
属性可以得到相应键的ASCII码值
keyup 和keydown事件不区分字母大小写 a 和 A 得到的都是65 (即都是大写) keypress 事件 区分字母大小写 a 97 和 A 得到的是65
1 2 3 4 5 6 document .addEventListener('keyup' , function (e ) { console .log('up:' + e.keyCode); }) document .addEventListener('keypress' , function (e ) { console .log('press:' + e.keyCode); })
2. BOM (浏览器对象) 小知识: 同步:每一个任务结束之后再执行下一个 异步:可以同时进行多个任务
函数执行为异步,先同步后异步
常见事件
窗口加载事件window.onload
当文档内容全加载完成时触发该事件,在 addEventListener 里没有 on 哦 这样js代码就可以写在任意地方了,不必在请求元素下面,但该方式只能写一次,如果使用 addEventListener 则没有限制document.addEventListener('DOMContentLoaded', function(){})
DOM 加载完毕,不包含图片 falsh css 等就可以执行 加载速度比 load更快一些
调整窗口大小事件window.onresize = function(){}
当窗口大小发生变化时触发该事件window.innerWidth
当前屏幕的宽度
定时器 (demo-14)window.setTimeout(调用函数, 延时时间)
延时时间单位是毫秒 但是可以省略,如果省略默认的是0window.clearTimeout(timeoutID)
停止定时器 # timeoutID 为计时器的名字window.setInterval(调用函数, 延时时间)
每隔这个延时时间,就调用这个函数,其它特性与 setTimeout 相同window.clearInterval(timeID)
停止定时器
location 对象 属性location.href
获取或设置整个 URL 扩充
属性
作用
.host
返回主机(域名)
.port
返回端口号,若未写返回空字符串
.pathname
返回路径
.search
返回参数
.hash
返回片段
方法location.assign(地址)
记录浏览历史,所以可以实现后退功能
location.replace()
不记录浏览历史,所以不可以实现后退功能
location.reload()
重新加载界面,相当于刷新
后缀函数
作用
back()
后退功能
forward()
前进功能
go(参数)
前进后退功能,参数为 1前进,-1 后退
元素系列
element.offsetParent
返回该元素带有定位到父元素,若父元素都没有则返回 body(下同)
element.offsetTop
返回元素相对带有定位父元素上方的偏移
element.offsetLeft
返回元素相对带有定位父元素左边框的偏移
element.offsetWidth
返回自身包括 padding、边框、内容区的宽度数值(不带单位)
element.offsetHeight
返回自身包括 padding、边框、内容区的高度数值(不带单位)
区分:想获取元素大小位置用 offset 想要给元素更改值用 style
来个栗子(放大镜)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 window .addEventListener('load' , function ( ) { var son = document .querySelector(".son" ); var big = document .querySelector(".big" ); var father = document .querySelector(".father" ); father.addEventListener('mouseover' , function ( ) { father.style.cursor = 'move' ; son.style.display = 'block' ; big.style.display = 'block' }) father.addEventListener('mouseout' , function ( ) { son.style.display = 'none' ; big.style.display = 'none' }) father.addEventListener('mousemove' , function (e ) { var x = e.pageX - this .offsetLeft; var y = e.pageY - this .offsetTop; var sonX = x - son.offsetWidth / 2 ; var sonY = y - son.offsetHeight / 2 ; var sonMax = father.offsetWidth - son.offsetWidth; if (sonX <= 0 ) { sonX = 0 ; } else if (sonX >= sonMax) { sonX = sonMax; } if (sonY <= 0 ) { sonY = 0 ; } else if (sonY >= father.offsetHeight - son.offsetHeight) { sonY = father.offsetHeight - son.offsetHeight; } son.style.left = sonX + 'px' ; son.style.top = sonY + 'px' ; var bigIMg = document .querySelector('.bigImg' ); var bigMax = bigIMg.offsetWidth - big.offsetWidth; var bigX = sonX * bigMax / sonMax; var bigY = sonY * bigMax / sonMax; bigIMg.style.left = -bigX + 'px' ; bigIMg.style.top = -bigY + 'px' ; }) })
element.clientTop
返回元素上边框的大小
element.clientLeft
返回元素左边框的大小
element.clientWidth
返回自身包括 padding、内容区的宽度,不包括边框(不带单位)
element.clientHeight
返回自身包括 padding、内容区的高度,不包括边框(不带单位)
扩充: 立即执行函数:不需要调用,立马能够自己执行的函数 写法:(function() {})();
或者 (function(){}());
element.scrollTop
返回被卷去的上侧距离(不带单位 下同)
element.scrollLeft
返回被卷去的左侧距离
element.scrollWidth
返回自身实际的宽度,不含边框
element.scrollHeight
返回自身实际的高度,不含边框
1 2 3 4 div.addEventListener('scroll' , function ( ) { console .log(div.scrollTop) })
区分 :想获取元素大小位置用 offset 想要给元素更改值用 style 获取元素大小用 client 获取滚动距离用 scroll 页面的滚动距离是通过 window.pageXoffset 获得
实栗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 window .addEventListener('load' , function ( ) { var arrow_l = document .querySelector('.arrow-l' ); var arrow_r = document .querySelector('.arrow-r' ); var focus = document .querySelector('.focus' ); var focusWidth = focus.offsetWidth; focus.addEventListener('mouseenter' , function ( ) { arrow_l.style.display = 'block' ; arrow_r.style.display = 'block' ; clearInterval (timer); timer = null ; }); focus.addEventListener('mouseleave' , function ( ) { arrow_l.style.display = 'none' ; arrow_r.style.display = 'none' ; timer = setInterval (function ( ) { arrow_r.click(); }, 2000 ); }); var ul = focus.querySelector('ul' ); var ol = focus.querySelector('.circle' ); for (var i = 0 ; i < ul.children.length; i++) { var li = document .createElement('li' ); li.setAttribute('index' , i); ol.appendChild(li); li.addEventListener('click' , function ( ) { for (var i = 0 ; i < ol.children.length; i++) { ol.children[i].className = '' ; } this .className = 'current' ; var index = this .getAttribute('index' ); num = index; circle = index; console .log(focusWidth); console .log(index); animate(ul, -index * focusWidth); }) } ol.children[0 ].className = 'current' ; var first = ul.children[0 ].cloneNode(true ); ul.appendChild(first); var num = 0 ; var circle = 0 ; var flag = true ; arrow_r.addEventListener('click' , function ( ) { if (flag) { flag = false ; if (num == ul.children.length - 1 ) { ul.style.left = 0 ; num = 0 ; } num++; animate(ul, -num * focusWidth, function ( ) { flag = true ; }); circle++; if (circle == ol.children.length) { circle = 0 ; } circleChange(); } }); arrow_l.addEventListener('click' , function ( ) { if (flag) { flag = false ; if (num == 0 ) { num = ul.children.length - 1 ; ul.style.left = -num * focusWidth + 'px' ; } num--; animate(ul, -num * focusWidth, function ( ) { flag = true ; }); circle--; circle = circle < 0 ? ol.children.length - 1 : circle; circleChange(); } }); function circleChange ( ) { for (var i = 0 ; i < ol.children.length; i++) { ol.children[i].className = '' ; } ol.children[circle].className = 'current' ; } var timer = setInterval (function ( ) { arrow_r.click(); }, 2000 ); })
3. 面向对象 创建及继承 来个栗子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Father { constructor (x, y ) { this .x = x; this .y = y; sum ( ) { console .log(this .x + this .y); say ( ) { return '我是爸爸' ; } } class Son extends Father { constructor (x, y ) { super (x, y); say ( ) { console .log(super .say() + '的儿子' ); subtract ( ) { console .log(this .x - this .y); } } var son = new Son(1 , 2 );son.sum(); son.say(); son.subtract();
在使用函数时,尤其需要注意 this 指向的到底是什么,一个口诀,谁调用,this 就指向谁 实例见案例/js/tab.js
原型、成员 结合栗子好懂一些
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 var obj1 = new Object ()var obj2 = {}function Star (uname, age ) { this .uname = uname; this .age = age; this .sing = function ( ) { console .log('xiao_shuang 哈哈哈' ); } Star.prototype.sing = function ( ) { console .log('我会唱歌' ); var ldh = new Star('刘德华' , 18 );console .log(ldh);ldh.sing() var xiao = new Star('xiao' , 18 );console .log(ldh.sing === xiao.sing)console .log(ldh.__proto__ === Star.prototype)console .log(ldh.uname);console .log(Star.uname); Star.sex = '男' ; console .log(Star.sex);console .log(ldh.sex);
原型对象 理解原型链: (套娃)
只要是对象就有__proto__
原型, 指向原型对象
Star
原型对象里面的__proto__
原型指向的是Object.prototype
Object.prototype
原型对象里面的__proto__
原型指向为 null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function Star (uname, age ) { this .uname = uname; this .age = age; } var ldh = new Star('刘德华' , 18 );console .log(Star.prototype);console .log(Star.prototype.__proto__ === Object .prototype);console .log(Object .prototype.__proto__);ldh.sex = '男' ; console .log(ldh.sex);Star.prototype = { constructor : Star , sing : function ( ) { console .log('我会唱歌' ); }, }
区分:Star.prototype.sing = function() {}
在原型对象中添加方法Star.prototype = {}
直接覆盖原型对象
实栗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Array .prototype.sum = function ( ) { var sum = 0 ; for (var i = 0 ; i < this .length; i++) { sum += this [i]; } return sum; }; var arr = [5 , 2 , 3 ];console .log(arr.sum());console .log(arr.sort());console .log(Array .prototype);var arr1 = new Array (11 , 22 , 33 );console .log(arr1.sum());
class 出现之前的继承 (了解) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 function Father (uname, age ) { this .uname = uname; this .age = age; } Father.prototype.money = function ( ) { console .log(100000 ); }; function Son (uname, age, score ) { Father.call(this , uname, age); this .score = score; } Son.prototype = new Father(); Son.prototype.constructor = Son; Son.prototype.exam = function ( ) { console .log('孩子要考试' ); } var son = new Son('刘德华' , 18 , 100 );console .log(son);console .log(Father.prototype);console .log(Son.prototype.constructor);son.money();
扩充方法 call() 1 2 3 4 5 6 7 8 9 10 11 12 function fn (x, y ) { console .log('我想喝手磨咖啡' ); console .log(this ); console .log(x + y); } var o = { name: 'andy' }; fn.call(); fn.call(o, 1 , 2 )
forEach() 1 2 3 4 5 6 7 8 9 10 11 var arr = [1 , 2 , 3 ];var sum = 0 ;arr.forEach(function (value, index, array ) { console .log('每个数组元素' + value); console .log('每个数组元素的索引号' + index); console .log('数组本身' + array); sum += value; }) console .log(sum);
filter() 1 2 3 4 5 6 7 var arr = [12 , 66 , 4 , 88 , 3 , 7 ];var newArr = arr.filter(function (value, index ) { return value % 2 === 0 ; }); console .log(newArr);
some() 1 2 3 4 5 6 7 8 9 10 11 12 13 var arr = [10 , 30 , 4 ];var flag = arr.some(function (value ) { return value < 3 ; }); console .log(flag)var arr1 = ['red' , 'pink' , 'blue' ];var flag1 = arr1.some(function (value ) { return value == 'pink' ; }); console .log(flag1);
filter
是查找满足条件的元素,返回的是一个数组,而且是把所有满足条件的元素返回回来
some
是查找满足条件的元素是否存在,返回的是一个布尔值,如果查找到第一个满足条件的元素就终止循环
trim() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var str = ' an dy ' ;console .log(str);var str1 = str.trim();console .log(str1);var input = document .querySelector('input' );var btn = document .querySelector('button' );var div = document .querySelector('div' );btn.onclick = function ( ) { var str = input.value.trim(); if (str === '' ) { alert('请输入内容' ); } else { console .log(str); console .log(str.length); div.innerHTML = str; } }
Object.keys() 1 2 3 4 5 6 7 8 9 10 11 12 13 var obj = { id: 1 , pname: '小米' , price: 1999 , num: 2000 }; var arr = Object .keys(obj);console .log(arr);arr.forEach(function (value ) { console .log(value); })
Object.defineProperty() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 var obj = { id: 1 , pname: '小米' , price: 1999 }; Object .defineProperty(obj, 'num' , { value: 1000 , enumerable: true }); Object .defineProperty(obj, 'price' , { value: 9.9 }); console .log(obj);Object .defineProperty(obj, 'id' , { writable: false , }); obj.id = 2 ; Object .defineProperty(obj, 'address' , { value: '中国山东蓝翔技校xx单元' , writable: false , enumerable: false , configurable: false }); console .log(obj);console .log(Object .keys(obj));delete obj.address;delete obj.pname;console .log(obj)Object .defineProperty(obj, 'address' , { value: '中国山东蓝翔技校xx单元' , writable: true , enumerable: true , configurable: true }); console .log(obj.address);
函数 定义方式
自定义函数 (命名函数)function fn() {};
函数表达式 (匿名函数)var fun = function() {};
利用 new Function('参数1','参数2', '函数体');
1 2 var f = new Function ('a' , 'b' , 'console.log(a + b)' );f(1 , 2 );
补充
所有函数都是 Function 的实例(对象)
函数也属于对象 (万物皆对象)console.log(f instanceof Object);
–> true
this 指向谁
普通函数 (this 指向 window)
1 2 3 4 5 function fn ( ) { console .log('1.人生的巅峰' ); console .log('普通函数的this -> ' + this ); } window .fn();
对象 (this 指向的是对象 o)
1 2 3 4 5 6 7 var o = { sayHi: function ( ) { console .log('2.人生的巅峰' ); console .log('对象方法的this -> ' + this ); } } o.sayHi();
构造函数 (this 指向 ldh 这个实例对象)
1 2 3 4 5 6 7 function Star ( ) {};Star.prototype.sing = function ( ) { console .log('3.人生的巅峰' ); console .log('构造函数的this -> ' + this ); } var ldh = new Star();ldh.sing();
绑定事件函数 (this 指向的是函数的调用者)
1 2 3 4 var btn = document .querySelector('button' );btn.onclick = function ( ) { console .log('绑定时间函数的this -> ' + this ); };
定时器函数 (this 指向的也是 window)
1 2 3 window .setTimeout(function ( ) { console .log('定时器的this -> ' + this ); }, 1000 );
立即执行函数 自动调用,不需要调用 (this 还是指向 window)
1 2 3 4 (function ( ) { console .log('4.人生的巅峰' ); console .log('立即执行函数的this -> ' + this ); })();
改变函数内 this 指向
方法
作用
call()
调用函数; 改变函数内的 this 指向 (主要作用可以实现继承)
apply()
主要作用同 call()
, 但是它的参数必须是数组 (利用 apply 借助于数学内置对象求数组最大值 )
bind()
不会调用原来的函数; 返回的是原函数改变 this 之后产生的新函数
1 2 3 4 5 6 7 8 9 10 11 12 13 var btns = document .querySelectorAll('button' );for (var i = 0 ; i < btns.length; i++) { btns[i].onclick = function ( ) { this .disabled = true ; setTimeout (function ( ) { this .disabled = false ; }.bind(this ), 2000 ); } }
严格模式 'use strict'
变量名必须先声明再使用
不能随意删除已经声明好的变量
全局作用域中函数中的 this 是 undefined
如果构造函数不加 new 调用, this 指向的是 undefined, 如果给他赋值则会报错
定时器 this 还是指向 window
函数里面的参数不允许有重名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <script> 'use strict' ;</script> function fn ( ) { 'use strict' ; } function fun ( ) { }
高阶函数 1 2 3 4 5 6 7 8 9 function fn (a, b, callback ) { console .log(a + b); callback && callback(); } fn(1 , 2 , function ( ) { console .log('我是最后调用的' ); });
闭包 指有权访问另一个函数作用域中变量的函数(像立即执行函数就是),其作用是延伸了变量的作用范围
来几个应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 var lis = document .querySelector('.nav' ).querySelectorAll('li' );for (var i = 0 ; i < lis.length; i++) { lis[i].index = i; lis[i].onclick = function ( ) { console .log(this .index); } for (var i = 0 ; i < lis.length; i++) { (function (i ) { lis[i].onclick = function ( ) { console .log(i); } })(i); for (var i = 0 ; i < lis.length; i++) { (function (i ) { setTimeout (function ( ) { console .log(lis[i].innerHTML); }, 3000 ) })(i); } var car = (function ( ) { var start = 13 ; var total = 0 ; return { price: function (n ) { if (n <= 3 ) { total = start; } else { total = start + (n - 3 ) * 5 } return total; }, yd: function (flag ) { return flag ? total + 10 : total; } } })(); console .log(car.price(5 )); console .log(car.yd(true )); console .log(car.price(1 )); console .log(car.yd(false )); var name = "The Window" ;var object = { name: "My Object" , getNameFunc: function ( ) { return function ( ) { return this .name; }; } }; console .log(object.getNameFunc()()) var f = object.getNameFunc();console .log(f())var name = "The Window" ; var object = { name: "My Object" , getNameFunc: function ( ) { var that = this ; return function ( ) { return that.name; }; } }; console .log(object.getNameFunc()())
递归函数 函数内部自己调用自己
1 2 3 4 5 6 7 8 function fb (n ) { if (n === 1 || n === 2 ) { return 1 ; } return fb(n - 1 ) + fb(n - 2 ); } console .log(fb(6 ));
拷贝
浅拷贝:只是拷贝一层,更深层次对象级别的只拷贝引用(地址),一改全改(指向一个地址)
深拷贝:每一级别的数据都会拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 var obj1 = { id: 1 , name: 'andy' , msg: { age: 18 }, color: ['pink' , 'red' ] }; var o1 = {};function deepCopy (newobj, oldobj ) { for (var k in oldobj) { var item = oldobj[k]; if (item instanceof Array ) { newobj[k] = []; deepCopy(newobj[k], item) } else if (item instanceof Object ) { newobj[k] = {}; deepCopy(newobj[k], item) } else { newobj[k] = item; } } } deepCopy(o1, obj1); console .log(o1); var arr = []; console .log(arr instanceof Object );o1.msg.age = 20 ; console .log(obj1);
正则表达式 创建方法:
利用 RegExp(正则表达式) 对象来创建 - 万物皆对象 -
利用字面量创建正则表达式
test 方法用来检测字符串是否符合正则表达式要求的规范
呃,细节太多不好学,直接看代码吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 var reg = /^abc/ ;console .log(reg.test('abc' ));console .log(reg.test('babcd' )); console .log(reg.test('aabcd' )); console .log('---------------------------' );var reg1 = /^abc$/ ;console .log(reg1.test('abc' ));console .log(reg1.test('abcd' )); console .log(reg1.test('abcabc' )); var rg = /[abc]/ ; console .log(rg.test('andy' ));console .log(rg.test('color' ));var rg1 = /^[abc]$/ ; console .log(rg1.test('aa' )); console .log(rg1.test('a' ));console .log(rg1.test('c' ));console .log(rg1.test('abc' )); console .log('------------------' );var reg = /^[a-z]$/ ; console .log(reg.test('a' ));console .log(reg.test('z' ));console .log(reg.test(1 )); console .log(reg.test('A' )); var reg1 = /^[a-zA-Z0-9_-]$/ ; console .log(reg1.test('a' ));console .log(reg1.test('B' ));console .log(reg1.test(8 ));console .log(reg1.test('-' ));console .log(reg1.test('_' ));console .log(reg1.test('!' )); console .log('----------------' );var reg2 = /^[^a-zA-Z0-9_-]$/ ;console .log(reg2.test('a' )); console .log(reg2.test('B' )); console .log(reg2.test(8 )); console .log(reg2.test('-' )); console .log(reg2.test('_' )); console .log(reg2.test('!' ));
ES6 let/ const
使用 let 关键字声明的变量具有块级作用域,var关键字是不具备这个特点的
防止循环变量变成全局变量
使用 let关键字声明的变量没有变量提升 (即不能先打印再声明)
使用 let关键字声明的变量具有暂时性死区特性 (使用了 let 声明变量,则外部同名变量无效)
const 就不多说了
解构 数组解构 允许按照一一对应的关系从数组中提取值,然后将值赋值给变量
1 2 3 4 5 6 7 8 let ary = [1 , 2 , 3 ]; let [a, b, c, d, e] = ary; console .log(a) console .log(b) console .log(c) console .log(d) console .log(e)
对象解构 允许使用变量的名字匹配对象的属性,匹配成功,将对象属性的值赋值给变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let person = { name: 'lisi' , age: 30 , sex: '男' }; let { name, age, sex } = person; console .log(name) console .log(age) console .log(sex) let { name: myName } = person; console .log(myName)
箭头函数 箭头函数是用来简化函数定义语法的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const sum = (n1, n2 ) => n1 + n2; const result = sum(10 , 20 );console .log(result)const fn1 = v => { console .log(v); } fn1(20 ) function fn2 ( ) { console .log(this ); return () => { console .log(this ) } } const obj = { name: 'zhangsan' }; const resFn = fn2.call(obj); resFn();
剩余参数 跟 python 的很像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const sum1 = (...args ) => { let total = 0 ; args.forEach(item => total += item); return total; }; console .log(sum1(10 , 20 ));console .log(sum1(10 , 20 , 30 ));let ary1 = ['张三' , '李四' , '王五' ];let [s1, ...s2] = ary1;console .log(s1)console .log(s2)
扩展运算符
1 2 3 4 5 let ary = ["a" , "b" , "c" ];console .log(...ary) console .log("a" , "b" , "c" )
应用于数组合并 — 既然是把数组拆了,那再加上 [] 就又变成数组了
1 2 3 4 5 let ary1 = [1 , 2 , 3 ];let ary2 = [4 , 5 , 6 ];let ary3 = [...ary1, ...ary2];console .log(ary3)
1 2 3 4 5 6 var oDivs = document .getElementsByTagName('div' ); console .log(oDivs)var ary_ = [...oDivs]; ary_.push('a' ); console .log(ary_);
扩展方法 Array
from()
: 将伪数组转换为真正的数组,还可以接受第二个参数:箭头函数
find()
: 找到第一个符合条件的数组成员并返回,没有找到则返回 undefined
finfindex()
: 找到第一个符合条件的数组成员位置,没有找到则返回 -1
includes()
: 数组是否含有给定值,返回布尔值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 var arrayLike = { 0 : "张三" , 1 : "李四" , 2 : "王五" , length: 3 } var ar = Array .from(arrayLike);console .log(ar)var arrayLike1 = { 0 : "1" , 1 : "2" , length: 2 } var ar1 = Array .from(arrayLike1, item => item * 2 )console .log(ar1)var a = [{ id: 1 , name: '张三' }, { id: 2 , name: '李四' }]; let target = a.find(item => item.id == 1 );console .log(targetlet ary0 = [10 , 20 , 50 ];let index = ary0.findIndex(item => item > 15 ); console .log(index)let ary4 = ["a" , "b" , "c" ];let result = ary4.includes('a' ) console .log(result)result = ary4.includes('e' ) console .log(result)
String
startWith()
: 参数字符串是否在原字符串的头部,返回布尔值
endWith()
: 参数字符串是否在原字符串的尾部,返回布尔值
repeat()
: 将原字符串重复 n 次,返回一个新的字符串
1 2 3 4 5 6 let str = 'Hello ECMAScript 2015' ;let r1 = str.startsWith('Hello' ); console .log(r1);let r2 = str.endsWith('2020' ); console .log(r2)console .log('y' .repeat(5 ))
模板字符串 使用反引号定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 let name = `张三` ;let sayHello = `Hello, 我的名字叫${name} ` ;console .log(sayHello)let result = { name: "zhangsan" , age: 20 }; let html = ` <div> <span>${result.name} </span> <span>${result.age} </span> </div> ` ;console .log(html)const fn = () => '我是fn函数' let html_ = `我是模板字符串 ${fn()} ` ;console .log(html_)
set 数据结构
Set 类似于数组,但成员的值都是唯一的,没有重复的值
Set 本身是一个构造函数,所以像对象一样 new 一个
可以进行 add、delete、has、clear等操作