es6语法
1. 定义变量
var的缺点:
允许重复声明
不能声明常量
没有块级作用域
let的作用:
不允许重复声明
不能声明常量
变量可以存在块作用域中
const的作用
不允许重复定义
只能声明常量
常量可以存在块作用域中
在es5中使用var可以重复声明,let和const增加了代码的严谨性,在重复声明后会报出变量已声明的错误
var a=1
var a=2
console.log(a) //2
let a=1
let a=2
console.log(a) //SyntaxError:Identifier 'a' has already been declared
因为es5中没有常量的概念,所以先说下常量的含义,常量表示声明后数值就不会发生改变。而const声明的数据分为两种基础数据类型和引用数据类型。基础数据类型声明后不能改变其数值,引用数据类型声明后,不能改变其对象引用,但可以改变对象的内容。
//基础数据类型
const PI=3.1615926
PI=6
console.log(PI)//TypeError:Assignment to constant variable.
//引用数据类型
const user={name:"joker",sex:"male"}
user.sex=22
console.log(user)//{name: "joker", sex: "male", age: 22}
user={name:"lucy",sex:"female",age:"20"} //TypeError:Assignment to constant variable.
像java,c,c++都有块级作用域,对于es5中的作用域只有全局作用域和函数作用域,而let和const的引入,让javaScript也能使用块级作用域.其中块作用域声明的变量为局部变量只在当前作用域有效,而块级作用域解决的一个问题就是方法中不能获取循环变量的当前数值.
function createArr(){
var arr = new Array();
for(var i=0;i<4;i++){
arr[i]=function(){
return i;
}
}
return arr
}
var arrObj=createArr();
console.log(arrObj[0]()) //4
console.log(arrObj[1]()) //4
console.log(arrObj[2]()) //4
console.log(arrObj[3]()) //4
上述代码中出现的这种问题的原因是,javasript中变量的寻找是一级一级往上查询的,当执行arrObj0方法时,当前作用域中没有i变量只能往上级作用域中寻找。执行arrObj0方法时for循环作用域中的i以循环完毕,因为没有块级作用域来保存循环的i,此时寻找到的i为循环后的i既i=4。用伪代码表示执行循序为
var arr=new Array()
var i=0;
for(i;i<4;i++){
arr[i]=function(){
return "bind"
}
//arr[i]=function(){}实际只是将数据和方法绑定,实际并没有的给arr[i]赋值
}
//当调用方法时
arr[3]=function(){
return i
}
console.log(arr[3]())
解决上述问题有三种方案,一种是使用立即执行函数,一种是外部建嵌套立即执行函数,一种是使用let。其中外部嵌套立即执行函数和let原理相同,都是把i存放在了其需求作用域中.
//立即执行函数
function createArr(){
var arr = new Array();
for(var i=0;i<4;i++){
arr[i]=(function(){
return i;
})(i)
}
return arr
}
...
//闭包
function createArr(){
var arr = new Array();
for(var i=0;i<4;i++){
(function(i){
arr[i]=function(){
return i;
}
})(i)
}
return arr
}
...
//使用let
function createArr(){
var arr = new Array();
for(let i=0;i<4;i++){
arr[i]=function(){
return i;
}
}
return arr
}
其中使用let提升作用域后的运行流程伪代码如下:
{
let i=1
arry[i]=function(){
return i
}
}
{
let i=2
arry[i]=function(){
return i
}
...
可以看出因为添加了块级作用域,在方法获取i时上一级作用域发生了改变.获取到的i为保存在块级作用域中的i。
2. 箭头函数
es6中简化了匿名函数的写法,其中使用箭头函数简化了function的声明。
写法如下:
function(){}可以用()=>{}来替代,其中的在箭头函数的()传递参数,若function中只有一个参数则可以去掉箭头函数的(),若funtion中只有return语句则可以去掉箭头函数中的{},例子如下:
//普通写法
function(){
}
functtion(parameter){
}
functtion(parameter1,parameter1){
}
function(parameter1,parameter1){
return parameter1;
}
//箭头函数
()>{
}
parameter=>{
}
(parameter1,parameter1)=>{
}
(parameter1,parameter1)=>return parameter1
其中箭头函数还改变了函数的this指向,箭头函数中的this为从外层作用域中继承的this。
3. 扩展参数
es6引用了rect参数,既用function(...argment)获取多余参数,其中argument是一个数组,将多余的参数存放到argment数组中。示例:
function test(a,b,...argument){
console.log(a) //1
console.log(b) //2
console.log(argument) //[3,4,5]
}
test(1,2,3,4,5)
扩展参数之后不能在添加参数
function(a,...b,c){
}
//SyntaxError: Function statements require a function name
函数的length不包括扩展参数
(function(a) {}).length // 1
(function(...a) {}).length // 0
(function(a, ...b) {}).length // 1
4. 解构赋值
es6添加的了解构赋值,就是对结构相同的对个数据进行赋值.其中需要保证等好两边的数据类型相同
//数组
let [a,b,c]=[1,2,3]
//对象
console.log(a,b,C)//1 2 3
let {arry,obj}={
arry:[1,2,3],
obj:{
name:"wangcai",
sex:"male"
}
}
console.log(arry,obj //[1,2,3] {name:"wangcai"}
其中解构赋值能深层赋值
let {[a,b,c],{name}}={
arry:[1,2,3],
user:{
name:"wangcai"
}
}
console.log(a,b,c,name)// 1 2 3 wangcai
不完全解构
let [[a]]=[[1,2]]
console.log(a) //1
let [ , , third] = ["one", "two", "three"];
console.log(third) // three
解构赋值和扩展参数
let {...argument}={
name:"joke",
age:"20"
}
console.log(argument)
如果解构不成功则变量的值为undefined
let [name] = []
let [age, sex] = ['wangcai']
console.log(name,age,sex) //undefined "wangcai" undefined
5. 函数扩展
函数的默认参数
function test(x=5,y=10){
console.log(x,y)
}
test()//5 10
test(1)//1 10
test(1,20)//1 20
test(undefined,20)//5 20
与解构参数使用
function test( {x,y}){
console.log(x,y)
}
test({x:6,y:20}) //6 20
function test( [x,y]){
console.log(x,y)
}
test([6,20]) //6 20
6. 数组扩展
let a=[1,2,3]
let b=[4,5,6]
let c=[a,b]
console.log(c) //c[[1,2,3],[4,5,6]]
数组合并
let a=[1,2,3]
let b=[4,5,6]
let c=[...a,...b]
console.log(c) //[1,2,3,4,5,6]
map遍历
//遍历的是数组的item,把每个item进行映射到新的数组中
let arry=[45,89,92,57,60,87]
let arry1=arry.map(item=>{
if(item<60){
return "不及格"
}
return "及格"
})
console.log(arry1)//["不及格", "及格", "及格", "不及格", "及格", "及格"]
reduce遍历
//返回的计算的数值,第一个参数为每次计算的结果,第一次循环时,第一个参数为第一个item
let arry=[10,20,30,40,50,60,70]
var avg=arry.reduce((result,nextItem,index)=>{
if(index===arry.length-1){
return (result+nextItem)/arry.length
}
return result+nextItem;
})
console.log(avg)
filter遍历
//根据需求过滤数组,返回一个过滤之后的新数组
let array=[45,37,80,72,59,45]
var pass=array.filter(item=>{
if(item>60){
return item
}
})
console.log(pass)
forEach遍历
//遍历数组的每一项
let array=[45,37,80,72,59,45]
array.forEach((index,item)=>{
console.log('index:{'+index+"}-------value{"+item+"}")
})
7. 字符扩展
字符模板
//字符串用``包裹使用字符模板
var name="wangcai"
var color="black"
var sex="male"
var str=`小狗的名字叫${name},颜色是${color},性别是${sex}`
console.log(str)
8.JSON
json对象转字符串
var a={
name:"wangcai",
color:"black",
sex:"male"
}
var str=JSON.stringify(a)
console.log(str)
字符串转json对象
var str='{"name":"wangcai","color":"white","age":1}'
var obj=JSON.parse(str)
console.log(obj)