ES6新特性
变量
函数
数组
字符串
面向对象
Promise
yield
模块化
变量Let
ES5作用域: 全局作用域,函数作用域(局部作用域)
ES6新增
let: 定义变量
- 定义块级作用域 {}
- 在同一块级作用域不能重复声明
const: 定义常量
- 声明必须赋值
- 不允许更改
块级作用域
花括号包括起来的就是块,就是块语法,大家比较常见的可能是if(){},for(){}这都是语法块,块级作用域
特点1: 同一个代码块中不允许声明同名的变量
let a = 10;
var b = 100;
let a = 100;
console.log(a);
注意2: let声明的是一个变量,变量是可读可改的,能修改
let a=200;
a = 'hello'
console.log(a) // hello
注意3: let 声明的变量, 不存在 声明前置
console.log(c);// 报错
let c = 5;
console.log(c);
注意4: 通过 let 声明的变量只在 let 命令所在的代码块内有效
ES 6中变量的作用域: 块级作用域 ----- {}
if(true){
let a=12
}
alert(a);// 报错,a只在上面的语法块中才有用
案例:块级作用域怎么用
<script>
window.onload=function(){
var aBtn=document.getElementsByTagName('input');
for(var i=0;i<aBtn.length;i++){
aBtn[i].index=i; // 存储i下标值
aBtn[i].onclick=function(){
console.log(i); // 每次打印出来的都是3
console.log(this.index); // 0,1,2
}
}
}
</script>
<input type="button" value="按钮1"/>
<input type="button" value="按钮2"/>
<input type="button" value="按钮3"/>
<script>
for(let i=0;i<aBtn.length;i++){
aBtn[i].onclick=function(){
console.log(i); // 0,1,2
}
}
</script>
暂时性死区: 在代码块内, 使用 let 声明变量之前, 该变量是不可用的.
常量const
const 用于声明一个只读的常量
注意一:同一个代码块中不允许声明同名的变量
const a=100;
const a=200; // 报错,不能重复定义
console.log(a);
注意二:const声明的是一个常量,常量只读不改
const PIM = 3.14;
// PIM = 3;// 报错
console.log(PIM);
注意三:块级作用域,只在花括号里面有效
if(true){
const a=12
}
alert(a);//报错
注意四: 如果 const 保存的是数组/对象/函数等 空间的地址时, 只能保证 所保存的地址不变, 地址中的值, 无法控制.
let numArr = [9, 5, 2, 7];// [9,5,2,7]
const arrP = numArr;
numArr[0] = 99;
console.log(arrP);// [99,5,2,7]
console.log(numArr); // [99,5,2,7]
解构赋值【拆解架构,重新赋值】
ES 6允许按照一定的模式, 从数组和对象中提取值, 然后对变量进行赋值.
解构赋值分为数组的解构赋值、对象的解构赋值、字符串的解构赋值、数值和布尔值的解构赋值、函数参数的解构赋值、函数的参数的解构赋值
解构赋值的本质: 模式匹配. 只要 = 两侧的模式相同, 左侧的变量就可以被赋予对应的值.
数组的结构
原始方法的解构赋值
let arr=[1,2,3]; let a=arr[0]; let b=arr[1]; let c=arr[2]; console.log(a,b,c)使用解构赋值
// 方法一 { let [a,b,c]=[1,2,3]; console.log(a,b,c) } // 方法二 { let a,b,c; [a,b,c]=[1,2,3]; console.log(a,b,c) } // 错误示范 let [a,b,c,d]; [a, b, c, d] = [9, 5, 2, 7]; console.log(a, b, c, d);不完全解构
let arr = [4, 7, 9, 3]; let [num1,num2] = arr; let [,num1,num2] = arr; let [num1,num2,...num3] = arr; let [num1, , , num2] = arr; console.log(num1, num2);不定长度的解构赋值
let color = ['red','green','blue','pink','black','white']; let [col1,...col2] = color; console.log(col1,col2);
对象的解构赋值
注意:对象的解构赋值与数组有一个重要的不同, 数组的元素是按顺序排列的, 变量的取值由先后位置决定, 而对象的属性没有次序, 只要键名匹配成功即可完成赋值
变量名与键名一致(对象的字面量表示法)
let {brand, price} = {brand: '宝马', price: 740}; let {price,brand}={brand:'宝马',price:250}; console.log(brand, price);变量名与键名不一致
let {brand: a, price: b} = {brand: '宝马', price: 740}; console.log(a, b);同一个对象给六个变量赋值
let dataObj = { codeNum: '200', codeMsg: 'ok', data: [ {name: '刘德华', age: 60}, {name: '刘德华', age: 60} ] }; let {codeNum, data, data: listObj, data: [dataPer], data:[{name, age}]} = dataObj;
注意:已经声明过的变量, 用于解构赋值时要特别小心. {} 很容易被系统识别
字符串的解构赋值
字符串能够使用解构赋值的原因是: 字符串时特殊的数组(字符串能够被转换成一个类似数组的对象)
let [a, b, c, d, e] = "Hello";
console.log(a, b, c, d, e);
解构赋值的用途
交换变量的值
let a = 3, b = 5; [a, b] = [b, a]; console.log(a, b);从函数内部返回多个值
let {dataObj} = {code: 200, msg: 'ok', dataObj: ['jack','rose','bob','小明']}; console.log(dataObj);可以迅速提取一个对象中的方法;
let {floor, random, sin} = Math; console.log('======'); console.log(Math.floor(Math.random() * 256)); // 原来的操作 console.log(floor(random() * 256)); // 现在的操作
箭头函数
箭头函数也称为也称为胖箭头函数;
箭头函数的基本语法:()=>{}
定义箭头函数
通过事件直接调用匿名函数
window.onload=function(){ alert('abc'); } window.onload=()=>{ alert('abc') }通过赋值的方式创建函数
let show=function(){ alert('abc'); } let show=()=>{ alert('abc'); } show();可以传参的箭头函数
let show=function(a,b){ alert(a+b); } show(12,6); let show=(a,b)=>{ alert(a+b); } show(12,6);
案例:给下面数组排序
let arr=[12,5,3,67,23,99,14,25];// 正序排序
// 普通方法
arr.sort(function(a,b){
return a-b;
});
// 改写为箭头函数
arr.sort((a,b)=>{
return a-b
});
alert(arr);
但是这里面几个注意事项:
A. 如果只有一个参数,()可以省
B. 如果只有一条语句,{}可以省
C. 只有一条语句的时候,并且使用return进行返回,不仅{}可以省略,return也可以省略
D.在箭头函数中不能使用arguments
注意1:如果只有一个参数,()可以省
// 求一个数的平方是多少
let show=function(a){
alert(a*2)
}
// 简写成箭头函数
let show=(a)=>{
alert(a*2)
}
// 强调:只有一个参数,就可以省略(),强调一下,只有一个多了不行,少了也不行
let show=a=>{
alert(a*2)
}
show(12);
注意二:如果只有一条语句,{}可以省略
let show=a=>alert(a*2) // 意思很明白:进去是a,吐出来是2*2
show(12);
注意三:如果只有一条语句,并且是用return进行返回,不仅{}可以省略,return也可以省略
let show=a=>(a*2) // 意思很明白:进去是a,吐出来是2*2
alert(show(12));
案例:添加一个函数,功能2秒钟之后改变页面的背景颜色
注意四:不能使用arguments
function gets(){
console.log(arguments);
}
let gets=()=>{
console.log(arguments);
}
gets(12,34,23,4);
箭头函数使用注意事项: 函数体内 this 是定义时所在的对象, 不再是使用时所在的对象(此时 this 变成一个静态的值了)
箭头函数的默认值
参数的默认值不是传值, 而是每次都会重新计算
let x = 100; function fun2(a = x + 1) { console.log(a); } fun2();// 101 x = 1000; fun2();// 1001一般设置默认值的参数应该是函数的尾参数
function fun3(a, b = 3) { console.log(a, b); } fun3(5);
获取剩余(rest)参数 […args ],等同于es5中的arguments
ES5中的arguments和ES6中rest剩余参数的区别是:argument中是伪数组,rest中是真数组
function total(...args){
// ES5:
// console.log(arguments) //伪数组
// args: 真数组
console.log(args instanceof Array);
console.log(args);
}
其实就是展开运算符 + 变量名
show=(a,b,...args)=>{
alert(a);
alert(b);
alert(args)
}
show(12,15,23,43,11);
注意:…args 必须是最后一个行参
函数的两个属性
ES6里面提供了函数的两个属性,分别是:length和name
length: 获取数组中参数的长度
但是,如果参数指定了默认值,函数的length属性将返回没有指定默认值的参数个数
function fun(a, b,c,d) {
}
console.log(fun.length);
Name: 函数的name属性,返回该函数的函数名
function fun1() {
}
console.log(fun1.name);
注意一:使用匿名函数表达式的方法定义的函数,它的name属性值就是变量的名字
let fun2 = function(argument){
}
console.log(fun2.name) //fun2
注意二:函数声明的优先级高于变量名
let superFun3 = function fun3(argument){
}
console.log(superFun3.name) //fun3
展开运算符
展开运算符: …
三个连续的点具有两个含义:展开运算符(spread operator)和剩余运算符(rest operator)。
实现数组的深拷贝(只能有一层引用类型)
// 普通拷贝 let arr1 = [1,2,3]; let arr2 = []; arr2[1] = 'hello'; console.log(arr1,arr2); // 深拷贝 let arr1 = [1,2,3]; let arr2 = [...arr1]; // 等价于:arr2 = [arr[0],arr[1],arr[2]] arr2[1] = 'hello'; console.log(arr1,arr2);向函数传递参数
function show(a,b,c){ alert(a); alert(b); alert(c); } // show(1,2,3); // 正常调用 show(...arr); // 使用...arg调用合并数组
let arr1=[1,2,3]; let arr2=[4,5,6]; let arr3=arr1.concat(arr2); // 使用concat拼接 // let arr3=[...arr1,...arr2]; // 使用rest参数 alert(arr3);伪数组
let divList = document.querySelectorAll("div"); // ES5 // for (var i = 0; i < divList.length; i++){ // console.log(divList[i].innerHTML); // } let targetDom = [...divList].filter(el => { console.log(el); })与解构赋值一起使用
let [a, ...rest] = [9, 5, 2, 7]; console.log(a, rest);函数嵌套中使用传递参数
function show(...args){ fn(...args); } function fn(a,b){ alert(a+b) } show(12,5);对象中使用
let person = {name:'jack',age:18,sex:'男'}; console.log({...person}); // 可以获取;使用字面量的形式复制一个对象并输出(使用展开运算符创建字面量对象)
字符串的扩展
字符串模板。【
${}】// 自定义背景颜色 let r = 255, g = 255, b = 0; // 原来的操作 document.body.style.background = 'rgb('+r+','+g+','+b+')'; // 现在的操作 document.body.style.background = `rgb(${r}, ${g}, ${b})`; // 输出小明的身高,体重,和BMI值 let weight = 75; let height = 1.75; // 体重(千克)/身高(米)的平方即kg/m2 console.log(`小明的身高是${weight},体重是${height},BMI值为${parseInt(weight/(height*height))}`);includes(‘被查找的内容’, 从下标index的位置开始查找)
startWith(str[, index]) 以…开头
endWidth(str[, index]) 以… 结尾
repeat(n): 让字符串重复几次
padStart(num[, str]) num:填充内容的长度, 在字符串的前面填充内容
padEnd(num[, str]) num:填充内容的长度 在字符串的后面填充内容
trimStart() 去掉字符串前面的空格
trimEnd() 去掉字符串后面的空格
trim() 去掉字符创两边的空格
ES5中常见的数组方法
ES5常见的数组方法:forEach ,map ,filter ,some ,every ,reduce (除了forEach,其他都有回调,都有return)
面试题:ES5中常见的数组方法有哪些?
let data = {
code: 1,
list: [{
id: 23,
title: "女装1",
price: 300
}, {
id: 24,
title: "女装2",
price: 200
}, {
id: 27,
title: "男装1",
price: 100
}, {
id: 29,
title: "男装2",
price: 400
}, {
id: 230,
title: "女装3",
price: 600
}, {
id: 40,
title: "童装1",
price: 700
}]
}
forEach (循环迭代)
forEach(f(item[,index]){})语法
f:是回调函数
item:数组中的每一个值
index:表示下标值
let arr=[12,5,8,9]; arr.forEach((item,index)=>{ console.log(item,index); })data.list.forEach((item, index) => { // console.log(item, index); console.log(item.price); if (item.price == 100) { break; //报错 } })缺点: 不能使用break和continue
没有return返回值
map(映射): 遍历数据并返回一个新的数组,对数据的处理会返回原先对应的位置
需求:所有产品的价格都打5折
let newData = data.list.map((item, index) => { return { id: item.id, title: item.title, price: item.price * 0.6 } }) console.log(newData);let newData = data.list.map((item, index) => { let {id,title,price} = item; return {id,title,price: price * 0.6} }) console.log(newData);filter(过滤) 返回符合条件的记录
return true,则把当前记录存入新数组,否则不存
let newData = data.list.filter((item, index) => { return item.price > 400 }) console.log(newData);some 如果有符合条件的记录,则返回真,否则返回假
let newData = data.list.some((item, index) => { console.log(index); return item.price == 400 }) console.log(newData);every 如果每一个都符合条件,则返回真,否则返回假
let newData = data.list.every((item, index) => { console.log(index); return item.price > 600 }) console.log(newData);reduce(汇总) 常用来实现累加
// let arr = [300, 600, 200, 100] // 首次调用时,sum是第一个元素,val是第二个元素,index是1 // 再次调用时,sum是上一次return的结果,val依次是下一个元素 let result = arr.reduce((sum, val, index) => { // console.log(sum, val, index); return sum + val; }) console.log(result); // 第二个参数是sum的初值, 则第一次调用 时, val是第一个元素 let result = data.list.reduce((sum, val, index) => { return sum + val.price; }, 0) console.log(result);
自面量对象的简写
在ES6中,如果键和值相同,则可以省略不写
let age = 20,
name = 'Alice';
// ES5: 定义对象字面量
let obj = {
age: age,
name: name,
say: function() {
console.log(1);
}
}
// ES6: 定义对象字面量
let obj = {
age,
name,
say() {
console.log(1);
}
}
console.log(obj.name)
obj.say();