02.ES6

发布于:2024-11-29 ⋅ 阅读:(25) ⋅ 点赞:(0)

ES6的特性比较多,在 ES5 发布近 6 年(2009-11 至 2015-6)之后才将其标准化。两个发布版本之间时间跨度很大,所以ES6中的特性比较多。

2.1、let

let 关键字用来声明变量,使用 let 声明的变量有几个特点:

1) 不允许重复声明

2) 块儿级作用域

3) 不存在变量提升

4) 不影响作用域链

5) 暂时性死区

6)不与顶级对象挂钩

在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。 该变量在声明之前使用都属于“暂时性死区“。

应用场景:以后声明变量使用 let 就对了

  <script>
      //声明变量格式
      let a;
      let b, c, d;
      let e = 100;
      let f = 521,
        g = "iloveyou",
        h = [];


      //1. 变量不能重复声明,防止变量被污染
      // let star = '王老师';
      // let star = '余老师';  //会报错


      //2. 块儿级作用域  避免暴露成全局作用域,影响别人
     {
          let girl = '王老师';
          var boy='张老师'
      }
      console.log(girl);//报错
      console.log(boy);//张老师
      
      // if  else  while  for  这些语句里,都是有块级作用域的
       //for 循环的计算器,就很合适let命令
      for(let i=0;i<3;i++){
        console.log(i);//0,1,2
      }
      console.log(i);//报错


      //3. 不影响作用域链
      //作用域链:内层作用域 ——> 外层作用域 ——> 全局作用域
      {
        let school = "bdqn";
        function fn() {
          console.log(school);//在fn作用域没有,还是会向上寻找
        }
        fn();
      }


      //4. 不存在变量提升
      // console.log(song);
      // let song = '恋爱达人';
      
        // 5、let暂时性死区
      var a = 1;
      if (true) {
        a = 2; // 报错,初始化前不能访问a,也就是在同一个作用域中,不可以访问,再定义
        let a = 1;
      }
      
       // 6、 不与顶层对象挂钩
      var myname='zhangsan'
      let myage=18
      console.log(window.myname);//zhangsan
      console.log(window.myage);//undefined
      
    </script>

2.2、const

const 关键字用来声明常量,const 声明有以下特点

1) 声明必须赋初始值

2) 标识符一般为大写(建议)

3) 不允许重复声明

4) 值不允许修改

const实际上保存的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。

但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。

注意: 对象属性修改和数组元素变化不会出发 const 错误, 对象地址不可改变。

5) 块儿级作用域

6)、 不与顶层对象挂钩

应用场景:声明对象类型使用 const,非对象类型声明选择 let

    <script>
        //声明常量
        const SCHOOL = 'bdqn';
        //注意事项
        //1. 一定要赋初始值
        // const A;
        //2. 一般常量使用大写(潜规则)
        // const a = 100;
        //3. 常量的值不能修改
        // SCHOOL = 'bdqn';
        //4. 块儿级作用域
        // {
        //     const PLAYER = 'UZI';
        // }
        // console.log(PLAYER);
        //5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
        const TEAM = ['UZI','MXLG','Ming','Letme'];
        // TEAM.push('Meiko');
          // 6、 不与顶层对象挂钩
      var myname = "zhangsan";
      const myage = 18;
      console.log(window.myname); //zhangsan
      console.log(window.myage); //undefined
    </script>

面试题1.let和const的区别(/var,let,const的区别?)

let声明的变量可以改变,值和类型都可以改变(let:声明的是变量);

const声明的常量不可以改变,这意味着,const一旦声明,就必须立即初始化,不能以后再赋值,当然数组和对象等复合类型的变量,变量名不指向数据,而是指向数据所在的地址。

const只保证变量名指向的地址不变,并不保证该地址的数据不变。

let和const和var的区别

  1. let ,const声明的变量会产生块作用域,var 不会产生块作用域
  2. 不同代码块之间的变量无法互相访问
  3. 注意: 对象属性修改和数组元素变化不会出发 const 错误 (数组和对象存的是引用地址)
  4. 应用场景:声明对象类型使用 const,非对象类型声明选择 let
  5. cosnt声明必须赋初始值,标识符一般为大写,值不允许修改。

2.3、变量的解构赋值

ES6 允许按照一定模式,从数组和对象,字符串中快速的提取成员,对变量进行赋值,这被称为解构赋值。

本质上,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

2.3.1、解构分类

2.3.1.1、数组的解构

ES6中允许从数组中提取值,按照对应位置,对变量赋值

<script>
        //数组的解构
        const F4 = ['小沈阳','刘能','赵四','宋小宝'];
        let [xiao, liu, zhao, song] = F4;
        console.log(xiao);
        console.log(liu);
        console.log(zhao);
        console.log(song); 
        // 省略变量
        let [a, , c] = [1, 2, 3]; 
      console.log(a, c);//1,3
</script>
2.3.1.2、对象的解构

对象的解构与数组有一个重要的不同。数组的元素是按顺序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值,否则解构失败就是undefined。

  <script>
        //对象的解构
     const zhao = {
        name: "赵本山",
        age: "不详",
        xiaopin: function () {
          console.log("我可以演小品");
        },
        data: {
          list: ["贾玲", "沈腾", "···"],
        },
      };

      let {
        name:n,//起别名
        age=18,//可以定义默认值
        xiaopin,
        data: { list },//可以解构下一级数据
      } = zhao;
      console.log(n);//赵本山
      console.log(age);
      console.log(xiaopin);
      console.log(list);
      xiaopin();
        
        let {xiaopin} = zhao;
        xiaopin();
    </script>
2.3.1.3、字符串解构
let [a, b, c] = "hello";
      console.log(a); //h
      console.log(b); //e
      console.log(c); //l
 let { length } = "hello";
      console.log(length);//5

2.3.2、解构应用

2.3.2.1、变量值交换
 let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a);

2.3.2.2、函数返回多个值

function myfun() {
  return [2, 3, 4];
}
let [a, b, c] = myfun();
console.log([a, b, c]);//[2, 3, 4]
console.log(a);//2
console.log(b);//3
console.log(c);//4

2.3.2.3、函数参数传参数

function myfun([a, b, c]) {
    console.log(a);
  }
  myfun([4, 5, 6]);

2.4、模板字符串

ES6 引入新的声明字符串的方式 『``』 '' ""

   <script>
        //1. 声明
        // let str = `我是一个字符串哦!`;
        // console.log(str, typeof str);

        //2. 内容中可以直接出现换行符
        let str = `<ul>
                    <li>孙悟空</li>
                    <li>猪八戒</li>
                    <li>沙悟净</li>
                    <li>白骨精</li>
                    </ul>`;
        //3. 变量拼接 ${lovest}
        let lovest = '沈腾';
        let out = `${lovest}是我心目中最搞笑的演员!!`;
        console.log(out);
    </script>

2.5、字符串扩展

2.5.1、 includes函数

判断字符串中是否存在指定字符,返回布尔值, 语法:string.includes("xxx")

<script>
  let myname = "hello";
  console.log(myname.includes("e")); //true
  console.log(myname.startsWith("o")); //true
  console.log(myname.endsWith("k")); //false
</script>

2.5.2、repeat函数

repeat()方法返回一个新字符串,表示将原字符串重复n次。str.repeat(数值)

    <script>
      let res = "hello";
      console.log(res.repeat(1)); //hello
      console.log(res.repeat(0)); //""
      console.log(res.repeat(2.5)); //hellohello
      console.log(res.repeat("2"); //hellohello
    </script>

2.6、数值扩展

2.6.1、Number.EPSILON

JavaScript 表示的最小精度,一般用在浮点数运算上,

EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16

  console.log(0.1 + 0.2 === 0.3);//false
  
      function equal(a, b) {
        if (Math.abs(a - b) < Number.EPSILON) {
          return true;
        } else {
          return false;
        }
      }
      console.log(equal(0.1 + 0.2, 0.3));//true

2.6.2、二进制和八进制

let b = 0b1010;// 0b开头 二进制
let o = 0o77;// 0o开头 八进制
let d = 100; //十进制
let x = 0xff;//0x开头 十六进制

2.6.3、 Number.isFinite

如果传递的值是有限数字,则返回true。 布尔值,字符串,对象,数组等所有其他内容均返回false:

console.log(Number.isFinite(100));//true
console.log(Number.isFinite(100/0));//false
console.log(Number.isFinite(Infinity));//false
console.log(Number.isFinite(NaN));  //false

2.6.4、Number.isNaN

检测一个数值是否为 NaN,只有对于NaN才返回true,非NaN一律返回false。

console.log(Number.isNaN(123));//false

2.6.5、Number.parseInt Number.parseFloat

字符串转整数

 console.log(Number.parseInt('5211314love'));
 console.log(Number.parseFloat('3.1415926神奇'));

2.6.6、 Number.isInteger

判断一个数是否为整数

 console.log(Number.isInteger(5));//true
 console.log(Number.isInteger(2.5));//false

2.6.7、Math.trunc

将数字的小数部分抹掉        

console.log(Math.trunc(3.5));//3

2.6.8、Math.sign

判断一个数到底为正数 负数 还是零,对于非数值,会先将其转换为数值。        

console.log(Math.sign(100));//1
console.log(Math.sign(0));//0
console.log(Math.sign(-20000));//-1

2.7、数组扩展

2.7.1、Array.from()方法

将伪数组或可遍历对象转换为真正的数组。

  <script>
      //   举例1:
      Array.from("12345"); // [1,2,3,4,5]
      //   举例2:
      let arr1 = {
        1: "a",
        2: "b",
        length: 3,
      };
      console.log(Array.from(arr1)); // [undefined, 'a', 'b']
      //举例3
      function test() {
        console.log(Array.from(arguments));// [1, 2, 3]
      }
      test(1, 2, 3);

       //举例4:选择器
      let divs = document.querySelectorAll("div");
      console.log(Array.from(divs));//[div, div, div]
    </script>

2.7.2、array.find() 方法

  • 该方法主要应用于查找第一个符合条件的数组元素
  • 它的参数是一个回调函数。

在回调函数中可以写你要查找元素的条件,当条件成立为true时,返回该元素。

如果没有符合条件的元素,返回值为undefined

 <script>
      //   举例1:
      let arr1 = [1, 2, 3, 2];
      let res = arr1.find((item) => {
        //   console.log(item,'item');
        //return item>2
        return  item == 2
      });
      console.log(res); //2, 如果未找到,返回undefined

      //   举例2:
      let person = [
        { name: "张三", age: 16 },
        { name: "李四", age: 17 },
        { name: "王五", age: 18 },
      ];

      let target = person.find((item, index) => {
        return  item.name == "张三";
      });
      console.log(target.name);//张三
    </script>

2.7.3、array.findindex()方法

定义:用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1。

   <script>
      let ary = [1, 5, 10, 15];
      let index = ary.findIndex((item, index) => {
        return item > 9;
      });
      console.log(index); // 2   第一个比9大的数字在索引值为2的部位
    </script>

2.7.4、array.includes()方法

定义:判断某个数组是否包含给定的值,返回布尔值

<script>
  let ary = [1, 5, 10, 15];
  console.log(ary.includes(5)); //true
</script>

2.7.5、Array.of()方法

将一组值转化为数组,即新建数组

<script>
  let arr1 = new Array(3);
  console.log(arr1); // [,,]
  let arr2 = Array.of(3);
  console.log(arr2); // [3]
</script>

2.7.6、fill方法

使用自己想要的参数替换原数组内容,但是会改变原来的数组

可以传多个参数

1个参数:默认从数组第一位开始替换

2个参数:(替换的值,替换索引位置)

3个参数:(替换的值,替换索引开始位置,替换索引结束位置【不包括】)

 <script>
      let arr1 = new Array(3).fill("hello");
      let arr2 = ["猪八戒", "孙悟空", "唐僧"].fill("kerwin", 1, 2);
      console.log(arr1); // ['hello', 'hello', 'hello']
      console.log(arr2); //  ['猪八戒', 'kerwin', '唐僧']
    </script>

2.7.7、最新数组方法

JavaScript中31个数组方法,包括es5,es6新增方法(关注收藏,持续更新)_js数组方法以及es6新增的数组方法有哪些-CSDN博客

2.7.8、延展操作符(Spread operator)

扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。

  <script>
        // 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』
        //声明一个数组 ...
        const tfboys = ['易烊千玺','王源','王俊凯'];
        // => '易烊千玺','王源','王俊凯'


        // 声明一个函数
        function chunwan(){
            console.log(arguments);
        }


        chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯')
    </script>

扩展运算符的应用

<body>
    <div></div>
    <div></div>
    <div></div>
    <script>
        //1. 数组的合并 
        const kuaizi = ['王太利','肖央'];
        const fenghuang = ['曾毅','玲花'];
        // 数组的合并 第一种方式
        // const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
        // 数组的合并 第二种方式
        const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
        console.log(zuixuanxiaopingguo);


        //2. 数组的克隆(深拷贝)
        const sanzhihua = ['E','G','M'];
        const sanyecao = [...sanzhihua];//  ['E','G','M']
        console.log(sanyecao);


        //3. 将伪数组转为真正的数组
        const divs = document.querySelectorAll('div');
        const divArr = [...divs];
        console.log(divArr);// arguments    
    </script>
</body>

2.8、对象拓展

ES6 新增了一些 Object 对象的方法

2.8.1、简写对象

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

  <script>
        //ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
        //这样的书写更加简洁
        let name = 'bdqn';
        let change = function(){
            console.log('我们可以改变你!!');
        }

       const school = {
        // name:name,//属性名和变量值一样,可以简写一个
        name,
        change, //外部定义的函数
        fun: function () {
          console.log("我是复杂写法");
        },
        improve() {
          //直接在对象里定义函数
          console.log("我是简写");
        },
      };

        console.log(school);
    </script>

注意:对象简写形式简化了代码,所以以后用简写就对了

2.8.2、 Object.is

比较两个值是否严格相等,与『===』行为基本一致 (+0 与 NaN)

console.log(Object.is(120, 120));// === 
console.log(Object.is(NaN, NaN));// true
console.log(NaN === NaN);// false

2.8.3、Object.assign

对象的合并,将原对象的所有可枚举属性,复制到目标对象,后面的对象会覆盖前面的对象一样的属性

Object.assign(target, object1,object2)的第一个参数是目标对象,后面可以跟一个或多个源对象作为参数。

target:参数合并后存放的对象

object1:参数1

object2:参数2

  const obj1 = {
        name: "tom",
        age: 18,
      };
      const obj2 = {
        name: "bob",
        age: 28,
        sex: "男",
      };
      console.log(Object.assign(obj1, obj2));
      //{name: 'bob', age: 28, sex: '男'}

2.8.3 、setPrototypeOf、 getPrototypeOf
可以直接设置对象的原型,不建议使用
setPrototypeOf(school, cities)
参数1:给谁设置原型对象 school
参数2:设置哪个原型对象 cities

 const school = {
        name: "bdqn",
      };
      const cities = {
        xiaoqu: ["北京", "上海", "深圳"],
      };
      // 设置原型
      Object.setPrototypeOf(school, cities);
      // 获取原型
      Object.getPrototypeOf(school);
      console.log(school);

2.9、函数扩展

2.9.1、箭头函数

ES6 允许使用「箭头」(=>)定义函数。

箭头函数只能简写函数表达式,不能简写声明式函数

function fn() {} // 不能简写
const fun = function () {}; // 可以简写
const obj = {
  fn: function () {}, // 可以简写
};
2.9.1.1、 语法:() =>{}

():函数的形参

=>:必须的语法,指向代码块

{}:代码块

      <script> 
       // ES6 允许使用「箭头」(=>)定义函数。
      //声明一个函数
      /* let fn = function(){
         } */
         
     /*  let fn = (a,b) => {
          return a + b;
      } */
      //调用函数
      // let result = fn(1, 2);
      // console.log(result);
       </script> 
2.9.1.2、箭头函数的特性
  1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值,没有自己的this
  2. 不能作为构造实例化对象 会报错
  3. 不能使用 arguments 变量
  4. 箭头函数的简写

1) 省略小括号, 当形参有且只有一个的时候

2) 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果

 <script>    
      //箭头函数的特性
      //1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值,没有自己的this
      function getName() {
        console.log(this.name);
      }
      let getName2 = () => {
        console.log(this.name);
      };


      //设置 window 对象的 name 属性
      window.name = "北大青鸟";
      const school = {
        name: "bdqn",
      };


      //直接调用,this指向window
      // getName();
      // getName2();


      //call 方法调用
      // getName.call(school);  //指向school
      // getName2.call(school);  //指向window


      //2. 不能作为构造实例化对象  会报错
   /*    let Person = (name, age) => {
          this.name = name;
          this.age = age;
      }
      let me = new Person('xiao',30);
      console.log(me); */


      //3. 不能使用 arguments 变量
   /*    let fn = () => {
          console.log(arguments);
      }
      fn(1,2,3); */


      //4. 箭头函数的简写
      //1) 省略小括号, 当形参有且只有一个的时候
    /*   let add = n => {
          return n + n;
      }
      console.log(add(9)); */
      //2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
      // 而且语句的执行结果就是函数的返回值
     /*  let pow = (n) => n * n;
      console.log(pow(8)); */
    </script>

注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适

2.9.1.3、补充this指向问题汇总

1、作为普通函数被调用时--this指向全局对象window

2、对象方法里的this 当函数作为对象方法被调用时this指向该对象

3、构造函数里面的this,构造函数里的this指向 new创建的实例化对象(没有return的情况下)

如果构造函数内出现了return并且是一个object对象那么最终的运算结果返回这个对象,只要构造函数不返回数据或者返回基本数据类型 this仍然指向实例

4、call&& apply&&bind

在function的原型上有三个方法 call apply bind,所有函数都是Function的实例,所以所有的函数都可以调用这三个方法,而这三个方法都是用来改变this指向的

定义:call(thisObj,Object) 调用一个对象的一个方法,以另一个对象替换当前对象。

说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

5、事件回调中的this指向事件源

6、定时器中的this指向window

7、箭头函数里面没有自己的this 他只会从自己的作用域链上一层继承this

···

2.9.2、参数默认值

2.9.2.1、 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
  function add(a, b, c = 10) {
        return a + b + c;
      }
      //let res1 = add(1, 2, 3);//6
      let res2 = add(1,1);//12
      cons
ole.log(res2);

2.9.2.2、 与解构赋值结合


      function connect({ name, age, sex, price = "3000" }) {
        console.log(name);
        console.log(age);
        console.log(sex);
        console.log(price);
      }
      connect({
        name: "章三",
        age: 20,
        sex: "男",
        // price: 4000,
      });

2.9.2.3、这个默认值的方式箭头函数也可以使用

 const fn = (a = 10) => {
    console.log(a);
  };
  fn(); // 不传递参数的时候,函数内部的 a 就是 10
  fn(20); // 传递了参数 20 的时候,函数内部的 a 就是 20

注意: 箭头函数如果你需要使用默认值的话,那么一个参数的时候也需要写 ()