ES6系列---【ES6新语法】

1、ES6与JavaScript的区别

​ ES6仅仅是一种语法规范。JavaScript只是ES6的一种实现,具体实现到多少看浏览器厂家执行规范的程度。javascirpt 还包括DOM、BOM,另外JavaScript还可以应用与后台开发环境例如node。

2、let 与 const

ES6新增用于声明变量的语法。

2.1 let与var的区别

a) var 是函数作用域,let是块作用域

  • let与var 用法是一样的

  • let在 if、for循环等语句中声明的变量也是局部变量

  • 优点:et声明的变量可以防止全局污染。容易产生bug

b) var 有变量提升,let不存在变量提升

  • let变量声明必须先声明,再使用,否则报错;

  • 优点:对于开发者来说,代码更严谨,报错更加一目了然,容易排除。

c) var 可以重复声明的,let在同一作用域下不能重复声明

  • 函数的形参let 也不允许重复声明。

  • 优点:在复杂的项目开发中,程序员重复声明变量在所难免,var的情况不报错,不易觉察,容易产生bug。let直接报错,比较直观容易排除

2.2 let变量在for循环中的应用

​ let变量在for循环中,分为父作用域和子作用域。for循环的圆括号中的变量是父作用域中,for循环的大括号实际为子作用域。

  var btns = document.getElementsByTagName("button");
    for (let i = 0; i < btns.length; i++) {
      btns[i].onclick = function () {
        alert(i + 1);
      }
    }

3、const 常量

const常量用于项目中不经常会改变的内容。例如:地址,数据库账号,密码、圆周率PI

  • const特征:

  • 一旦被声明并赋值后不可再改动

  • 声明和赋值必须同时进行

  • 其他特征和let一样

  • 约定俗称:常量名称大写

  • 特殊说明:

    const常量对于复杂类型来说,只能保证保存地址的不能被更改,至于地址指向的内容是可以修改的。

4、et变量与顶级对象(window)解绑

  • var 声明的全局变量,实际上是window对象的属性,这是JavaScript遗留的设计败笔
  • 从ES6开始,let 声明的变量与window对象不再绑定
 let a = "ok";
 console.log( window.a ); //undefined

4、解构赋值

​ 解构赋值: ES6按照一定的模式,将结构化的数据(数组、对象)中的数据提取出来,赋值给变量

  • 总结特征:

    • 必须有赋值运算符(等号)
    • 等号的前面是模式和变量
    • 等号的后面是数组或对象
  • 数组解构赋值的几种情况

  • 要解构的数据和变量一一对应

  • 要解构的数据比变量多,没有影响

  • 要解构的数据比变量少,解构失败变量的值为undefined

  • 解构赋值允许使用 空的逗号实现缺省

  • 解构赋值的默认值(当解构赋值失败时或者严格等于undefined时默认值生效)

let [x=1,y=x] = []; // x=1 y=1
let [x=1,y=x] = [2]; //x=2, y=2
let [x=1,y=x] = [1,2]; //x=1 y=2
let [x=y,y=1] = []; //报错,变量y未声明即使用了
  • 对象解构赋值的情况

  • 对象的解构赋值,因为对象中的属性没有次序,因此对象必须依靠键的匹配实现解构赋值。

  • 对象解构赋值的默认值(当解构赋值失败时或者严格等于undefined时默认值生效)

// let {name:xxx,sex:yyy,age:zzz} = {name:"张三",age:20,sex:"男"}
  // console.log( xxx, yyy,zzz);
  // 实际可能写为:
  // let {name:name,sex:sex,age:age} = {name:"张三",age:20,sex:"男"}
  // console.log( name,sex,age);
  // ES6允许简化为:
  let {name,sex,age} = {name:"张三",age:20,sex:"男"}
  console.log( name,sex,age);
  • 函数形参的解构赋值

    • 可利用数组实现解构赋值。注意声明函数时的形参此时不是数组,是模式和变量
     function fn([a,b,c]){
        console.log( a+b+c );
      }
      fn([2,3,4]); */
      // 相当于
      // let [a,b,c] =  [2,3,4]   
    
    • 利用对象实现函数解构赋值。注意,声明函数时的形参不是对象,是模式和变量\
    function demo({x,y}){
        return x*y
      }
      console.log( demo({x:2,y:2}) ); */
      // 相当于
      // let {x,y} = {x:2,y:2}
    
    • 函数形参解构赋值时的默认值
    function fn({x=0,y=0}){
        return x*y
      } */
      // console.log( fn({x:1}) )
    

5、解构赋值应用场景

1) 交换变量的值

2) 获取函数的多个返回值

3)利用解构赋值实现ajax封装函数

  // 利用解构赋值实现ajax封装函数。可灵活使用解构赋值的默认值,这样调用函数时只需要传递必要的参数即可
  function sendAjax({type="get",url,data=null,dataType="json",timeout="5000"}) {
    $.ajax({
      type: type, //请求的方法 get post
      url: url,  //请求的地址
      data: data, // 请求时发送的数据
      dataType: dataType, //期望返回的数据类型
      // ajax成功后的回调函数
      success: function (response) {
        console.log(respnse);
      },
      // 失败时的回调函数
      error: function (err) {
        console.log(err);
      }
    });
  }
  // 函数调用时传递实参为一个对象
  sendAjax({url:"http://baidu.com/01.json"});
  sendAjax({url:"http://baidu.com/02.json"});

以上代码进一步优化为:

将封装函数保存为外部js, 需要时引用:

  // 利用解构赋值实现ajax封装函数。可灵活使用解构赋值的默认值,这样调用函数时只需要传递必要的参数即可
  function sendAjax({type="get",url,data=null,dataType="json",timeOut="5000"},callback) {
    $.ajax({
      type: type, //请求的方法 get post
      url: url,  //请求的地址
      data: data, // 请求时发送的数据
      dataType: dataType, //期望返回的数据类型
      // ajax成功后的回调函数
      success: function (response) {
        // console.log(respnse);
        callback(response)
      },
      // 失败时的回调函数
      error: function (err) {
        console.log(err);
      }
    });
  }
<script src="./sendAjax.js"></script>
<script>
sendAjax({type:"post",url:"http://api.shenzhou888.com.cn/v2/ecapi.banner.list"},function(data){
    // 渲染页面代码
    console.log( data );
  });
</script>

6、字符串扩展--模板字符串

​ ES6可以使用模板字符串(``) 代替原来的繁琐的拼字符串渲染页面的方式。可以使用 ${ } 来嵌套变量或js表达式。

  let str = `<ul>
      <li><span class="name">姓名:</span><span class="uname">${student.name}</span></li>
      <ul>
        <li>${ "语文:"+ student.score[0]}</li>
        <li>${ "数学:"+ student.score[1]}</li>
        <li>${ student.score[2]}</li>
      </ul>
      <li>性别:${ student.sex }</li>
    </ul>`;

    let box = document.getElementById("box");
    box.innerHTML = str;

7、ES6对象扩展

  • 允许属性名简写
  let name = "jack";
  let sex = "男"
  let obj = {
    name,
    sex,
    say(){
      console.log( name );
    }
  }

  • ES6支持对象的键为表达式
let city = {};
  for(let i=0;i<26;i++){
    console.log( String.fromCharCode(i+65) );
    let key = String.fromCharCode(i+65);
    city[key] = [];
  }
  • 几个静态方法
    • Object.assign() 对象的合并
    • Object.keys() 获取对象上所有的键,以数组的形式返回
    • Object.values() 获取对象上所有的值,以数组的形式返回
  // 对象的合并,第一个参数为合并的目标对象
  let obj1 ={ name:"jack"};
  let obj2 = { sex:"男"};
  Object.assign(obj1, obj2);

  console.log( obj1 );

8、数组扩展

  • Array.from() 将类数组对象转换为真正的数组
  // nodelist, htmlCollection, argument 类数组对象
// 典型的类数组对象的形式:
  let obj = {
    "0":"hello",
    "1":"world",
    "length":2
  }
  console.log( obj );
  console.log( Array.from(obj) );

  • includes()

​ 用来查找数组中是否存在指定的值,有就返回true, 没有返回false。与indexOf的功能类似。

  // includes() 用来查找数组中是否存在指定的值,有就返回true, 没有返回false。解决了indexOf()对NaN无效的bug
  let arr = [2,3,4,5,NaN];
/*   if( arr.indexOf(NaN) != -1 ){
    console.log("找到了");
  }else{
    console.log("没找到");
  } */
  if( arr.includes(NaN) ){
    console.log("找到了");
  }else{
    console.log("没找到");
  }

9、函数扩展

ES6可以使用箭头(=>)来简化函数的声明。

  • 特征: 用 => 替换了 function

  • =>的后面:

    • 如果函数体内只有一行代码,大括号可省略
    • 如果只有一行代码而且是return语句,return 也可省略
    • 如果只有一行代码而且是retrun一个对象,为了避免歧义,要使用圆括号包起来
  • =>的前面:

    • 如果只有一个形参,圆括号也可以省略
    • 如果有多个或者没有形参,圆括号不能省略
  • 箭头函数中的this指向规律

  • ES6之前的普通函数中this指向规律:

    1)在全局函数或定时器的回调函数中this指向 window

    2)在事件处理函数中this指向事件源

    3)在对象的方法中this指向对象本身

    4)可使用call/apply/bind 改变this指向

  • ES6中箭头函数的this指向规律:

    1)定义好箭头函数后,this的指向就确定了,与call/apply等没有关系

    2)永远指向其上层环境(环境指的的是函数内或全局下,只有这两种情况,其他的大括号不能称为环境)

  function Person(){
    let fn1 = ()=>{
      console.log( this );
    }
    fn1();
  }
// 1、Person当普通函数调用时
  // Person();
// 2、Person当构造函数使用时,构造函数中的this发生了改变,指向创建的新对象。那么箭头函数中的this也指向新创建的对象。
  new Person();
  • 箭头函数的不适应用的情况:

​ 1)事件处理函数中;

​ 2)对象的方法中;

​ 3)构造函数中

函数形参的默认值

  // 函数形参的默认值
  function fn(name="杨营"){
    // if(!name){
    //   name = "杨营";
    // }
    // name = name || "杨颖";  //短路语法
    console.log(`我是:${name}` );
  }
  fn("刘子琪")

rest剩余参数运算符 和 spread 扩展运算符

rest 剩余参数,用于获取多余(全部)的实参并放入一个数组中。

  // rest剩余参数运算符(...),只出现在函数形参声明处,作用可代替arguments,实现将实参转换为数组
  function fn(...c){
    console.log( Array.from(arguments)  );
    console.log( c );
  }
  fn(1,2,3,4,5,6)

spread扩展运算符(...),作用是将结构化的参数(数组,对象)转换为逗号分隔的参数序列。类似rest的逆运算。

/*   let arr = [2,3,4,5]
  console.log( ...arr );
 */
  // 应用场景1 -- 函数传参
/*   let arr = [2,5,0,9];
  console.log( Math.min(...arr) );  */
  // 应用场景2--数组合并
  let arr1 = [2,3,4,5];
  let arr2 = ["hello","ok"];
  let arr3 = [...arr1,...arr2];
  // 对象合并
  let obj1 = {
    name:"jack"
  }
  let obj2 = {
    age:20
  }
  let obj3 = {
    ...obj1,
    ...obj2
  }
  console.log( obj3 );

10、symbol 类型

​ symbol是ES6新增的数据类型,string、number、boolean、null、undefined、object、symbol。

  // symbol类型,作用是产生一个永不和其他symbol相同的独一无二的值。
  // 创建symbol时可添加一个参数,起到在控制台输出时的区分作用,类似于程序中的注释,对程序的执行没有任何影响
  let s1 = Symbol("老大");
  let s2 = Symbol("老二");
  console.log(typeof s1); 
  console.log( s1 == s2 ); //永远false
  console.log(s1,s2);

11、set数据类型

​ set 是ES6新增的类似数组的数据结构。特点:set中的成员永远是唯一,允许重复。set的主要作用是过滤数组中重复的项。

  // set 数据类型,类似数组的数据结构,作用:可以过滤到数组中重复的项
  let arr = [2,3,2,4,3,0,1,4];
  let s1 = new Set(arr);
  console.log( s1 );
  console.log( Array.from(s1) );

set 自有的属性和方法:

size set中成员的个数

add() 添加某个值

delete() 删除某个值

has() 返回一个布尔值,表明是否包含有某个值

clear() 清除set中所有成员

12、Map数据类型

​ Map是ES6新增的类似对象的数据结构,也是键值对的集合。

  • 特点:键的范围不限于字符串,可以是各种类型的值都可以当做键,比object提供的‘字符串一值’的对应更加完善

  • set 自有的属性和方法:

    • size 类似数组的length属性:size用于返回Map集合的内容长度
    • set(key,value):添加一个键值数据
    • get(key):根据key获取value
    • has(key):返回布尔值,表明是否包含有某个值
    • delete(key):根据指定的key删除数据
    • clear():清除Map中所有成员,没有返回值
    //Map基本使用
    let m = new Map();
    m.set('c', 'content')
    m.get('c')//content
    m.size//1
    m.has('c') // true
    m.delete('c')
    m.has('c')
    m.clear()
    
    //Map结构和数组结构之间的转换
    let map = new Map([
      [1, 'one'],
      [2, 'two'],
      [3, 'three'],
    ]);
    [...map.keys()]// [1, 2, 3]
    [...map.values()]// ['one', 'two', 'three']
    [...map.entries()]// [[1,'one'], [2, 'two'], [3, 'three']]
    [...map]// [[1,'one'], [2, 'two'], [3, 'three']]
    
  • Map 循环遍历

    Map 原生提供三个遍历器:

    • keys():返回键名的遍历器。
    • values():返回键值的遍历器。
    • entries():返回所有成员的遍历器
let map = new Map([
  ['F', 'no'],
  ['T',  'yes'],
]);
for (let key of map.keys()) {
  console.log(key);
}
// "F"
// "T"
for (let value of map.values()) {
  console.log(value);
}
// "no"
// "yes"
for (let item of map.entries()) {
  console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
  console.log(key, value);
}
// 等同于使用map.entries()
for (let [key, value] of map) {
  console.log(key, value);
}
上面代码最后的那个例子,表示 Map 结构的默认遍历器接口(Symbol.iterator 属性),就是 entries 方法。
map[Symbol.iterator] === map.entries // true

posted on 2021-04-13 19:37  码农小小海  阅读(397)  评论(0编辑  收藏  举报

导航