es6基础 和es5新增方法forEach ,map ,filter ,some ,every ,reduce方法

ES6新特性

  1. 变量

  2. 函数

  3. 数组

  4. 字符串

  5. 面向对象

  6. Promise

  7. yield

  8. 模块化

变量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允许按照一定的模式, 从数组和对象中提取值, 然后对变量进行赋值.

解构赋值分为数组的解构赋值、对象的解构赋值、字符串的解构赋值、数值和布尔值的解构赋值、函数参数的解构赋值、函数的参数的解构赋值

解构赋值的本质: 模式匹配. 只要 = 两侧的模式相同, 左侧的变量就可以被赋予对应的值.

数组的结构
  1. 原始方法的解构赋值

    let arr=[1,2,3];
    let a=arr[0];
    let b=arr[1];
    let c=arr[2];
    console.log(a,b,c)
    
  2. 使用解构赋值

    // 方法一
    {
      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);
    
  3. 不完全解构

    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);
    
  4. 不定长度的解构赋值

    let color = ['red','green','blue','pink','black','white'];
    let [col1,...col2] = color;
    console.log(col1,col2);
    
对象的解构赋值

注意:对象的解构赋值与数组有一个重要的不同, 数组的元素是按顺序排列的, 变量的取值由先后位置决定, 而对象的属性没有次序, 只要键名匹配成功即可完成赋值

  1. 变量名与键名一致(对象的字面量表示法)

    let {brand, price} = {brand: '宝马', price: 740};
    let {price,brand}={brand:'宝马',price:250};
    
    console.log(brand, price);
    
  2. 变量名与键名不一致

    let {brand: a, price: b} = {brand: '宝马', price: 740};
    console.log(a, b);
    
  3. 同一个对象给六个变量赋值

    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);

解构赋值的用途

  1. 交换变量的值

    let a = 3, b = 5;
    [a, b] = [b, a];
    console.log(a, b);
    
  2. 从函数内部返回多个值

    let {dataObj} = {code: 200, msg: 'ok', dataObj: ['jack','rose','bob','小明']}; 
    console.log(dataObj);
    
  3. 可以迅速提取一个对象中的方法;

    let {floor, random, sin} = Math;
    console.log('======');
    console.log(Math.floor(Math.random() * 256)); // 原来的操作
    console.log(floor(random() * 256));	// 现在的操作
    

箭头函数

箭头函数也称为也称为胖箭头函数;

箭头函数的基本语法:()=>{}

定义箭头函数
  1. 通过事件直接调用匿名函数

    window.onload=function(){
    	alert('abc');
    }
    window.onload=()=>{
    	alert('abc')
    }
    
  2. 通过赋值的方式创建函数

    let show=function(){
    	alert('abc');
    }
    let show=()=>{
    	alert('abc');
    }
    show();
    
  3. 可以传参的箭头函数

    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 变成一个静态的值了)

箭头函数的默认值
  1. 参数的默认值不是传值, 而是每次都会重新计算

    let x = 100;
    function fun2(a = x + 1) {
    	console.log(a);
    }
    fun2();// 101
    x = 1000;
    fun2();// 1001
    
  2. 一般设置默认值的参数应该是函数的尾参数

    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)。

  1. 实现数组的深拷贝(只能有一层引用类型)

    // 普通拷贝
    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);
    
  2. 向函数传递参数

    function show(a,b,c){
      alert(a);
      alert(b);
      alert(c);
    }
    // show(1,2,3); // 正常调用
    show(...arr); // 使用...arg调用
    
  3. 合并数组

    let arr1=[1,2,3];
    let arr2=[4,5,6];
    let arr3=arr1.concat(arr2); // 使用concat拼接
    // let arr3=[...arr1,...arr2]; // 使用rest参数
    alert(arr3);
    
  4. 伪数组

    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);
    })
    
  5. 与解构赋值一起使用

    let [a, ...rest] = [9, 5, 2, 7];
    console.log(a, rest);
    
  6. 函数嵌套中使用传递参数

    function show(...args){
    	fn(...args);
    }
    function fn(a,b){
    	alert(a+b)
    }
    show(12,5);
    
  7. 对象中使用

    let person = {name:'jack',age:18,sex:'男'};
    console.log({...person}); // 可以获取;使用字面量的形式复制一个对象并输出(使用展开运算符创建字面量对象)
    

字符串的扩展

  1. 字符串模板。【${}

    // 自定义背景颜色
    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))}`);
    
  2. includes(‘被查找的内容’, 从下标index的位置开始查找)

  3. startWith(str[, index]) 以…开头

  4. endWidth(str[, index]) 以… 结尾

  5. repeat(n): 让字符串重复几次

  6. padStart(num[, str]) num:填充内容的长度, 在字符串的前面填充内容

  7. padEnd(num[, str]) num:填充内容的长度 在字符串的后面填充内容

  8. trimStart() 去掉字符串前面的空格

  9. trimEnd() 去掉字符串后面的空格

  10. 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
  }]
}
  1. 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返回值

  2. 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);
    
  3. filter(过滤) 返回符合条件的记录

    return true,则把当前记录存入新数组,否则不存

    let newData = data.list.filter((item, index) => {
      return item.price > 400
    })
    console.log(newData);
    
  4. some 如果有符合条件的记录,则返回真,否则返回假

    let newData = data.list.some((item, index) => {
      console.log(index);
      return item.price == 400
    })
    console.log(newData);
    
  5. every 如果每一个都符合条件,则返回真,否则返回假

    let newData = data.list.every((item, index) => {
      console.log(index);
      return item.price > 600
    })
    console.log(newData);
    
  6. 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();