数组
1.forEach方法
-
forEach( ( item, [index],arr )=>{ })
-
其中item是数组当前项,index可选是数组当前项的索引号 arr数组本身
-
forEach性能差 ,循环一旦开始,中间不能被终止 return不能终止迭代 不能break
forEach方法和map()方法的区别:
- 都能遍历数组,匿名函数都有三个参数
- map有返回值,会分配内存空间返回一个与原数组长度一致的新数组 能够链式操作 比如filter、every等等操作
- forEach无返回值,或者说返回一个undefined,不能够链式操作
<script>
const arr = ['李白', '诸葛亮', '司马懿', '孙悟空']
arr.forEach(function(item, index) {
console.log('打印次数');
if (item === '诸葛亮') {
console.log("索引项:" + index);
}
})
</script>
2.some方法
- arr.some( ( item, [index] )=>{ })
- 找到对应项后 ,可以通过return true 固定写法 来终止循环
- 用于检测数组中的元素是否满足指定的条件 返回值为布尔值true 或false
- 查找第一个满足的条件则终止循环,不再继续查找
<script>
const arr = ['李白', '诸葛亮', '司马懿', '孙悟空']
arr.some(function(item, index) {
console.log('打印次数');
if (item === '司马懿') {
console.log("索引项:" + index);
return true
}
})
</script>
3.every方法
-
arr.every( ( item, [index] )=>{ })
-
every() 方法用于检测数组所有元素是否都符合指定条件
- 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
- 如果所有元素都满足条件,则返回 true.
<script> const arr = [{ id: 1, name: '西瓜', status: true }, { id: 2, name: '草莓', status: true }, { id: 3, name: '香蕉', status: true }] const result = arr.every(item => item.status === true) console.log(result); //true </script>
4.reduce方法
-
arr.reduce(function( total, item,[ index ] ),[initValue])
- 参数1 :total 表示计算结束后的返回值
- 参数2:item表示循坏项的当前值
- 参数3:index 可选 表示当前元素的索引
- 参数4:initValue 可选。传递给函数的初始值。不传的时候会把第一项作为初始值,但是第一项不会执行reduce方法
-
返回值为函数计算的结果
<script> const arr = [{ id: 1, name: '西瓜', status: false, price: 6, number: 3 }, { id: 2, name: '草莓', status: true, price: 3, number: 5 }, { id: 3, name: '香蕉', status: true, price: 9, number: 10 }] //先过滤一下得到status为true的数组 再使用reduce()方法返回计算后的结果 const result = arr.filter(item => item.status).reduce((total, item) => { //每次累加的结果返回给total 初始值为0给total return total += item.price * item.number }, 0) console.log(result); //105 </script>
let和const命令
1.var命令
会变量提升和函数提升
2.let命令
-
let声明变量 ,没有变量提升
-
有块级作用域
-
不能重复声明 比如let a=1 ;let a=2 但是可以修改 let a=3 ;a=4
3.const命令
- const声明变量 ,没有变量提升
- 不能重复声明 一旦声明无法修改 比如const i=4;i=8
建议:默认情况下使用const,当你需要变量值要修改的情况使用let
模板字符串
- 使用tab键盘的反引号 ``
- 插入变量值使用${ 变量名}
函数之默认值、剩余参数
1.可以直接给形参传值
- 不写则默认实参传值
2.默认表达式可以是一个函数
剩余参数
- 由三个点和具名参数组成
...args
- arguments是伪数组,剩余参数是个真数组 它有原型对象
- 剩余运算符:将多个独立的参数合并到一个数组中 ,一般放在函数的形参上
function pick(obj, ...args) {
let result = {}
for (let i = 0; i < args.length; i++) {
result[args[i]] = obj[args[i]]
}
return result //...args为真数组
}
let user = {
name: 'zs',
age: 23,
sno: 123456
}
let userData = pick(user, 'name', 'age')
console.log(userData) //{name: 'zs', age: 23} 返回真数组
以前的写法
函数之扩展运算符
- 扩展运算符:将一个数组分割,并将各个项作为分离的参数传给函数
apply()
方法接受数组形式的参数apply(null,[ ]) 参数1可以为null 也可以为" " 第二个参数为数组
箭头函数
使用=>来定义 function( ){ }等价于 ( )=>{ }
当只要一个参数时可以省略() ,当函数执行只有一行代码时,可以省略return 和{ }
当函数一个参数也没有,必须写()
当执行代码返回一个数组或者对象时 ,可以省略return 但必须加()包裹执行的内容
立即执行函数
fn=( function( ){ } )****( ); // 返回的匿名函数并赋值给fn变量
fn() ;//调用函数
this指向问题
1.使用bind( )函数修改this指向
- bind()不会调用函数但可以改变this指向 ,而call() 会调用函数且改变this指向
2.使用箭头函数修改this指向
箭头函数没有this指向,箭头函数内部this只能通过查找它的作用域链来确定 ,最终由上下文确定。
一旦使用箭头函数,当前就没有自己的作用域
3.箭头函数注意事项
-
使用箭头函数 函数内部没有arguments ,不能通过arguments对象访问传入的参数
-
arguments对象和Function是分不开的 ,arguments对象只有函数开始时才可用
-
箭头函数不能使用new关键字来实例化对象
解构赋值
- 是对赋值运算符的一种扩展
- 它针对数组和对象来进行操作–数组结构[ ] 、对象解构{ }
- 代码书写简洁易读
1.对象解构
完全解构
不完全解构
默认解构
2.数组结构
完全解构 一一对应
不完全解构
可以嵌套
对象的扩展功能和方法
es5的写法:
es6的简写写法:
- 同名可以简写
- 在对象中函数可省略function和前面的冒号:
扩展的对象方法
- is( ) 类似于=== 用来比较两个值是否严格相等
-
assign( ) 对象的合并 返回值为合并后的新对象
Object.assign(目标对象,对象1,对象2……)
Symbol数据类型
- 原始数据类型Symbol,它表示是独一无二的值
- 它的最大作用:用来定义对象的私有变量
const str = Symbol('name')
const str1 = Symbol('name')
console.log(str === str1); //false
const private = Symbol('name')
console.log(private); //Symbol(name)
let obj1 = {
//简写
[name]: '张三'
}
//添加属性值 以下都可
// obj1.name = '张三'
// obj1[name] = '张三'
// 如果使用Symbol定义的对象中的变量,只能通过对象[变量名]去访问 ,而不能通过对象.变量名去访问 不然打印的是undefined
console.log(obj1[name]); //张三
Set集合数据类型
集合表示无重复值得有序列表
Set是一种叫做集合的数据结构
主要应用于数组去重
Map数据类型
Map数据类型是键值对的有序列表,键和值是任意类型
Map是一种叫做字典的数据结构
主要应用于数据储存
数组的扩展方法
1.form()方法
- 将伪数组转换成真正的数组
2.of()方法
- 将任意的数据类型转换成数组
3.find()方法
- 找出第一个符合条件的数组成员
4.findIndex()方法
- 找出第一个符合条件的数组成员的索引项
5.entries()方法
-
返回一个遍历器 ,可以使用for …of 循环进行遍历
-
遍历数组的键值对
6.keys()方法
- 返回一个遍历器 ,可以使用for …of 循环进行遍历
- 遍历数组的键
7.values()方法
- 返回一个遍历器 ,可以使用for …of 循环进行遍历
- 遍历数组的值
8.includes()方法
返回一个布尔值,用来表示数组中是否包含给定的值
迭代器 iterator
一种新的遍历机制 两个核心
1.迭代器是一个接口,能快速的访问数据,通过Symbol.iterator 来创建迭代器 ,通过迭代器的next( )方法来获取迭代后的结果
2.迭代器用于遍历数据结构的指针( 数据库的游标)
生成器 generator
generator函数 可以通过 yield 关键字( 类似于暂停执行yield后面的代码) 将函数挂起 ,为了改变执行流提供了可能,同时为了做异步编程提供了方案
作用:部署ajax操作,让异步代码同步化
它与普通函数的区别
1.function后面 函数名前面跟一个 *
- 只能在函数内部使用yield 表达式 让函数挂起
generator函数是分段执行的 一旦遇到 yield 语句会暂停执行 ,而next( )会恢复执行
next( )方法可以带一个参数,该参数会被当做上一个yield 表达式的返回值
每一次next传值 然后调用后,恢复上一个yield语句接收 该传入的实参
使用场景(一般搭配迭代器使用):
对不具备iterator 接口的对象提供遍历操作
for in 可以遍历对象 ,而for of 不能遍历对象,只能遍历带有iterator 接口的对象
for of与forEach 不同的是,它可以正确响应 break、continue 和 return 语句。它不仅可以遍历数组,还可以遍历类数组对象和其他可迭代对象。并且它不会遍历自定义属性
for of 循环重复调用next()方法,每次循环调用一次
const obj = {
name: 'zhangsan',
gender: '男'
}
// 让对象具有迭代器接口
obj[Symbol.iterator] = iteratorObj;
console.log(obj);
//迭代器函数
function* iteratorObj(obj) {
// 获取对象所有的key保存到数组中
for (let key of Object.keys(obj)) {
//console.log(Object.keys(obj)); //['name', 'gender']
yield [key, obj[key]]
}
}
// for of 循环重复调用next()方法,每次循环调用一次
for (let [key, value] of iteratorObj(obj)) {
console.log(`${key}:${value}`); //name:zhangsan gender:男
使用场景:异步代码同步化
案例1
function* main() {
//res是next()恢复执行后传递参数的返回值
let result = yield request('http://www.liulongbin.top:3006/api/getbooks')
console.log(result); //{status: 200, msg: '获取图书列表成功', data: Array(15)}
console.log('数据请求完成,接着执行同步代码打印操作!');
}
//生成一个迭代器对象
const item = main()
item.next()
// 异步请求函数
function request(url) {
$.ajax({
url: url, //同名参数可简写url
type: 'GET',
success(res) {
//第二次调用next() 把res结果赋值给yield语句 赋值的result
item.next(res)
}
})
}
//由于 setTimeout()是异步任务,按顺序执行会出现以下打印界面
案例2 让异步代码同步化
// 遇到yield 让函数暂停下来了等加载数据函数的倒计时执行完后 后面next()恢复执行 ,等数据返回之后然后在next()再执行hideUi()
function* load() {
loadUI()
yield showData()
hideUI()
}
let item1 = load()
item.next()
function loadUI() {
console.log('加载loadui页面');
}
function showData() {
// 模拟异步操作
setTimeout(() => {
console.log('数据加载完成');
item1.next()
}, 3000);
}
function hideUI() {
console.log('隐藏了hideUI界面');
}
promise对象的基本使用
相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果
各自异步操作都可以用同样的方法来进行处理
特点:
- 对象的状态不受外界影响,处理异步操作的三个状态 pending(进行不可逆转) resolved(完成执行并不代表成功 包含fulfilled 满足状态和rejected失败状态) rejected(失败)这三个状态也是函数
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果
// 封装一个函数 返回一个promise对象,外界对其传参 链式调用then()
function timeout(time) {
return new Promise((resolved, rejected) => {
let res = {
status: 200,
data: {
name: 'zhangsan'
},
error: '失败'
}
setTimeout(() => {
if (res.status === 200)
return resolved(res.data)
rejected(res.error)
}, time)
})
}
// 从外界传参 then()接收两个回调函数 ,分别打印成功获取和失败获取promise对象返回的消息
timeout(2000).then(function(val) {
console.log(val); //{name: 'zhangsan'}
}, function(err) {
console.log(err); //失败
})
//封装一个ajax函数
function getJSON(url) {
return new Promise((resolved, rejected) => {
console.log(url);
const xhr = new XMLHttpRequest()
//发起get请求
xhr.open('GET', url)
//定义监听请求状态改变的事件函数
xhr.onreadystatechange = handler
// 响应数据为json对象
xhr.responseType = 'json'
// 设置头部信息
xhr.setRequestHeader('Accept', 'application/json')
// 发送
xhr.send()
function handler() {
// console.log(this);
if (xhr.readyState === 4 && xhr.status === 200) {
resolved(this.response) //{status: 200, msg: '获取图书列表成功', data: Array(6)}
} else {
rejected(new Error(this.statusText))
}
}
})
}
getJSON('http://www.liulongbin.top:3006/api/getbooks').then((result) => {
console.log(result);
}, (err) => {
console.log(err);
})
then()方法
then( callback ,[ callback ] )
- 方法中第一个参数是resolved( )回调函数,第二个参数可选 是rejected( ) 回调函数
- then( )返回一个新的promise对象,可以采用then()链式编程
- then( null,err) 表示只返回错误的结果 等价于 catch( err) —推荐使用**catch( )**方法接收错误的信息
then里面第二个参数捕捉错误只能捕捉上级的 不能捕捉同级的第一个参数里的错误 所以要用catch
resolve( )方法和reject( )方法
resolve( )方法和reject( )方法能将现有的任何对象转换成promise对象
// let o = Promise.reject('ok') //直接利用Promise调用
let p = new Promise((resolve) => { //利用 new promise实例来调用
return resolve('foo')
})
console.log(p); //Promise {<fulfilled>: 'foo'}
let o = new Promise(reject => {
reject('fvc')
})
console.log(o); //Promise {<rejected>: 'fail'}
all( )方法
适用于异步并行操作,只有都成功才会成功
参数里面接收的是数组
应用:一些游戏类的素材较多,等待图片、flash、静态资源文件都加载完成才进行页面的初始化
race( )方法
适用于某个异步请求设置超时时间,并且在超时后执行相应的操作
参数里面接收的是数组
//请求图片资源
function requsetImg(imgSrc) {
return new Promise((resolve, reject) => {
// new一个图片实例
const img = new Image()
img.onload = function() {
// 接收图片
resolve(img)
}
img.src = imgSrc
})
}
//定义定时器函数
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('图片请求超时'))
}, 3000)
})
}
// 请求成功执行then() 三秒过后调用catch() 记住race()里面必须是数组
Promise.race([requsetImg('./images/1.jpg'), timeout()]).then((res) => {
// 成功
console.log(res);
document.body.appendChild(res)
}).catch(err => {
//失败
console.log(err); //Error: 图片请求超时
})
done( )方法和finally( )方法
- done()用来往外抛出错误,finally()可以执行回调函数
- 一般放到catch()的后面链式调用
Promise 对象的回调链,不管以
then
方法或catch
方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到(因为 Promise 内部的错误不会冒泡到全局)。因此,我们可以提供一个done
方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。
finally
方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。它与done
方法的最大区别,它接受一个普通的回调函数作为参数,该函数不管怎样都必须执行。
async和await的用法
作用:使得异步操作更加方便
async会返回一个promise对象,它是generator生成器的语法糖 调用then() 和 catch()
- await 和async在一个函数里面搭配使用
- 若有多个await then() 需要等待所有的await 操作完成 才返回成功或失败的信息
async function fn() {
let str = await 'hello you'
let data = await str.split(' ').join('-')
return data
}
fn().then(res => {
console.log(res); //hello-you
}).catch(err => {
console.log(err);
})
async function fn2() {
try {
await Promise.reject('出错了')
} catch (err) {
}
return await Promise.resolve('hello')
}
fn2().then(res => {
console.log(res); //hello-you
}).catch(err => {
console.log(err);
})
总结
generator 、Promise 、async 的两个作用:
- 解决回调地狱问题
- 使得异步操作更简单
class类的用法
es5之前写法
class Person {
//实例化的时候会被立即调用
constructor(name, age) {
this.name = name
this.age = age
}
//类中多个方法不能使用逗号隔开
// printName() {
// return this.name
// }
// printAge() {
// return this.age
// }
}
// Object.assign(目标对象,{对象1},{对象2} ...)
// 将assign方法一次性向类中添加多个方法
Object.assign(Person.prototype, {
printName() {
return this.name
},
printAge() {
return this.age
}
})
let p = new Person('zhangsan', 18)
console.log(p);
console.log(p.printName()); //zhangsan
console.log(p.printAge()); //18
类的继承
extends 关键字来继承其他累的公共属性和方法
super( ) super为超类 它会调用父类中constructor()的方法
class Animal {
constructor(name, age) {
this.name = name
this.age = age
}
f1() {
return this.name
}
f2() {
return this.age
}
}
//使用extends继承父类
class Dog extends Animal {
constructor(name, age, func) {
super(name, age)
// Animal.call(this, name, age)
this.func = func
}
// 定义子类自己的方法
effect() {
return `${this.name}今年${this.age}岁,他会${this.func}`
}
// 子类重写父类的方法
f1() {
return this.name + super.f2() + this.func
}
}
let dog = new Dog('二哈', 8, '狗叫')
console.log(dog); //Dog {name: '二哈', age: 8, func: '狗叫'}
console.log(dog.effect());
console.log(dog.f1());
ES6的模块化实现
es6模块主要由两个功能构成:export 和 import
一个模块就是一个文件
- export 用于规定模块的对外接口------ 用于导出变量
- import 用于输入其他模块提供的功能-----用于引入变量
as关键字:
- 使用export 需要使用{ 变量} 来包裹起来 , as关键字可以对导出的变量进行重命名, 可以使用as关键字重命名
export {name as myName,age as myName}; import {myName,myName} from './a.js';
- 对于导入的变量,同样也可以使用as命令
export {name,age}; import {name as name1,age as age1} from './a.js';
错误的变量导出方式
var age = 1; export age; 错误 export 1; 错误 export var age = 1; 正确 export {age}; 正确 function fn () {} export fn; 错误 export function fn () {} 正确 export {fn} 正确
使用*字符可以将模块中所有导出的变量导入到指定的变量中。
import * as varibles from './a.js';
export default命令
export default命令与export命令一样用于导出变量。不同的是,export可以使用多次。在导入变量的时候,需要知道输入的变量名称才能进导入,而export default只能使用一次,在导入变量的时候,用户不需要知道模块内部导出的变量名称。
var name = "name"; export default name;
import varibles from './a.js'; console.log(varibles) //name
export default在导出变量的时候,不需要像export一样使用花括号。在引入变量的时候也一样。
export default后面不能跟声明变量的语句,因为export default命令实质上是输出了一个叫default的变量,然后允许你在引入的时候为这个变量取任意名称
export default var name = 1; //错误 export default 1; 正确 var name = 1; export default name; //正确
axios的基本使用
axios(艾克C奥斯)是一个专注于网络请求的库,通过promise封装的ajax
不同于jquery,无需操作dom,它负责请求和拿数据
1.发起get请求
- 请求参数使用params:{}
- 拿到带参数请求的具体数据使用data:res中 res.data
<script src="./lib/axios.js"></script>
<script>
axios({
//请求方式
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks',
//url中的查询参数
params: {
id: 2
},
// 请求体参数
data: {}
}).then(function(res) {
console.log(res);
})
</script>
res.data 才是请求真正的数据
document.querySelector("#btnGet").addEventListener('click', async function() {
//解构赋值可以用`:`进行重命名
const {data: res} = await axios({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks'
})
console.log(res.data);
})
2.发起post请求
- 请求参数使用data:{}
- 拿到带参数请求的具体数据使用 data.body
- 如果不使用then回调函数,则使用async异步/await
- 如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await!
- await 只能用在被 async “修饰”的方法中
<script>
document.querySelector("#btnPost").addEventListener('click', async function() {
//使用解构赋值{data} 来解析对象在带有data的属性
const {data} = await axios({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/post',
data: {
name: '宋江',
age: 18
}
})
console.log(data);
})
</script>
3.使用axios直接发起get请求
请求参数要写{params:{参数}}
document.querySelector('#btnGET').addEventListener('click', async() => {
const {
data: res
} = await axios.get('http://www.liulongbin.top:3006/api/getbooks', {
params: {
id: 1
}
})
console.log(res);
})
4.使用axios直接发起post请求
请求参数{data:{ 参数}},也可以简写{参数}
document.querySelector('#btnPOST').addEventListener('click', async() => {
const {
data: res
} = await axios.post('http://www.liulongbin.top:3006/api/post', {
data: {
name: 'zx',
info: 'go'
}
})
console.log(res);
})