javascript
JS基础
简单数据类型
Undefined类型
- 只声明但未初始化
- 只有一个值:undefined
- 用typeof检测返回undefined,typeof返回的值是一个字符串
NUll类型
- 表示空对象指针,用于未来会保存对象的变量初始化
- 只有一个值:null
- 用typeof检测返回object,typeof返回的值是一个字符串
- ==注意==:undefined派生自null(null==undefined为true,但是null == =undefined为false)
Boolean类型
- 只有两个值:true和false
- 转型函数Boolean()
- 数字:除了0和NaN,其余都是true
- 字符串:除了空串都为true
- null,undefined为false
- 对象为true
- 对任意数据类型取反两次!!可以转为布尔值
Number类型
- js中所有的数字都是Number类型
- 二进制0b
- 八进制最高位加0
- 十六进制最高位加0x
- 浮点数在小数点后没有数或小数点后都为0时会被转为整型
- ==注意==:
- 在输出和进行算术运算时都会转换成十进制
- ECMAScript中浮点计算(0.2+0.1)会有误差,因此不要去判断浮点数
数值范围
- 超过Number.MAX_VALUE和-Number.MAX_VALUE的数值会被转成 Infinity和-Infinity
- Number.MIN_VALUE表示的是>0的最小值
NaN
- 任何涉及NaN的操作都会返回NaN(没有字符串连接)
- NaN与任何值都不想等,包括NaN本身
- isNaN()用于测试传入的数值是否能转为数值,如果能则返回false
- ==注意==:
-
typeof NaN为number
-
true能转化为1
-
- isNaN()也适用于对象,对象调用isNaN()函数时首先调用对象自己的valueOf()方法,以确定该方法的返回值是否可以转为数值。如果不能,再基于这个返回值调用tostring()方法,再次测试
数值转换
Number()
- 可以用于任何数据类型
- Boolean值,true返回1,false返回0
- null值,返回0
- undefined值,返回NaN(Number类型)
- 字符串,除空的转为0,有额外字符的转为NaN,其他都转为十进制数
- ==注意==:不能转八进制,因为前导0会忽视
parseInt(,进制)
-
用于将一个字符串中的有效==整数==内容取出来
-
如果第一个字符不是数值或负号,则返回NaN。(空返回NaN)
-
直到解析到非数字字符(包括小数点)停止
-
能够解析八进制和十六进制,加上第二个参数,表示基数是多少进制
==注意==:
- 对于非字符串值会先转为String然后再操作
parseFloat()
- 可以解析第一个小数点
- 只能解析十进制数
- 如果传入的字符是整数,则也会返回整数
String类型
- 转义字符
- 拼接字符串会很慢,字符串的不可变性
- 注意比较运算符的==两边都是==字符串时不会将其转化成数字进行比较,而会分别比较字符串中字符的Unicode编码,一位一位进行比较,如果两位一样则比较下一位,所以==在比较两个字符串型的数字之前一定要转成Number==
转为字符串
toString()
- 除了null,undefined都有该方法
- 参数表示返回数值的进制
- 该方法有返回值,不会影响原变量
String()
- 对于Number和Boolean,实际还是调用toString()方法
- 如果值为null,返回 “null”
- 如果值为undefined,返回“undefined”
+ ""
- 加一个空字符串,隐式类型转换
JS对象
创建对象
-
字面量
1 2 3 4 5 6var obj = { uname: 'xqz', //里面的属性方法采取键值对的形式 sayHi: function () { //方法冒号后面跟的是一个匿名函数 console.log('hi'); } } -
利用Object()
1 2 3 4 5var obj = new Object(); //一个空对象 obj.uname = 'xqz'; obj.sayHi = function () { console.log('Hi'); }; -
构造函数
function Person(){
}
Person() //不加new是普通函数
new Person() //加new是构造函数
1 2 3 4 5 6 7 8 9 10function Star(uname, age, sex) { //构造函数首字母大写 this.name = uname; this.age = age; this.sex = sex; this.sing = function (songs) { console.log(songs); } } var ldh = new Star('刘德华', 19, '男'); //构造函数不需要return ldh.sing('冰雨');
==注意==:
-
构造函数每执行一次就会创建一个新的方法,也就是说所有的实例的sing方法都是唯一的,这样占用了大量的内存空间,完全可以让所有的对象共享一个方法:对象的prototype属性中写
-
对于不再使用的对象,必须设置为null,这样GC才会回收
1 2var person = new Person();//此时仍有变量在引用 var person = null; //此时栈中对堆中的引用断开,对象成为垃圾
使用对象
-
使用属性
obj.uname
obj.[‘uname’]
-
使用方法
obj.sayHi();
hasOwnproperty() 方法验证属性是存在于对象中,还是存在于实例中。在实例中则返回true,在构造函数的prototype中则返回false。 name in Object 只要能通过原型链找到则返回false. hasPrototypeProperty()方法 实例中重写属性后,属性就存在于实例中,原型中的属性就用不到了。
枚举(不明白) 得到所有可枚举的实例属性 Object.keys()方法
Object.assign(default,new) //属性覆盖
遍历对象
|
|
==注意==:
- “属性名” in 对象:可以检查obj中是否有该属性
- obj2=obj1;此时修改obj1中的值会影响obj2因为他们指向的是同一个堆地址,如果让obj1=null,并不会改变obj2的值,只是将obj1的指向断开,堆内存中的值仍然存在
判断对象类型
-
instance of检测是否为该对象类型,Array和Function都是特殊的Object类型
-
typeof
能区别:数值/字符串/布尔值/undefined/function
不能区别:null与Object,Object和Array
-
===只对undefined和null有效,因为只有这两种类型有固定值
-
typeof a(返回值是字符串类型) === ‘undefined’也可以进行判断,注意undefined == =’undefined‘是false,一个是undefined类型,一个是字符串类型
内置对象
Math对象
-
最大值
Math.max()
-
绝对值
Math.abs()
-
取整
-
向下
Math.floor()
-
向上
Math.ceil()
-
四舍五入
Math.round()
==注意==:负数中.5特殊,往大了取
-
-
随机数
-
返回[0,1)之间的小数
Math.random()
-
返回两个数之间的随机整数
1 2 3 4//返回两个数之间的随机整数,并且包含这两个数 function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
-
日期对象
-
返回系统当前时间 new Date()
-
返回自定义的时间
-
参数为数字型
new Date(2020,6,30)
==注意==:返回的月份比实际大1月
-
参数为字符串型
new Date(‘2020–6–30 8:23:45’);
-
-
年
date.getFullYear()
-
月
date.getMouth() + 1(0~11)
-
日
date.getDate()
-
周几
date.getDay() (0-6)
-
时
date.getHours()
-
分
date,getMinutes()
-
秒
date.getSeconds()
-
时间戳(毫秒)
==注意==:是距离1970年1月1日过了多少毫秒
-
date.valueof()
-
date.getTime()
-
+new Date()
-
Date.now()
-
数组对象
创建数组
-
字面量
1var arr = [1, 3, 3, 3] -
利用new Array()
1 2var arr1 = new Array(2); //长度为2的空数组 var arr1 = new Array(2, 3); //等价于[2,3]表示里面有两个数组元素是2和3
==注意==:
- 读取不存在的索引不会报错,返回undefined
- 对于连续的数组,用length会得到数组的长度,对于非连续的数组,length获得数组的最大索引加1
检测是否为数组
- arr instance of Array
- Array.isArray(arr)
增
-
在末尾加, 返回新数组长度
arr.push()
-
在开头加,返回新数组长度
arr.unshift()
-
在指定位置加
splice(开始索引,0,添加的元素) //返回删除的数组,在开始的索引之后增加
删
-
删末尾一个,返回删除的元素
arr.pop()
-
删开头一个,返回删除的元素
arr.shift()
-
删除并在删除位置添加,会改变原数组
splice(开始索引,删除个数,添加的元素)//返回删除的数组
改
splice(开始索引,删除个数,添加的元素)//返回删除的数组
查
根据元素找索引
|
|
findIndex(),返回一个索引
|
|
翻转
arr.reverse(),修改原数组
排序
- 修改原数组,默认按照unicode编码进行排序
- sort里放一个函数如果返回大于0的数则a,b交换位置,如果返回小于0的数则a,b不交换位置
|
|
|
|
合并
arr1.concat(arr2)
不会改变原数组,返回新数组
数组转字符串
- arr.join(连接符) //默认逗号,不会改变原数组,将转换后的字符串作为结果返回
- arr.toString() //逗号分隔
数组截取
arr.slice(开始索引,结束索引(不包含))
==注意==:
- 如果传递一个负值,则从后往前进行计算
- 不会改变原数组
数组遍历
- array.filter(function(currentValue,index,arr), thisValue)//当前元素的值,当前元素的索引,当前元素属于的数组对象
- 不会改变原始数组
- 返回一个新数组
|
|
- some(function(){})
- 用于检测数组中的元素是否满足指定条件
- some()方法会以此执行数组的每个元素:
- ==如果有一个元素满足条件,则表达式返回true==,剩余的元素不再遍历
- 如果没有满足体条件的元素,返回false
==注意==:不能对空数组进行检测
|
|
字符串对象
-
string是简单数据类型,为什么有length属性?
步骤:
- 创建基本类型的一个实例;
- 在实例上调用指定的方法;
- 销毁这个实例;
1 2 3 4 5 6 7 8 9 10var str = "我是string基本类型的值"; var new_str = new String("我是string基本类型的值"); // 包装处理 var my_str = new_str.substring(5,8); new_str = null; // 方法调用之后销毁实例 var str2 = "xqz"; str2.age = 21; console.log(str.age); //undefined //可见,并非string调用了自身的方法,而是后台创建了一个基本包装类型String,从而进行下一步操作。 //基本类型的“销毁性”致使我们不能为基本类型添加属性和方法。 -
==注意==:String,Number,Boolean都是基本包装类型
1 2 3var a = 123; a.hello = "hello"; //这里不报错是因为转为了基本包装类型Number(),给改对象添加了hello属性,而后让new_num=null从而销毁实例 console.log(a.hello);//这里调用a的hello属性不报错,结果为undefined,因为重新又创建了一个Number()实例,此时这个实例中并没有hello属性 -
字符串的不可变性
指的是里面的值不变,其实只是地址变了,内存中开辟了一个内存空间
1 2 3 4 5 6 7 8var str2 = 'andy'; str2 = 'red'; //str从andy指向red,但是andy仍然存在 //因为我们字符串的不可变所以不要大量拼接字符串 var str2 = ''; for (var i = 0; i < 100; i++) { //如果i过大会很卡 str += i; } console.log(str); -
==注意==:字符串的所有方法都不改变自身,都返回一个新的字符串
根据值找索引
|
|
根据索引找值
-
返回字符
str.charAt()
str[]
-
返回ASCII值,unicode编码
str.charCodeAt()
-
str[]
因为在底层字符串是以字符数组的形式保存的
合并
str1.concat(str2)
截取
- str.substr(开始的索引,截取长度) //如果只有一个参数且为负数,则是从后往前
- str.substring(开始索引,结束索引) //结束索引不能为负数,负数会被转为0,如果第二个参数小于第一个参数会自动交换位置
- str.slice(开始索引,结束索引(不包含)) //可以接受负数,会将字符串长度与负数相加作为第二个参数
- 都是返回截取下来的字符串
替换
str.replace(要替换,替换为) //只会换一个
返回一个新的字符串
可以接收正则表达式
|
|
大小写
toUpperCase()
toLowerCase()
去除空格
str.trim()
是否包含
str.includes() //返回bool类型(es6)
搜索指定内容
str.search()
如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到则返回-1,它可以接收正则表达式作为参数来进行搜索
str.search(/a[bef]c/),不能全局匹配,只会查找第一个
提取
|
|
字符串转数组
str.split(以什么分隔符分割该字符串) //返回一个数组
==注意==:
- 根据任意字母来将字符串拆分str.split(/[A-z]/),这个方法不设置全局匹配也会全部拆分;
根据字符编码获取字符
var result = String.fromCharCode()
FormData对象
https://www.jianshu.com/p/e984c3619019
arguments的使用
-
arguments是函数的一个内置对象,只有function()才有,当不确定有几个参数传递时使用
-
arguments是一个伪数组:可以通过索引访问,有length属性,但是没有数组的方法
JS预解析
变量提升
只提升变量名(使用var定义),不提升赋值操作
函数提升
只提升函数声名,不调用函数
==注意==:先执行变量提升,再执行函数提升
-
例题
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 28f1(); console.log(c); console.log(b); console.log(h); function f1() { var h = b = c = 9; //相当于 Var a=9;b=9;c=9;b和c直接赋值 没有var 当全局变量看 //集体声明应该写成 var a=9,b=9,c=9; console.log(h); console.log(b); console.log(c); } //相当于 function f1() { var h; h = 9; b = 9; c = 9; console.log(h); console.log(b); console.log(c); } f1(); console.log(c); console.log(b); console.log(h);//此处报错,h没有声名,因为h的作用域只在f1函数中
JSON
- JS中的对象只有JS自己认识,其他的语言都不认识
- JSON就是一个特殊格式的字符串,可以被任意语言所识别,且可以转成任意语言的对象,JSON在开发中主要用来数据的交互
- JavaScript Object Notation JS对象表示法
==注意==:
- JSON字符串的属性名必须加双引号
分类
- 对象{}
- 数组[]
JSON中允许的值
- 字符串
- 数值
- 布尔值
- null
- 对象
- 数组
JSON转对象
JSON.parse()
- 需要一个JSON字符串作为参数,会将该字符串转为JSON对象
对象转JSON
JSON.stringify()
- 需要一个js对象作为参数,会返回一个JSON字符串
WebAPI
DOM
节点操作

-
nodeType
- 元素节点
- 属性节点
- 文本节点
-
nodeName
-
nodeValue
==注意==:节点操作主要操作元素节点
元素节点和元素对象的区别
1.所谓元素,即html文档里面,所有的标签都可以称之为元素,比如说
、
2.所谓节点,是js为了对html文档进行操作,而开发的,即DOM,文档对象模型。即每个元素都可以称之为一个节点,节点是唯一的。比方来说,《p》标签,肯定是一个p标签元素,那如果通过js对它进行样式控制的时候,就必须获取(找到)到这个元素,称之为节点,如果有好多元素,可以获得第1个、第2个或者第n个。总之,元素是统称,节点是具有唯一性的。
获取节点
| API | 说明 |
|---|---|
| document.getElementById(’’) | 根据id返回元素对象 |
| document.getElementByClassName(’') | 根据类名返回元素对象 |
| document.getElementByTagName(’') | 根据标签名返回元素对象集合(伪数组),可以先获取父元素在获取子元素 |
| document.querySelector(’') | 根据css选择器返回第一个符合条件的元素对象 |
| document.querySelectorAll(’') | 根据css选择器返回所有元素对象 |
| document.body() | 获取body标签 |
| document.documentElement | 获取html标签 |
==注意==:得到的多个都是伪数组
获取父节点
| API | 说明 |
|---|---|
| node.parentNode | 得到的是离元素最近的父级节点 |
获取子节点
| API | 说明 |
|---|---|
| node.children | 得到所有子节点(元素节点) |
| node.children[0] | 得到子节点的第一个元素 |
| node.children[node.children.length-1] | 得到子节点的最后一个元素 |
| node.childNodes | 包括空白的所有子节点 |
| node.firstChild | 包括空白的第一个子节点 |
| node.firstElementchild | 不包括空白的第一个子节点 |
获取兄弟节点
| API | 说明 |
|---|---|
| node.nextElementSibling | 下一个兄弟节点(元素节点) |
| node.previousElementSibling | 上一个兄弟节点(元素节点) |
创建节点
| API | 说明 |
|---|---|
| var child = document.createElement(‘标签名’) | 创建一个节点 |
| document.createTextNode() | 创建文本节点,child.appendChild(textnode) |
| element.innerHTML='' | 创建并且添加 |
添加节点
| API | 说明 |
|---|---|
| node.appendChild(child) | 添加到父节点(node)的子节点列表末尾 |
| node.insertBefore(child,指定元素(node.children[])) | 添加到父节点(node)的指定的子节点之前 |
删除节点
| API | 说明 |
|---|---|
| node.removeChlid(child) | node是一个父节点 |
| node.remove() | 删除自身节点及其子节点 |
复制节点
| API | 说明 |
|---|---|
| node.cloneNode() | 只复制标签 |
| node.cloneNode(true) | 深拷贝,全复制 |
替换节点
| API | 说明 |
|---|---|
| node.replaceChild(new ,old) | 替换节点 |
元素操作
操作元素内容
innerHTML和innerText的区别
-
innerText不识别html标签,且会自动去除空格和换行
-
innerHTML识别html标签,且保留空格和换行
-
这两个属性可读写,可以获取元素里面的内容
1 2 3 4 5 6 7 8 9 10 11//innerText和inner HTML的区别 //1.innerText 不识别HTML标签 去除空格和换行 var div =document.querySelector('div'); div.innerText='<strong>1</strong>'; //2.innerHTML 识别HTML标签 (常用) 保留空格和换行 div.innerHTML='<strong>1</strong>'; //这两个属性可读写 可获取元素里的内容 var p = document.querySelector('p'); console.log(p.innerText); console.log(p.innerHTML);
操作元素属性
获取属性
获取元素自带属性
| API | 说明 |
|---|---|
| element.属性名 | 常见元素自带的属性:src,href,title,alt等,表单元素自带的属性:type,value,disable等,获取class属性时用className获取 |
-
offset系列属性
offset系列属性 作用 element.offsetParent 返回最近一级的带有定位的父元素,没有则返回body==区别==element.parentNode返回最近一级父亲,不管有没有定位 element.offsetTop 返回元素相对带有定位父元素上方的偏移,没有则以body为准 element.oddsetLeft 返回元素相对带有定位父元素左边框的偏移 element.offsetWidth 返回自身包括==边框,padding,内容区==的宽度,返回数值不带单位 element.offsetHeight 返回自身包括边框,padding,内容区的宽度,返回数值不带单位 ==offset与style的区别==
offset style 可以得到任意样式表中的样式值 只能得到行内样式表中的样式值 返回的数值没有单位 返回带有单位的字符串 offsetWidth包括padding+border+width style.width不包括padding和border offsetWidth等属性是只读属性,不能赋值 可读可写 用于获取元素大小 用于更改元素样式值 -
client系列属性
client系列属性 作用 element.clientTop 返回元素上边框的大小 element.clientLeft 返回元素左边框的大小 element.clientWidth 返回自身包括==padding,内容区==的宽度,返回数值不带单位 element.clientHeight 返回自身包括padding,内容区的宽度,返回数值不带单位 -
scroll系列属性
scroll系列属性 作用 element.scrollTop 返回被卷去的上侧距离(overflow:auto;滚动条),返回数值不带单位,有padding从内容离开padding算起,否则边框下沿开始计算 element.scrollLeft 返回被卷去的左侧距离,返回数值不带单位 element.scrollWidth 返回自身不含边框的==实际宽度==(超出的也算进去),返回数值不带单位 element.scrollHeight 返回自身不含边框的==实际高度==(超出的也算进去),返回数值不带单位
==注意==:
- 元素被卷去的头部距离:element.scrollTop获取
- 页面被卷去的头部距离,window.pageYoffset获取
- 说明垂直滚动条滚动到底:scrollHeight-scrollTop == clientHright //用于判断用户是否阅读完协议
获取元素自定义属性
element.getAttribute(‘属性名’)
设置属性
设置元素自带属性
| API | 说明 |
|---|---|
| element.属性名 = ‘’; |
设置元素自定义属性
| API | 说明 |
|---|---|
| element.setAttribute(‘属性名’,‘值’) |
==注意==:修改class属性时
- 用element.==className== ‘’;
- 用element.setAttribute(’==class==’,’’);
==注意==:H5规定自定义属性data开头作为属性名并且赋值:
移除属性
移除元素自定义属性
| API | 说明 |
|---|---|
| element.removeAttribute(’’) |
判断是否有该属性
| API | 说明 |
|---|---|
| element.hasAttribute() | 判断元素属性,而不是css样式表中的样式属性 |
操作元素样式
获取样式属性
| API | 说明 |
|---|---|
| getComputedStyle(element).属性 | 可以获取css样式表的样式,需要两个参数1.需要获取样式的元素2.可传递一个伪元素,一般都传null,该方法会返回一个对象,对象中封装了当前元素对应的样式。 |
| element.style.样式名 | 只能获取行内样式(这里的style就是元素的一个属性,将将样式名修改为驼峰命名) |
设置样式属性
| API | 说明 |
|---|---|
| element.className='' | 会覆盖原来的class,用 += 可以防止覆盖,注意要加空格className += ‘ b2’ |
| element.style.样式名=‘值’ | 添加的是内联样式,所以如果在样式中写了important,js就无法修改了(这里的style就是元素的一个属性) |
动画函数的封装
动画函数原理
定义一个setInterval的定时器,函数里对元素的样式进行操作
|
|
动画函数简单封装
|
|
缓动动画函数封装
|
|
三种动态创建元素的区别
-
document.write()会导致文档流重绘
-
element.innerHTML = ''
-
拼接字符串,很慢
解决方法:存入数组中,一次性渲染,很快
1 2 3 4 5 6 7 8 9 10 11 12var inner = document.querySelector('.inner'); inner.innerHTML = '<a href="#">百度</a>'; // 创建多个字符串拼接的时候特别慢效率低 // 但是用数组的形式拼接是最快的 var arr = []; var date1 = Date.now(); for (var i = 0; i < 1000; i++) { arr.push('<a href="#">9</a>'); } inner.innerHTML = arr.join('');//数组转字符串 var date2 = Date.now(); console.log(date2 - date1);
-
var child = document.createElement();
node.appendChild(child);
比2慢,比1快
事件
鼠标事件
| 事件 | 说明 |
|---|---|
| onclick | 点击 |
| onmouseover/onmouseenter | 移入 |
| onmouseout/onmouseleave | 移出 |
| onmousedown | 按下 |
| onmouseup | 松开 |
| onmousemove | 移动 |
| onwheel | 鼠标滚轮,e.datail(火狐)或者e.wheelDelta |
==注意==:mouseover和mouseenter的区别:mouseenter不会冒泡,简单的说,它不会被它本身的子元素的状态影响到.但是mouseover就会被它的子元素影响到,在触发子元素的时候,mouseover会冒泡触发它的父元素.(想要阻止mouseover的冒泡事件就用mouseenter)
键盘事件
| 事件 | 说明 |
|---|---|
| onkeyup | 松开,不区分大小写 |
| onkeydown | 会在文字还没进入文本框前就添加事件,不区分大小写,一直按着某个按键不松手,事件会连续触发,第一次和第二次之间会间隔稍微长一点,其他会特别快 |
| onkeypress | 不识别功能按键,如ctrl。区分大小写,触发比onkeydown慢 |
表单事件
| 事件 | 说明 |
|---|---|
| onfocus | 获得焦点,无冒泡 |
| onblur | 失去焦点,无冒泡 |
| onchange | 在元素值改变时触发,适用于input,textarea,select元素 |
| onselect | 在文本框内容被选中时触发,适用于单选框,多选框 |
编辑事件
| 事件 | 说明 |
|---|---|
| oncopy | 在拷贝时触发 |
| onselect | 在文本框内容选中时触发,return false让用户无法选中 |
| oncontentmenu | 鼠标右击触发,用e.preventDefault()来禁止鼠标右键 |
页面事件
| 事件 | 说明 |
|---|---|
| onload | 等待文档流加载完成后触发 |
| onbeforeunload | 即将离开页面(刷新或关闭)时触发 |
滚动事件
| 事件 | 说明 |
|---|---|
| onscroll | 滚动条滚动触发该事件,给添加了overflow:auto的元素绑定 |
传统事件
注册
element.事件类型 = function(){}
删除
element.事件类型 = null
事件监听器
区别传统
相比传统的onclick=function(){},addEventListener可以让同一元素同一事件可以注册多个监听器,按注册顺序依此执行,而传统的只能写一个,如果写了多个以最后一个为准
注册
| API | 说明 |
|---|---|
| element.addEventListener(’’",function(e){},[true/false]) | 第一个参数事件类型,不用加on,第三个参数默认false,冒泡阶段,true,捕获阶段 |
删除
| API事件 | 说明 |
|---|---|
| element.removeEventListener(’’",函数名,[true/false]) | 第一个参数事件类型,不用加on,第三个参数默认false,冒泡阶段,true,捕获阶段 |
事件对象
事件对象属性
| 属性 | 说明 |
|---|---|
| e.type | 事件类型 |
| e.target | 真正触发事件的那个元素(事件委托:ul和li利用冒泡只需给ul添加点击事件,用e.target获取点击的li) |
事件对象方法
| 方法 | 说明 |
|---|---|
| e.preventDefault() | 阻止默认行为 |
| e.stopPropagation() | 阻止事件冒泡 |
鼠标事件对象
| 属性 | 说明 |
|---|---|
| e.pageX/Y | 相对于文档页面(图片跟随鼠标移动,图片要绝对定位) |
| e.clientX/Y | 相对于浏览器的可视窗口 |
| e.screenX/Y | 相对于电脑屏幕 |
| e.offsetX/Y | 相对于带有定位的父盒子的xy坐标 |
键盘事件对象
| 属性 | 说明 |
|---|---|
| e.altKey | |
| e.ctrlKey | |
| e.shiftKey | 是否按下shift |
| e.keyCode | 键盘输入的ascll码 |
DOM事件流
传统和监听器一般都是得到冒泡阶段,把addEventListener第三个参数改为true则能得到捕获阶段
捕获阶段
document=>html=>body=>father=>son(如果father有监听事件,先执行father的,再执行son的)
冒泡阶段
于捕获相反,取消冒泡:e.cancelBubble=true,点击了子元素,点击事件冒泡到父元素
==注意==:onblur,onfocus,onmouseenter,onmousemove没有冒泡
事件委托
原理:将事件监听器设置在父节点上,利用冒泡原理影响每个子节点,用e.target获取按下的那个元素
|
|
BOM
Window对象是浏览器的顶级对象
- 它是JS访问浏览器窗口的一个接口
- 它是一个全局对象。定义在作用域中的变量,函数会变成window对象的属性和方法
==注意==:window下的一个特殊属性:window.name
window对象
==浏览器内核常见模块:==
js引擎模块、html,css文档解析模块、DOM\CSS模块、布局和渲染模块、定时器模块、事件响应模块、网络请求模块。
location属性
location是一个对象,用于获取或设置窗体的URL,并且可以用于解析,如果直接打印location,返回的是地址栏的信息
-
属性
属性 说明 window.location.href 返回当前页面的URL location.host 返回主机域名 location.port 返回端口号 location.pathname 返回路径 location.hash 返回片段 #后面的内容 常见于链接 锚点 window.lacation.search 返回参数:?键=值(var arr=substr(1).split(“=”)) -
方法
方法 说明 assign() 与改变href属性一样可以跳转页面,可以后退,和直接修改location一样 replace() 替换当前页,不记录历史,无法后退 reload() 重新加载页面,若参数为true会强制刷新,相当于浏览器上的刷新按钮
|
|
navigator属性
包含有关浏览器的信息,常用window.navigator.userAgent,返回由客户机发送服务器的user-agent头部的值,用正则进行匹配
==注意==:
- ie11已经不能用useragent判断浏览器了,但是ie中有ActiveXObject对象属性,通过判断页面一这个属性来知道是不是ie浏览器
histroy属性
| 方法 | 说明 |
|---|---|
| back() | 后退,相当于浏览器上的按钮 |
| forward() | 前进 |
| go(1/-1) | 1前进一个页面,-1后退一个页面,-2后退两个页面 |
| length | 当此访问的链接的数量 |
其他常见属性
| 属性 | 说明 |
|---|---|
| window.page(Y/X)offset | 获取页面卷去的头部/左侧 |
| window.scroll(x,y) | x,y不加单位,滚定至文档中的特定位置 |
| window.innerWidth | 返回窗口宽度,无单位 |
window事件
| 事件 | 说明 |
|---|---|
| window.onload=funtion(){}/window.addEventListenter(’load’,function(){}) | 在文档内容(css,js,html)全部加载完成后触发 |
| window.onDOMContentLoaded | 在DOM加载完成后就触发 |
| window.onresize | 调整窗口大小时触发 |
定时器
setTimeout
-
创建
会返回一个定时器ID给变量
var time = window.setTimeout(回调函数,[延迟的毫秒数])//在定时器到期后执行回调函数,==只调用一次==
-
清除
clearTimeout(定时器ID)
setInterval
-
创建
var time = window.setInterval(回调函数,[延迟的毫秒数])//每隔延迟的时间就调用一次,==会重复调用==
-
清除
clearInterval(定时器ID),可以接收任何参数,如果参数是undefined或者null则什么也不做
|
|
this指向问题
- 在全局作用域,定时器,普通函数中this指向window,==注意==:箭头函数中的this指向上下文对象
- 方法中的this指向调用者
- 构造函数中的this指向实例
JS执行对列
同步任务在主线程执行,形成一个执行栈。当有异步任务时,如ajax,DOM待触发事件,定时器。放入异步进程处理,触发后放入任务队列(异步队列),等待主线程执行完毕后,通过事件循环机制来任务队列中取出任务执行

JS高级
类和对象
-
关键字:class
注意:类中所有函数不需要加function关键字,多个方法间不加逗号分隔.
-
方法中的this指向:方法的调用者
构造器
-
关键字:constructor()
-
作用:用于传递参数,返回实例对象,new生成对象实例时自动调用。
注意:如果未定义会自动创建一个constructor()
-
this指向:实例对象
|
|
注意:
this的指向问题
|
|
类的继承
关键字
-
entends
-
注意:ES6中类没有变量提升,必须先定义类,才能实例化
继承属性
调用父类构造函数:
- 关键字:super(x,y)
注意:在constructor中调用,且必须在子元素的this之前调用
|
|
继承方法
-
子类实例会自动继承父类的方法
-
在子类中调用父类方法:
- 关键字:super.父类方法名()
|
|
-
扩展子类的方法
|
|
构造函数和对象
-
利用构造函数创建对象,首字母要大写(之前还有利用new Object(), 字面量的方法创建对象)
-
通过this添加实例成员和实例方法
-
构造函数名.属性名 || 方法名,添加静态成员和静态方法
==注意==:静态成员和方法只能通过构造函数来访问
1 2 3 4 5 6 7 8 9 10 11 12 13function Star(uname, age) { this.uname = uname;//实例成员 this.age = age; this.sing = function () { console.log('我会唱歌'); } } var ldh = new Star('刘德华', 13); Star.sex = '男';//静态成员 Star.dance = function () { console.log('dance'); }//静态方法 console.log(Star.sex);
构造函数原型:prototype(原型对象)
-
构造函数通过原型分配的函数是所有对象所共享的
-
每一个构造函数都有一个prototype属性,这个属性就是一个对象,它所拥有的所有属性和方法,都会被构造函数所拥有,包函constructor指回构造函数,和proto属性指向父级的prototype
-
每一个实例对象也都有一个_proto_属性,也就是对象原型,指向构造函数的prototype
注意:一般公共的属性定义到构造函数里面,公共的方法放入原型对象中
|
|
对象原型:proto
- 每个实例对象都会有一个属性proto向构造函数的prototype,但最终又通过prototype里的constructor指回构造函数
- 每一个构造函数的prototype(原型对象)中也有一个proto属性,指向父级构造函数的prototype
方法查找规则
- 先看实例对象身上有没有a方法
- 如果没有,通过proto指向去构造函数的prototype里找有没有
- 如果没有,通过prototype执向父级构造函数的prototype里找有没有,直到找到object为止
注意:
- 通过proto到prototype中找到的属性用person.hasOwnProperty()去查找属性返回false,通过in查找返回true
- 在打印对象时会自动掉用Object中的toString()方法,如果不想用Object中的方法,可以给对象添加toString()方法
constructor
-
proto中有一个constructor,最终通过prototype指回构造函数
-
prototype中有一个constructor,指回构造函数
注意:如果prototype被覆盖了,需要重新将constructor:构造函数名(重新指回构造函数)
原型链

|
|
==注意==:
-
Object是对象也是函数,Object.proto===Function.prototype,Object是Function的实例
-
function也是==Function(构造函数)==的实例 new Function(),Star.proto->Function.prototype
-
Function也是Function的实例,Function.proto = Function.prototype
-
Star.prototype.proto->Object.prototype
-
ldh.proto->Star.prototype,Star.prototype.proto->Object.prototype
成员查找机制
- 当访问一个对象的属性(包括方法时),首先查找这个对象自身有没有该属性
- 如果没有就查找它的原型(也就是proto指向的prototype原型对象)
- 如果还没有就查找原型对象的原型
- 以此类推直到Object为止(null)
- proto对象原型的意义就在于为对象成员查找机制提供一个方向路线
instance of

通俗一点来讲,instanceof的判断规则是:instanceof会检查整个原型链,将沿着A的__proto__这条线来一直找,同时沿着B的prototype这条线来一直找,直到能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。即上图中的 f1–>__proto__ 和 Foo–>prototype 指向同一个对象,console.log(f1 instanceof Foo)为true。
this指向
- 在构造函数中,里面的this指向的是实例对象
- prototype中的this也指向实例对象,因为实例对象调用原型对象里面的方法
|
|
改变this指向
this指向的4种形式
- 一般函数,this指向全局对象window
- 在严格模式下,为undefined
- 对象的方法里调用,this指向调用该方法的对象
- 构造函数里的this,指向创建出来的实例
- 箭头函数中this指向上下文
call
- 第一个参数:改变this指向
- 第二个参数:实参
- 使用时候会自动执行函数
|
|
apply
- 第一个参数:改变this指向,在函数运行时才会改变this指向
- 第二个参数:数组(里面为实参)
- 使用时候会自动执行函数
- 主要应用:Math.max.apply(Math,arr)//这里this的指向还是Math不过可以比较数组中的最大值
==注意==:
- call和apply这两个方法都是函数对象的方法,需要通过函数对象来调用
- 调用call和apply会将一个对象指定为第一个参数,此时这个对象会称为函数执行时的this
- call(obj,2,3)方法可以将实参在对象之后依次传递,apply需要将实参封装到数组中统一传递
bind
- 第一个参数:改变this指向
- 第二个参数之后:实参
- 返回值为一个新的函数
- 使用的时候需要手动调用下返回 的新函数(==不会自动执行==)
原型继承
继承属性
通过构造函数+原型对象模拟实现继承,称为组合继承
原理:同call()把父类型的this改为子类型的this
|
|
继承方法
直接给构造函数添加的是静态方法,给构造函数的prototype添加的是实例方法
原理:创建一个父类的实例,让子类的原型对象执向这个实例所在的内存空间,但是子类的prototype里的constructor被覆盖了,需要重新指向子类构造函数,这样就能通过父类实例的中的proto找到父类中的方法,且在子类中添加自己的私有方法也不会影响父类。
|
|
扩展内置对象
|
|
Web Workers
- 主线程才能操作dom,web workers可以将大计算量的代码另外开一个线程去计算,从而防止冻结用户界面
|
|
|
|
缺点
- 慢
- 不能跨域加载js
- worker内代码不能访问DOM
- 浏览器兼容问题
函数
- 函数也是一个对象
- 函数不会检查实参类型和数量,少了则为undefined,多了则忽略
- return后的语句不会执行,return;后面不跟值相当于返回undefined,不写return也返回undefined。使用return结束整个函数
- 函数对象也可以return
- 实参会存到arguments(伪数组)中,函数中不定义形参也能使用,arguments有一个属性callee,是当前正在执行得函数对象
定义
-
命名函数
function fn(){ }
-
匿名函数
var fun = function() {}
-
new Function(‘参数1’,‘参数2’,‘函数体’)
var f = new Function(“xxxx ”);
==注意==:所有函数都是Function的实例

执行上下文栈
- 在全局代码执行前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象
- 在全局执行上下文(window)确定后,将其添加到栈中
- 在函数执行上下文创建后,将其添加到栈中(压栈)
- 在当前函数执行完后,将栈顶的对象移除(出栈)
- 当所有的代码执行完后,栈中只剩下window
|
|
调用方式和this指向
- 解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象
-
普通函数
fn();//实际上是windows.fn()
this指向windows
-
对象的方法
obj.xxx();
this指向对象
-
构造函数里的方法
function xxx(){}
new xxx();
this指向实例,包括构造函数的prototype原型对象里的this也指向实例
-
事件函数
btn.onclick=function(){}
this执向调用者btn
-
定时器函数
setInterval(function(){},1000)//实际上是windows.setInterval
this指向window,只能用bind(this)改变this指向,因为call和apply是立即执行。
-
立即执行函数
(function(){})()或者(function (){} ())
this 指向windows
高阶函数
它接收函数作为参数,将函数的返回值作为输出
|
|
另外,JS的回调函数同样是以实参形式传入其他函数中,这也是高阶函数(在函数式编程中回调函数被称为 lambda表达式):
|
|
闭包
变量作用域
- 局部变量(函数作用域)
- 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁
- 每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的
- 在函数作用域中可以访问全局变量,反之不行
- 当在函数作用域中操作一个变量时,有则直接使用。没有,则去上一级作用域中去寻找
- 定义形参就相当于var 定义变量
- 全局变量(全局作用域)
- 在打开页面时创建,关闭页面时销毁
- 直接编写在script标签中的js代码,都在全局作用域
- 在函数中不用var定义的变量也在全局作用域中
- 全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用
- 创建的变量都变成window对象的属性,创建的函数都变成window对象的方法
- 当函数执行完毕,本作用域内的局部变量就会自动销毁
闭包的产生
- 当一个嵌套的内部函数引用了嵌套的外部函数的变量(函数),就产生了闭包
- 通过chrome的debug调试查看closure就是闭包
闭包的定义
指有权访问另一个函数作用域中变量的函数
闭包的作用
在函数a执行完毕并返回后,闭包使得Js的垃圾回收机不会回收a所占用的资源,因为a的内部函数b需要依赖a中的变量,从而延伸了变量的作用范围(生命周期)。
闭包的生命周期
产生:在嵌套内部函数定义执行完成时就产生了(不是在调用时)
死亡:在嵌套的内部函数成为垃圾对象时
demo
|
|
闭包的例子
获取ul中li的索引号
- 最初的方法
|
|
- 利用闭包
|
|
这里面的闭包指的是匿名函数,通过(i)把值保存到了num中。每个点击事件都有一个局部变量num,num保存的是相应的i值。
- 错误写法
|
|
每个li标签的onclick事件执行时,本身onclick绑定的function的作用域中没有变量i,i为undefined,则解析引擎会寻找父级作用域,发现父级作用域中有i,且for循环绑定事件结束后,i已经赋值为4,所以每个li标签的onclick事件执行时,log的都是父作用域中的i,也就是4。
经典例子
|
|
直接调用fn函数,此时fn执行完后,就连同它的变量num一同销毁,但是如果将fn的返回值赋给f1,这时候相当于f1=function(){var n = 0};并且匿名函数内部引用这fn里面的变量num,所以变量num无法被销毁,而变量n在调用完后会销毁,在每次调用时新建,于是最后只剩下num,所以再次调用时num是在4的基础上+1。
定时器中的闭包函数
|
|
闭包的应用:定义js模块
|
|
|
|
闭包的缺点
因为闭包会使得Js的垃圾回收机不会回收占用的资源,滥用闭包会造成内存泄露,所以在必要时,我们要及时释放这个闭包函数
内存溢出与内存泄漏
内存溢出:栈溢出,堆溢出
内存泄露:内存泄漏积累多了就容易导致内存溢出
常见的内存泄漏:
- 意外的全局变量
- 没有及时清理的计时器或回调函数
- 闭包
Let的出现
将上面的错误写法中的var改为let,let会产生块级作用域
|
|
递归
函数内部自己调用自己,作用和循环一样
注意:防止发生栈溢出,所以要加退出条件return
|
|
浅拷贝和深拷贝
-
浅拷贝只是拷贝一层,更深层次的对象级别的只拷贝引用(修改数据会修改原来的)
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 26var obj1 = { name: 'zs', age: 18, sex: '男', dog: { name: '金毛', age: 2, yellow: '黄色' } } var obj2 = {}; function copy(o1, o2) { for (var key in o1) { o2[key] = o1[key]; } } copy(obj1, obj2); // 修改obj1中的成员 obj1.name = 'xxxx'; obj1.dog.name = '大黄'; console.dir(obj2); // name 属性深拷贝,不改变;dog对象浅拷贝, dog.name 随之发生改变ES6语法糖:Object.assign(new,old)
-
深拷贝拷贝多层,每一级的数据都会拷贝
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// 定义一个深拷贝函数 接收目标target参数 function deepClone(target) { // 定义一个变量 let result; // 如果当前需要深拷贝的是一个对象的话 if (typeof target === 'object') { // 如果是一个数组的话 if (Array.isArray(target)) { result = []; // 将result赋值为一个数组,并且执行遍历 for (let i in target) { // 递归克隆数组中的每一项 result.push(deepClone(target[i])) } // 判断如果当前的值是null的话;直接赋值为null } else if(target===null) { result = null; // 判断如果当前的值是一个RegExp对象的话,直接赋值 } else if(target.constructor===RegExp){ result = target; }else { // 否则是普通对象,直接for in循环,递归赋值对象的所有值 result = {}; for (let i in target) { result[i] = deepClone(target[i]); } } // 如果不是对象的话,就是基本数据类型,那么直接赋值 } else { result = target; } // 返回最终结果 return result; }==注意==:先判断数组再判断对象,因为数组也属于对象,如果对象中没有function和RegExp且为json对象可以先用
JSON.stringify转为字符串再用JSON.parse转为新的对象
正则
创建
|
|
检测
|
|
特殊字符
边界符
-
^:行首文本以谁开始
-
&:行尾文本以谁结束
-
\bxxx\b:表示单词边界
/^abc$/
字符类
-
:中括号里的内容是或的关系
1 2 3 4 5 6/[abc]/ 表示包含有a或b或c的一个或多个 /^[abc]$/ 表示有且仅有其中一个 /[^abc]/ 除了中括号里的
量词符
用于设定每个模式出现的次数
| 量词 | 说明 |
|---|---|
| * | 重复0次或更多次,相当于{0,} |
| + | 重复一次或更多次,相当于{1,} |
| ? | 重复0次或一次,相当于{0,1} |
| {n} | 重复n次 |
| {n,} | 重复n次或更多次 |
| {n,m} | 重复n次到m次(中间无空格) |
|
|
正则中的预定义类
| 预定义类 | 说明 |
|---|---|
| \d | 匹配0-9之间的任一数字 |
| \D | 匹配0-9以外的字符,相当于/[^0-9]/ |
| \w | 匹配任意的字母,数字和下划线,相当于/[A-Za-z0-9_]/ |
| \W | 除了所有字母,数字和下划线以外的字符,相当于/[^A-Za-z0-9_]/ |
| \s | 匹配空格(包括换行符,制表符,空格符等),相当于[\t\r\n\v\f],去除开头和结尾空格/^\s*|\s*$/ g |
| \S | 匹配非空格的字符,相当于/[^\t\r\n\v\f]/ |
正则中的替换
-
replace(//,’’)只替换第一个,加上/g全局替换
1 2 3btn.onclick = function () { div.innerHTML = text.value.replace(/激情|gay/g, '**'); }
修饰符
- /g:全局匹配
- /i:忽略大小写
- /gi:全局匹配且忽略大小写
| [ ] | 中括号里的内容是或的关系 |
| [ab] | a|b |
| [a-z] | 任意小写字母 |
| [A-Z] | 任意大写字母 |
| [A-z] | 任意字母 |
| /a[bde]c/ | 检测一个字符串中是否含有abc或adc或aec |
| /[^]/ | 除了中括号里的都行 |
ES5
严格模式
为脚本开启‘use strict’写在script标签第一行
为函数开启写在函数体第一行
特点
-
变量必须先声名
==区别:==标准模式中
a=2||this.a=2是给window对象的一个属性,可以用delete删除
var a=2也是给window对象一个属性,但是不能用delete删除
-
全局作用域中this是undefined,而不是windows对象
-
构造函数不加new调用(不创建实例)的话会报错,因为严格模式中this为undefined,要new之后this才有指向的实例对象,标准模式中构造函数没有实例对象,它的this也是指向window对象的
==注意:==定时器的this还是指向window
-
参数不能同名
JSON对象
写法:
- 只能用双引号
- 所有名字都必须用双引号包起来
JSON对象转JSON字符串
JSON.stringify(json)
JSON字符串转JSON对象
JSON.parse(json)
JSON的简写
名字和值一样时保留一样即可
|
|
json中方法的简写
ES6中可以和面向对象中的方法一样把function删除
|
|
Object扩展
常用的三个静态方法
Object.create(prototype,[descriptors])
作用:
-
以指定对象为原型创建新的对象(通过__proto__可以找到)
-
为新的对象指定新的属性,并对属性进行描述
value:指定值
writable:标识当前属性值是否可以修改,默认为false
configurable:标识当前属性是否可以被删除,默认为false
enumberable:标识当前属性是否能用for in 枚举 默认为 false

Object.defineProperty()
- 定义对象中新属性或修改原有的属性
- obj:目标对象
- prop:要增加或修改的属性名字
- descriptor:增加或修改的属性所持有的特性
- value:设置属性的值,默认为undefined
- writable:值是否可以重写,默认为false,遍历时就无法遍历出来
- enumerable:目标属性是否可以被枚举,默认为false也遍历不出来
- configurable:目标属性是否可以别删除或者再次修改特性,默认false
|
|
Object.defineProperties(object,descriptors)
作用:
- 为指定对象定义扩展多个属性
- get:用来获取当前属性值的回调函数
- set:用来修改当前属性值的触发回调函数,并且实参即为修改后的值
- 存取器属性:setter,getter一个用来存,一个用来取
|
|
对象本身的两个方法
get propertyName(){}
set propertyName(){}
|
|
Array扩展
indexOf
Array.prototype.indexOf(value) 得到值在数组中的第一个下标
lastIndexOf
Array.prototype.lastIndexOf(value) 得到值在数组中的最后一个下标
forEach
Array.prototype.forEach(function(item,index){}) 遍历数组
- array.forEach(function(currentValue,index,arr)) 遍历每个元素,将每个元素的返回值给回调函数
- 数组中有几个元素函数就会执行几次,每次执行时,浏览器会将遍历到的元素以实参的形式传递进来,我们可以来定义形参来读取这些内容
- 浏览器会在回调函数中传递三个参数
- currentValue:数组当前项的值
- index:数组当前项的索引
- arr:数组对象本身
==注意==:如果return false会阻止函数继续向下执行,但不会结束遍历,会继续遍历下一个元素,无返回值
|
|
Array.prototype.map(function(item,index){}) 遍历数组返回一个新数组,返回加工后的值
map
映射,给多少处理完后还多少
map() 方法==返回一个新数组==,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
|
|
filter
Array.prototype.filter(function(item,index){}) 遍历过滤出一个新的子数组,返回条件为true的值
- array.filter(function(currentValue,index,arr))会==返回一个新的数组==,新数组中是通过检查指定数组中符合条件的所有元素,主要用于筛选数组
- 通过return true或false来决定保留不保留
注意:直接返回新数组
|
|
some
array.some(function(currentValue,index,arr))用于查找数组中是否有满足条件的元素
==注意==:
- 返回的是布尔值,找到返回true且找到后不会再继续执行,找不到返回false。
|
|
区别:foreach和filter不会终止迭代,some检测到符合要求的元素后会停止,且返回值三者不同
reduce(参数一,参数二)
参数一是回调函数
参数二是tmp的默认值,0
进去一堆,出来一个
- tmp为中间结果,是函数返回的结果,当遍历到数组最后一个元素是=0时,函数的返回值则为最终结果
- item为数组中的每一项
- index为数组索引
|
|
Function扩展
Function.prototype.bind()

ES6
let
-
产生块级作用域
-
for循环中防止i变成全局变量
-
let无变量提升(js预解析会把var和function(){}提到最前面)
-
暂时性死区
-
不能重复声明相同的变量名
1 2 3 4 5 6var tmp = 123; if (true) { tmp = 'avd'; // let tmp;如果在if中需要用一样的变量名,用let声名 } console.log(tmp);1 2 3 4 5 6 7 8 9 10 11<script> let arr = []; for (let i = 0; i < 2; i++) { arr[i] = function () { console.log(i); } } arr[0](); arr[1](); //每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的,函数执行时输出的是自己的上一级(循环产生的块级作用域)作用域下的i值 </script>
const
-
用来声名常量,值无法更改
-
也具有块级作用域,不存在变量提升
1 2 3 4 5 6 7 8if (true) { const a = 10; if(true){ const a=20; console.log(a); } console.log(a); } -
必须赋初始值
-
赋值后的内存地址不能修改,但是复杂数据类型内的值可以改
1 2 3const arr=[100,100]; arr[0]='a';//这里没有修改内存地址,所以是可以修改的 arr=['a',100];//这里修改了内存地址,所以是无法修改的
解构赋值
如果解构后无值则为undefined
|
|
箭头函数
-
不能使用argunments来获取参数
-
函数体只有一句可以省略大括号
-
只有一个参数可以省略括号
-
箭头函数不绑定this关键字,箭头函数中的this指向的是函数定义位置上下文的this(所处的对象)
- 如果箭头函数外层有函数,箭头函数的this和外层函数的this一摸一样
- 如果外层没有函数,指向window
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20<script> const add = (a, b) => { console.log(a + b); } add(1, 3); const obj = { name: 'zhangsan' } function fn() { console.log(this); return () => { console.log(this);//这里两个this相同 } } const fun = fn.call(obj); fun(); </script>注意:
1 2 3 4 5 6 7 8 9var age = 100; var obj = { age: 20, say: () => { console.log(this);//这里的this指向window alert(this.age); } } obj.say();
形参默认值
|
|
三点运算符
-
将不定数量的参数表示为一个数组,只能放在最后
1 2 3 4 5 6 7 8const sum = (num, ...arr) => { console.log(num); console.log(arr); let total = 0; arr.forEach(item => total += item); return total;//50 }; console.log( sum(10, 20, 30)); -
可以配合解构使用
1 2var obj={xxx,xxx,xxx}; let {s1,...s2}=obj;//s1是obj对象中的第一个数据,剩下的在s2数组中

JSON
写法:
- 只能用双引号
- 所有名字都必须用双引号包起来
JSON对象转JSON字符串
JSON.stringify(json)
JSON字符串转JSON对象
JSON.parse(json)
JSON的简写
名字和值一样时保留一样即可
|
|
json中方法的简写
ES6中可以和面向对象中的方法一样把function删除
|
|
Array的扩展方法
扩展运算符
将数组或对象转为用逗号分隔的参数序列,其实就是和剩余参数一个相反的过程,这里用逗号拆开,剩余参数是合并为一个数组
|
|
-
可以用于合并数组
1 2 3 4 5arr1=[1,2,3]; arr2=[4,5,6]; arr3=[...arr1,...arr2]; //或者 arr1.push(...arr2); -
可以将伪数组转为真正的数组
1 2 3 4//方法一: arr2=[...arr1];//arr1是伪数组; //方法二: let arr2=Array.form(arr1,item=>item+1);//将arr1伪数组转为真正的数组,并且每个数组元素加1
Array.form()
将伪数组转为数组且对元素进行加工
Array.find()
用于找出第一个符合条件的数组成员,返回对象,如果没有找到则返回==undefined==
|
|
Array.findindex()
用于找出第一个符合条件的数组成员的==位置==,如果没有返回==-1==
|
|
String的扩展方法
模板字符串
-
可以解析变量
1`hello,my name is${变量名}` -
可以换行
-
可以调用函数
1 2 3 4const sayhello = function(){ return....; } let agree = `hello,my name is ${sayhello()}`
includes()
判断是否包含指定的字符串
startsWith()
startsWith()
是否以某字符开头,返回布尔值
startsWith(‘Hello’)
endsWith()
是否以某字符结尾,返回布尔值
endsWith(’!’)
repeat()
将原字符重复n次,返回一个新的字符串
str.repeat(3);
trim()
删除字符串两边的空格,不影响原字符串,==返回一个新的字符串==(防止用户输入空格)
Number的扩展方法
二进制与八进制数值表示法:二进制0b,八进制0o
isFinite()
判断是否是有限大的数
isNaN()
判断是否是NaN
isInteger()
判断是否是整数
parseInt()
判断是否是整数
trunc()
将字符串转换为对应的数值
Object的扩展方法
-
Object.is(v1,v2)
判断2个数据是否相等
-
Object.assign(target,source1,source2..)
将源对象的属性赋值到目标对象上,如果没有则使用原来的默认值
-
直接操作_proto_属性
let obj2 = {}
obj2.proto = obj1
-
Object.keys()
-
用于获取对象自身所有的属性
-
返回由属性名组成的数组
|
|
Promise
作用:将异步操作写成同步代码,避免了回调地狱
promise对象的3个状态
- pending:初始化状态
- fullfilled:成功状态
- rejected:失败状态
过程:
- 首先new promise对象
- 在异步代码执行成功时,调用resolve()方法,改变对象状态,传的参数在promise实例的then方法中的第一个函数中获取
- 异步代码执行失败时,调用reject()方法,改变对象状态,传的参数在promise实例的then方法中的第二个函数中获取
|
|
symbol


==注意==:
- for in 和for of 不能遍历symbol属性
对象的Symbol.iterator属性:指向对象的默认遍历器方法(fenerator)

==注意==:
- 三点运算符和解构赋值实际上就是实现了iterator接口
iterator遍历器
概念:是一种接口机制,为各种不同的数据结构提供统一的访问机制
作用:
- 为各种数据结构,提供一个统一的,简便的访问接口
- 使得数据结构的成员能够按照某种次序排列
- ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费
工作原理:

底层实现:
实际上这里的nextIndex使用了闭包

实现了iterator接口的数据结构

==注意==:
- 对象没有iterator接口,无法用for of去遍历循环
generator

普通函数:一路到底
generator函数:函数加*,中间能停,next一次走一步,yield处停止
- yield的值是next中传入的参数,==注意==:执行函数的第一个next不能传参,因为传了也不能赋值给变量,第二个next传的参数是第一个yield的返回值
- 调用next方法的返回值是函数return的值,或者yield后面的值
- ==生成遍历器对象==,给对象的Symbol.iterator属性添加一个遍历器对象后,就能用for of遍历

yield
可以传参,返回
看成把一个函数分成多个子函数,show_1,show_2
|
|

==注意==:
- 在getNews里面调用next方法并且传参,这样能在generator中得到url的值
class类和继承
类和对象
-
关键字:class
注意:类中所有函数不需要加function关键字,多个方法间不加逗号分隔.
-
方法中的this指向:方法的调用者
构造器
-
关键字:constructor()
-
作用:用于传递参数,返回实例对象,new生成对象实例时自动调用。
注意:如果未定义会自动创建一个constructor()
-
this指向:实例对象
|
|
==注意==:
this的指向问题
|
|
类的继承
关键字
-
entends
-
注意:ES6中类没有变量提升,必须先定义类,才能实例化
继承属性
调用父类构造函数:
- 关键字:super(x,y)
注意:在constructor中调用,且必须在子元素的this之前调用
|
|
继承方法
-
子类实例会自动继承父类的方法
-
在子类中调用父类方法:
- 关键字:super.父类方法名()
|
|
-
扩展子类的方法
|
|
深度克隆
- arr.concat():数组浅拷贝
- arr.slice():数组浅拷贝
- JSON.parse(JSON.stringify(arr/obj)):数组或对象深拷贝,拷贝的数据里不能有函数,这里实际上拷贝的是json字符串,是基本数据类型
- Object.assign();浅拷贝
- 浅拷贝拷贝引用,拷贝以后的数据会影响原数据
- 深拷贝拷贝值,拷贝以后的数据不会影响原数据
封装深拷贝函数
|
|
set容器
- 无序的,不可重复的多个value的集合体
-
类似于数组,但是成员不能重复,会自动去重
1 2const s = new Set(); const s = new Set([1,2,3,4,4])//可以接收数组初始化,会自动去重4 -
数据数量
s.size();
-
可以用于数组去重
1 2 3var arr = [1,2,3,4,4]; const s = new Set(str); var arr = [...s];//这里用扩展运损符将s用逗号分隔开
实例方法
- add(value):添加某个值,返回Set结构本身
- delete(value):删除某个值,返回布尔值,表示是否和删除成功
- has(value):返回布尔值,表示该值是否为set的成员
- clear():清除所有成员,没有返回值
Set遍历
和数组一样有foreach方法,无返回值
s.forEach(value=>log(value))
map容器
- 无序的key,不重复的多个key-value的集合体
Map()
Map(array)
set(key,value)//添加
get(key)
delete(key)
has(key)
clear()
size
|
|
for of
- 遍历数组
- 遍历set
- 遍历map
- 遍历字符串
- 遍历伪数组
ES7
async/await
- ES7的新语法,可以更加方便得进行异步操作
- async用于函数上(async函数得返回值时promise对象)
- await用于saync函数中(await可以得到当前异步的结果)
==注意==:因为async返回的也是个promise对象,在调用时也可以用then获得函数的返回值
|
|
==注意==:await后面必须跟promise实例对象,才能获取异步的结果
|
|
-
处理多个异步任务
桉顺序写即可
1 2 3 4 5 6 7 8 9axios.defaults.baseURL = 'http://localhost:3000'; async function queryData() { var info = await axios.get('async1'); var ret = await axios.get('async2?info=' + info.data);//用info作为参数 return ret.data; } queryData().then(ret=>{ console.log(ret); })
Array.includes()
表示某个数组是否包含给定的值,返回布尔值
|
|
指数运算符
**
模块化规范
namespace模式
|
|
|
|
IIFE模式
|
|
|
|
IIFE模式增强
|
|
|
|
CommonJS
规范


基于服务器端
文件结构

|
|
|
|
==注意==:
- npm install xxx –save-dev 标识开发依赖包
基于浏览器端
文件结构

-
首先和服务端一样,用module.epxorts进行暴露,require进行引入
-
其次
全局下载browserify包:npm install browerify
再局部下载开发依赖:npm install browerify –save-dev
-
其次命令行打包处理:
错误内容:
'browserify' 不是内部或外部命令,也不是可运行的程序 或批处理文件。已解决: 命令行前面加上browserify的路径即可,
node_modules\.bin\browserify js/src/app.js -o js/dist/build.js==注意==:
-
前面的是原文件
-
-o表示output
-
后面的是输出文件的目录以及文件名字
-
然后在index.html中引入输出的新文件,即可在浏览器端使用require
AMD
规范

文件结构

下载requireJS
定义没有依赖的模块
|
|
定义有依赖的模块
|
|
main.js
|
|
==注意==:
- 引入jquery时要小写
index.html
|
|
CMD
ES6

步骤:
-
定义package.json文件
-
安装babel-cli,babel-preset-es2015和browserify
- npm install babel-cli browserify -g
- npm install babel-preset-es2015 –save-dev
- preset 预设(将es6转为es5的所有插件打包)
-
定义.babelrc文件,
1 2 3{ "presets": ["es2015"] } -
编码
文件结构
|
|
统一暴露
|
|
默认暴露
|
|
main
|
|
==注意==:
- 要使用解构赋值的方式来引入模块
5.编译
-
使用babel将ES6编译为ES5代码:==babel js/src -d js/lib==
源文件目录 编译后的文件目录
改成require那种es5的,但是require仍然需要转换
-
使用Browserify编译js:==browserify js/lib/main.js -o js/lib/bundle.js==
6.引入:index.html中使用bundle文件
==注意==:
- 一旦修改了js文件就需要重新编译打包
打包完成后文件结构

