ES6
一、变量
1.1 let变量
用于声明变量,用法与var类似,但存在新的特性
特性:
- let所声明的变量,只在当前代码块内有效,避免全局污染
- 没有变量声明提升
- 暂时性死区,在let命令声明变量前,该变量都是不可用的
- 不允许重复声明
二、常量
2.1 const命令
用于声明常量
特性:
不可以重新赋值
const obj = { name:'alice', age:22 } obj.name = 'zhang' //{ name: 'zhang', age: 22 },不报错,因为只改变了对象的值,没有改变引用地址
声明的同时必须初始化
const a = 7;
- 暂时性死区
- 不允许重复声明
- 只在当前的代码块内有效
三、解构
3.1 数组解构
从数组和对象中提取值,对变量进行赋值。即只要等号两边的模式相同,等号右边的值就会一一进行赋值。
let [a,b,c] = [1,2,3] let [a,b,c] = [1,2,3,4] //1 2 3 let [a,b,...c] = [1,2,3,4] //1 2 [3,4] let[a,b,c,d,e] = [1,2,3] //1 2 3 undefined undefined //等号左边变量多余,多余的变量会被赋值为undefined //等号右边变量多余,多余的变量会被忽视或者使用...将其整合为一个数组 let[a,[b],c] = [1,[2,3],4] //1 2 4 let[a,b,c] = [1,[2,3],4] //1 [ 2, 3 ] 4 let[a,[b,c],d] = [1,[2,3],4] //1 2 3 4 let[a,b,c,d] = [1,[2,3],4] //1 [ 2, 3 ] 4 undefined let[a,b=22] = [10] //10 22 let[a,b=22] = [10,20] //10 20 //如果改变了默认值,则以改变后的值为准,若没有改变,则继续使用默认值
数组嵌套对象
let[a,{name:user}] = ['hello',{name:'tom'}] console.log(a, user) //hello tom
对象嵌套数组
let{test} = {test:[1,2,3]} console.log(test) //[1,2,3]
默认值可为函数
function f(){console.log(111)} let[x=f()] = [1] console.log(x) //1
3.2 对象解构
对象的属性没有次序,所以变量必须与属性同名,才能取到正确的值
let{name,age} = {name:'tom',age:12} //是let{name:name,age:age} = {name:'tom',age:12}的简写 console.log(name,age) //tom 12
//若要修改属性名 let{foo:bar}={foo:'ss',bar:'aa'}//将foo改为bar,bar的值为'ss' console.log(bar) //ss
3.3 字符串解构
字符串被转换成一个类似数组的对象
const [a, b, c, d, e] = ‘hello’; //a=h;b=e;c=l;d=l;e=o
对数组的属性解构
let{length:t}='zzzh' console.log(t) //4 let{trim}='zzz' console.log(trim === String.prototype.trim) //true //可以解构其原型上的方法 let{toString}=true console.log(toString === Boolean.prototype.toString); //true
函数参数解构
function test([a,b]){ return a+b } let res = test([1,2]) console.log(res) //3 function test({a=3,b=2}){ return a*b } let s = test({a:1}) console.log(s) //2
用处:
从函数返回多个值
function foo(){ return[1,2,3] } let[a,b,c] = foo()
交换变量的值
let a=3; let b=4; [a,b]=[b,a];
四、对象扩展
ES6允许直接在对象中写入变量和方法,此时属性名就是变量名,属性值就是变量值
let name = 'tom' let age = 12 // let obj = { // name:name, // age:age, // gender:'男', // sayName:function(){ // console.log(1111) // } // } let obj = { name, age, gender:'男', sayName(){ console.log(1111) } }
方法的name属性为方法名
function test(){} console.log(test.name) //test let p = { //test:function(){} test(){ } } console.log(p.test.name) //test
let test = 'hello' let obj = { name:'zhangsan', //test:'hello' test,
[test]:'123'
}
console.log(obj) //{ name: 'zhangsan', test: 'hello', hello: '123' }
- Object.is()用来判断两个值是否相等,与===的不同之处:-0不等于+0,NAN相等
let a = +0
let b = -0
var res = Object.is(a,b) //false
console.log(a===b) //true
let a = NaN
let b = NaN
var res = Object.is(a,b)
console.log(a===b) //false
console.log(res) //true
- Object.assign(target,...,obj)将后面的参数对象合并到target对象中,是一种浅拷贝
let obj1={
name:'tom'
}
let obj2 = {
name:'zhangsan',
age:12
}
let obj3 = {
gender:'男',
sayName:function(){
}
}
let target = {}
let res = Object.assign(target,obj1,obj2,obj3)
console.log(target)
console.log(res)
/*上下返回一致{
name: 'zhangsan',
age: 12,
gender: '男',
sayName: [Function: sayName]
}*/
自己写assign函数
function myAssign(target,...temp){
temp.forEach(function(item){
for(var key in item){
target[key] = item[key]
}
})
return target
}
myAssign(target,obj2,obj1,obj3)
console.log(target)
//{ name: 'tom', age: 12, gender: '男', sayName: [Function: sayName] }
- Object.keys(obj) 返回由obj对象的属性名构成的一个数组
Object.values(obj) 返回由obj对象的属性值构成的一个数组
Object.entries(obj) 返回由obj对象中属性名和属性值组成的数组所构成的数组
let obj = {
name:'ss',
age:13,
gender:'女'
}
var res = Object.keys(obj)
console.log(res) //[ 'name', 'age', 'gender' ]
var res = Object.values(obj)
console.log(res) //[ 'ss', 13, '女' ]
var res = Object.entries(obj)
console.log(res) //[ [ 'name', 'ss' ], [ 'age', 13 ], [ 'gender', '女' ] ]
## 五、函数扩展
- 允许为函数的参数设置默认值(函数的length属性值为未给予默认值的参数个数)
- rest参数(...变量名)
function foo(...values){
console.log(values)
}
foo(1,2,3,2,1) //[ 1, 2, 3, 2, 1 ]
- **箭头函数**
- ```javascript
let test1 = (a,b)=> console.log(a+b)
test1(1,2)
let test2 = a => console.log(a)
test2(1)
//参数只有一个时可以省略小括号(),函数体中只有一条语句时可以省略大括号{}
//箭头函数没有自己的this,而是引用外部的this let obj = { name:'tom', sayName(){ console.log(this) } } obj.sayName() //{ name: 'tom', sayName: [Function: sayName] } let obj = { name:'tom', sayName:()=>{ console.log(this) } } obj.sayName() //{} //此时的this指向全局
- 不能作为构造函数
- 没有内部属性arguments
五、数组扩展
扩展运算符(..),rest参数的逆运算
let arr =[1,2,3] console.log(...arr) //1 2 3 console.log([...'hello']) //[ 'h', 'e', 'l', 'l', 'o' ],即将字符串转换为数组
Array.from() 可以将类数组对象或可迭代数据转换成数组
let obj = {'0':'hello','1':'world','2':'nice',length:5} console.log(Array.from(obj)) //[ 'hello', 'world', 'nice', undefined, undefined ]
Array.of() 可以将一组值转换成数组
console.log(Array.of(true,true,false)) //[ true, true, false ] console.log(Array.of('hello','nice','world')) //[ 'hello', 'nice', 'world' ]
.find() 参数是一个回调函数,所有数组成员依次执行此回调函数,直到找到第一个被回调函数筛选出的值(即第一个返回值为true的成员),并返回该值
let arr = [10,2,3,,11] let res = arr.find((item,index,arr)=>{ return item<10 }) console.log(res) //2 //若没有符合条件的值,则返回undefined
.findIndex() 遍历数组,找到第一个被回调函数筛选出的值,并返回该值的索引
let arr = [10,2,3,,11] let res = arr.findIndex((item,index,arr)=>{ return item<10 }) console.log(res) //1 //若没有符合条件的值,则返回-1
.fill() 使用固定的值去填充数组
let arr = [] arr.length = 3 let res = arr.fill(10) console.log(res) //[10,10,10] console.log(res === arr) //true
- .keys(),values(),entries(),返回一个遍历器对象,可执行for-of命令进行遍历
索引,值,键值对
- .includes() 判断某个数是否存在于数组中,返回一个布尔值
六、Set/Map
6.1 Set
类似于数组,但它的数据集合是无重复的
//s是Set的实例
arr = [1,2,2,1,2,3,4,5]
let s = new Set(arr)
console.log(s) //Set { 1, 2, 3, 4, 5 }
arr = [...s] //将set对象转换为数组
console.log(arr) //[1,2,3,4,5]
- 属性:
.size Set实例中的成员总数
- 方法:
.add(value) / .delete(value) / .clear() / .has(value) set成员中是否包含该值 / .forEach() / .keys(),values(),entries()
s = [1,1,1,2,3,4,1] console.log([...new Set(s)]) //去重,参数可以为具有iterator接口的其他数据结构
6.2 Map
Map类似于对象,也是键值对的集合,但是其键的数据类型不仅限于字符串
//可以接收数组作为参数
let map = new Map([ ['name', '张三'], ['title', 'Author'] ]);
console.log(map) //Map { 'name' => '张三', 'title' => 'Author' }
map.set('name','alex')
map.set('age',12)
console.log(map.has('age'))
map.delete('name')
- 属性:
.size Map结构中的成员总数
- 方法:
.set(key,value) / .get(key) / .delete(key) / .clear() / .has(key) Map对象中是否包含该键 / .forEach() / .keys(),values(),entries()
6.3 Iterator(遍历器)
Iterator是一种接口,为各种不同的数据结构提供统一的访问机制。任何只要被部署Iterator接口的数据结构都可以完成遍历操作。
作用:
- 为各种数据结构提供了统一的、简便的访问接口
- 使得数据结构的成员能够按某种次序排列
供es6新推出的遍历命令for...of消费
let arr = [1,2,3,4,5] let keys = arr.keys() for(let key of keys){ console.log(key) }
- 具备Iterator接口的数据结构:
Array、Map、Set、String、TypeArray、函数的arguments对象、NodeList对象
next()
let s = new Set([10,2,2,2,3,1]) let values = s.values() console.log(values.next()) //{ value: 10, done: false }false代表没有结束 console.log(values.next()) //{ value: 2, done: false } console.log(values.next()) //{ value: 3, done: false } console.log(values.next()) //{ value: 1, done: false } console.log(values.next()) //{ value: undefined, done: true }
七、Class
ES6的class中的绝大多数功能ES5都能做到,新的class写法只是让对象原型的写法更加清晰更像面向对象编程的语法。
class Animal{
//构造函数
constructor(name){
this.name = name //类的实例属性定义在构造函数当中
}
//在类中可以直接定义方法,这些方法都定义在类的prototype属性上面,都会被实例继承。
toSay(){
console.log('实例方法')
}
//静态方法不能被实例调用(继承),只能通过类调用
//静态方法中的this指的是类,而不是实例
static mySay(){
console.log('静态方法')
}
}
let cat = new Animal('tom')
cat.toSay()
Animal.mySay()
console.log(cat)
//静态属性只能通过此种方法进行定义
Animal.sound = 'miao'
console.log(Animal.sound) //miao
//可以通过Object.assign()方法向类的原型中添加方法
Object.assign(Point.prototype, {
toString(){},
toValue(){}
});
继承
class Animal{
constructor(name){
this.name = name;
}
say(){
console.log('say')
}
static sayMy(){
console.log('sayMy')
}
}
class Dog extends Animal{
constructor(name,age){
//此时的super()相当于Animal.prototype.constructor.call(this),即调用父类的构造函数(this指向的的是Dog,返回的是Dog的实例)
//此时的super为函数
super(name);
this.age = age;
}
Dogsay(){
//super指向父类的原型对象,相当于super.say.call(this),this指向Dog
//此时的super为对象
super.say()
}
static DogsayMy(){
//super指向父类
super.sayMy()
}
}
let dog = new Dog('wang',6)
dog.say()
dog.Dogsay()
Dog.sayMy()
Dog.DogsayMy()
console.log(dog)
console.log(Dog.__proto__ === Animal)
//子类的__proto__属性表示构造函数的继承,指向父类
console.log(Dog.prototype.__proto__ === Animal.prototype)
//子类的prototype.__proto__属性表示方法的继承,指向父类
八、Promise
Promise是一个容器,存放着未来将要结束的某个事件(通常是异步操作)的结果。同时,Promise也是一个对象,可以获取异步操作的消息。它可以将异步操作以同步操作的流程表达出来。用于解决异步,优化异步。
promise的参数是一个函数,函数的参数分别为resolve和reject:
- resolve函数在异步操作成功时调用(promise对象的状态pedding-->fullfilled),会将异步操作的结果,作为参数传递给回调函数
- reject函数在异步操作失败时调用(promise对象的状态pedding-->rejected),会将异步操作报出的错误,作为参数传递给回调函数
通过then方法和catch方法(或者then方法的第二个参数,一般不使用)分别指定两个状态的回调函数
let p = new Promise((resolve,reject)=>{
$.ajax({
url:'http://39.105.67.242:5588/orde/findAll',
method:'get',
success:function(res){
resolve(res)
},
error:function(e){
reject(e)
}
})
})
p.then((res)=>{
console.log(res)
}).catch((e)=>{
console.log(e)
}).finally(()=>{
//不管Promise的状态最后如何,都会执行此回调函数
console.log('结束')
})
Promise.all()
//参数为一个数组,p1,p2,p3都为Promise实例 var p = Promise.all([p1,p2,p3])
只有p1,p2,p3的状态都转变为fullfilled,p的状态才能转变为fullfilled。此时p1,p2,p3的返回值组成一个数组,传递给p的回调函数。p1,p2,p3中只要有一个状态转变为rejected,p的状态就转变为rejected,此时第一个状态变为rejected的实例的返回值被传递给p的回调函数。
Promise.race()
//参数为一个数组 var p = Promise.race([p1,p2,p3])
只p1,p2,p3中有一个实例的状态被改变,p的状态就会被改变。率先改变状态的实例的返回值被传递给p的回调函数。
九、Generator
Generator是一个状态机,封装了多个内部状态。执行Generator函数会返回一个遍历器对象,可以依次遍历Generator函数内部的每一个状态。
可以将异步操作同步化。
//function与函数名之间加*
function* test(){
yield 'hello'
yield 'world'
yield 'nice'
return 'yes'
}
let res = test() //返回一个迭代器对象
console.log(res.next()) //{ value: 'hello', done: false }
console.log(res.next()) //{ value: 'world', done: false }
console.log(res.next()) //{ value: 'nice', done: false }
console.log(res.next()) //{ value: 'yes', done: true }
应用:
let axios = require('axios')
function* main() {
var result = yield request("http://39.105.67.242:5588/customer/findAll");
console.log(result.data);
}
function request(url) {
// response参数当做上一个yield表达式的返回值
//.then代表异步请求成功
axios.get(url).then(function(response){it.next(response);});
//it.next(response)执行的是result=response以及后面的输出语句
}
var it = main();//返回迭代器对象
it.next();//执行yield表达式里的request函数
十、Async
将异步操作同步化
let axios = require('axios')
//function前加async
async function foo(){
//只有当前的异步操作完成后,才能执行下面的输出操作
let customers = await axios.get("http://39.105.67.242:5588/customer/findAll");
console.log("customers:",customers.data.data[0].id);
}
foo();
十一、模块化
CommonJS API将通过定义处理许多常见应用程序需求的API来填补javascript规范没有定义用于构建更广泛应用程序的标准库的缺点,最终提供与Python、Ruby和Java一样丰富的标准库。其意图是应用程序开发人员能够使用CommonJS API编写应用程序,然后在不同的JavaScript解释器和主机环境中运行该应用程序。
11.1 模块化作用域
每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见.
全局属性
global.warn = true
- 私有属性
11.2 模块的导入导出(模块交互)
CommanJS
导出(定义模块)
//module变量代表当前模块,其exports属性是对外的接口 module.exports.a = a
导入(模块加载)
let b = require('模块路径') console.log(b.a)
es6
导出
export default xx
导入
import xx from ''
11.3 模块对象
- module.id 模块的识别符,通常是带有绝对路径的模块文件名。
- module.filename 模块的文件名,带有绝对路径。
- module.loaded 返回一个布尔值,表示模块是否已经完成加载。
- module.parent 返回一个对象,表示调用该模块的模块。
- module.children 返回一个数组,表示该模块要用到的其他模块。
- module.exports 表示模块对外输出的值。
11.2 path模块
用于文件路径
安装path模块
npm install path
引入path模块
var path = require('path')
- basename('') 返回文件名
- dirname('')返回目录名
- extname('')返回文件扩展名
let path = require('path')
console.log(path.basename('./a.js')) //a.js
console.log(path.dirname('d:/briup/4-es6/0821/a.js')) //d:/briup/4-es6/0821
console.log(path.extname('./a.js')) //.js
11.3 querystring模块
把对象转换成查询字符串
let res = querystring.stringify(obj)
把查询字符串转换成对象
let str = querystring.parse(res)
十二、npm
Npm是使Js开发者能够更方便的分享和复用以及更新代码,被复用的代码被称为包或者模块,一个模块中包含了一到多个js文件。在模块中一般还会包含一个package.json的文件,该文件中包含了该模块的配置信息。一个完整的项目,需要依赖很多个模块。
> npm init
创建配置文件package.json
> npm init -y
创建默认配置文件
> npm install npm@latest -g
更新npm(npm会随着node一起被安装到本地)
> npm install -g cnpm --registry=https://registry.npm.taobao.org
安装淘宝镜像,加快下载速度
> npm install + '依赖的名字'
安装模块,安装模块时,默认会将所安装的模块写入到package.json中的dependencies属性中。如果想要仅在当前模块中使用某个第三方模块,就可以使用npm install的默认安装,默认安装即是本地安装;如果想要在命令行中使用模块,就需要进行全局安装。
> npm install
安装所有项目依赖的模块(依赖关系在配置文件中已存在)
> npm update <module_name>
更新模块
> npm uninstall -g <package_name>
从node_modules中删除不需要的模块
> npm uninstall –save -g <package_name>
不仅删除node_modules中的依赖,还需要删除package.json中的信息,可以使用—save参数
- -g 全局安装,一处安装处处使用,不加-g,即为局部安装,只在当前路径内有效
十三、babel
babel用于将es6转换成浏览器可识别的es5(因为浏览器只能识别一部分es6的语法)
> babel a.js //将a.js代码转换为es6
> babel a.js --out-file test.js //将a.js的代码转换成es5并导入到test.js文件中
babel src --out-dir srcc //将src文件夹中所有的文件转换为es5并导入到srcc文件夹下
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。