ES6学习笔记

ES6学习笔记

一、let 和const关键字

1.2 .0 let关键字的使用

  1. let命令 基本语法
    let a =10;
    {
    let b = 100;//b只在当前代码块中有效
    }
    
  2. 不存在变量的提升
    console.log(a)// a is not function 
    let a=19;
    
    console.log(b);//undefined
    var b =10;
    
    
    
    • a在未声明之前就是用了,var存在全局作用于,所以b只是没有被赋值,结果为undefined;但是let声明的变量,提前使用就会报错
  3. 暂时性死区( TDZ)
    var tmp = 123;
    
    if (true) {
        //TDZ开始
      tmp = 'abc'; // ReferenceError
      let tmp;//TDZ结束
    }
    
    • 虽然tmp在外层使用了var声明,但是if语句里,tmp使用了let声明绑定了tmp区域,但是tmp=“abc”,还未在let声明tmp是就进行赋值操作,所以报错了。
    function bar(x = y, y = 2) {
      return [x, y];
    }
    
    bar(); // 报错
    
    • 调用bar函数之所以报错(某些实现可能不报错),是因为参数x默认值等于另一个参数y,而此时y还没有声明,属于“死区”。如果y的默认值是x,就不会报错,因为此时x已经声明了
  4. 不允许重复声明
    // 报错
    function func() {
      let a = 10;
      var a = 1;
    }
    
    // 报错
    function func() {
      let a = 10;
      let a = 1;
    }
    

1.2.1 块级作用域

  1. ES5存在全局作用域和函数作用域
    var tmp = new Date();
    
    function f() {
      console.log(tmp);
      if (false) {
        var tmp = 'hello world';
      }
    }
    
    f(); // undefined
    
    • 内层变量覆盖外层变量)外部全局tmp变量,但是又因为函数f()中,有声明了tmp,导致函数内部tmp覆盖了外部temp变量,至于输出undefined,是因为if 判断false不走输出语句,但是前面输出语句有tmp,声明了没赋值,所以值就是undefined啦
    var s = 'hello';
    
    for (var i = 0; i < s.length; i++) {
      console.log(s[i]);
    }
    
    console.log(i); // 5
    
    • 计数的循环变量泄露为全局变量)循环结束了,但是i的值还存在。
  2. ES6块级作用域
    function f1() {
      let n = 5;
      if (true) {
        let n = 10;
      }
      console.log(n); // 5
    }
    
    • n =5 和 n= 10是处于两块不同作用于的变量,n之所以输出5是因为这个n是和 let n= 5同处于一块作用域
  3. ES6块级作用域和函数声明
    • 块级作用域中声明函数,类似于用let声明变量,只在当前块中有效
    function f() { console.log('I am outside!'); }
    
    (function () {
      if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
      }
    
      f();//ES5中 结果为:I am inside!
    }());
    
    • ES5实际执行过程(f函数会被提升到自调用函数作用域的最前面)
    // ES5 环境
    function f() { console.log('I am outside!'); }
    
    (function () {
        //注意和上面代码if function位置
      function f() { console.log('I am inside!'); }
      if (false) {
      }
      f();
    }());
    
    • ES6中执行(函数f存在if判断这个作用域中,所以仅限于此作用域有用,但是因为false所以,相当于没有声明函数)
    // 浏览器的 ES6 环境
    function f() { console.log('I am outside!'); }
    
    (function () {
      if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
      }
    
      f();
    }());
    // Uncaught TypeError: f is not a function
    
  4. 特别注意:(浏览器兼容性问题)—>为了减轻因此产生的不兼容问题;浏览器的实现可以不遵守上面的规定,有自己的行为。以下,只针对ES6有用
    • 允许在块级作用域声明函数

    • 函数声明类似于var ,即会将函数提升到作用域的头部

    • // 块级作用域内部的函数声明语句,建议不要使用
      {
        let a = 'secret';
        function f() {
          return a;
        }
      }
      
      // 块级作用域内部,优先使用函数表达式
      {
        let a = 'secret';
        let f = function () {
          return a;
        };
      }
      

1.2.3 const关键字的使用

  • 1.const基本语法(const声明一个只读的常量。一旦声明,常量的值就不能改变。)
    const PI = 3.1415;
    PI // 3.1415
    
    PI = 3;
    // TypeError: Assignment to constant variable.
    
  • 2、const本质(const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。)
  • 3、const定义的数组,可以对其进行读写操作,但是如果将新数组赋值给它就会报错,可以push但是不可以给数组赋值
    const a = [];
    a.push('Hello'); // 可执行
    a.length = 0;    // 可执行
    a = ['Dave'];    // 报错
    

1.2.4 顶层对象的属性

  • 在浏览器中指的是window对象,在node中指的是global;ES5中顶层对象和全局属性都是等价的
    window.a = 1;//顶层对象   
    a // 1
    
    a = 2;//全局对象
    window.a // 2
    
  • ES6改进
    var a = 1;
    // 如果在 Node 的 REPL 环境,可以写成 global.a
    // 或者采用通用方法,写成 this.a
    window.a // 1
    
    let b = 1;
    window.b // undefined
    
    • 上面代码中,全局变量avar命令声明,所以它是顶层对象的属性;全局变量blet命令声明,所以它不是顶层对象的属性,返回undefined

二、变量的解构赋值

2.1.0 解构的含义和使用

2.1.1 解构的数组案例

  • 从数组和对象中提取值,对变量进行赋值,这被称为解构

    //以前写法
    let a= 10;
    let b =20;
    
    //ES6写法  可以从数组中提取值,按照对应位置,对变量赋值
    let [a,b] =[10,20]
    
    
  • 解构本质:写法属于“模式匹配”;只要等号两边的模式相同,左边的变量就会被赋予对应的值(值)

    <script>
        // 解构
        let [a,b,c] = [1,2,4];
        console.log(a);
    
        let [e,,d]=[,3,6];
        console.log(e);//undefied  表示解构不成功
        console.log(d);//6
    
        let[head,hand,...all] = [1,2,3,4]
        console.log(head);
        console.log(hand);
        console.log(all);//前面解构完剩下的值
    
    	let [a,...b,c]= [1,2,3];//报错 ...b应该放在最后
    
    
        let[h,k,...para] = [1]
        console.log(h);//1
        console.log(k);//undefind
        console.log(para);//[]
    </script>
    
  • 不完全解构

    let [a,[b],c]=[3,[6,8],0];
    console.log(a);//3
    console.log(b);//6
    console.log(c);//0
    
  • 注意:如果等号右边的是不可遍历的对象,就会报错

    let [a,r,y]='哈哈哈';
    let [m,n,o]=false;
    
    //浏览器控制台报错  
    变量的解构和赋值.html:42 Uncaught TypeError: false is not iterable
    
  • 解构的默认值
    let [foo = true] = [];
    foo // true
    
    let [x, y = 'b'] = ['a']; // x='a', y='b'
    let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
    
  • ES6中使用严格运算符=== 只有严格等于undefined默认值才会生效,后面有值就用后面的。

    let [x = 1] = [undefined];
    x // 1
    
    let [x = 1] = [null];
    x // null
    
    • 上面代码,一个数组等于null,是不严格等于undefined的,所以默认值不生效

2.1.3 解构对象案例

let {foo,bar} ={foo:'小明',bar:99};
console.log(foo);//小明
console.log(bar);//99
  • 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。例如:

    let {bar}={brr:'1000'}console.log(bar);//undefined
    
  • 对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。

    // 例一
    let { log, sin, cos } = Math;
    sin(90)//0.89
    // 例二
    const { log } = console;
    log('hello') // hello
    
  • 对象的解构其实是下面代码的简写(找到右边对应,直接赋值输出)

    let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
    console.log(foo)//aaa
    console.log(bar)//bbb
    
    let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
    baz // "aaa"
    foo // error: foo is not defined
    let {a =10,b=1} = {a=1,b=3}
    //a =10;可以看成a:10
    a = 1
    b = 3
    

    上面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。(直接看值)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7IreVL96-1635732965572)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210928153614434.png)]

    上面代码有三次解构赋值,分别是对locstartline三个属性的解构赋值。注意,最后一次对line属性的解构赋值之中,只有line是变量,locstart都是模式,不是变量

  • 如果结构模式是嵌套对象。而且子对象的父属性不存在,则会报错

    let {foo :{bar}} = {bar:"bar"}//报错
    
  • 解构赋值可以取到被继承的对象
     // 解构赋值可以取到继承的值
        let obj1 = {};
        let obj2 = { foo: 'bar' };
        Object.setPrototypeOf(obj1, obj2);
        const { foo } = obj1;
        console.log(foo);//"bar"
    
    • obj1的原型对象是obj2,而obj1自身是没有foo属性的,因为继承,所以拿到来自obj2的属性和值
  • 对象解构的默认值,和数组解构一样,严格等于undefined时才生效

  • 注意点如果要将已经声明的变量解构赋值必须注意

    let x;
    {x} ={x:1}//报错
    
    let y;
    ({y} ={y:3})
    console.log(y);//3
    
    • 前面报错是因为,js引擎将{x}当成了代码块。

    • 不能使用圆括号的情况
      1. ​ 变量的声明,函数参数

        let [(a)] =[1];
        let{x:(c)}={};
        
        //函数参数
        function f([(a)]){return a}
        
      2. 可以使用圆括号的情况
        [(b)] = [3]; // 正确
        ({ p: (d) } = {}); // 正确
        
        • 都是赋值语句,第一行模式是取数组的第一个成员;第二行语句中,模式是p,而不是d
  • 字符串的解构
    let [a,b,c,d]='nice';
    a//n
    b//i
    c//c
    d//e
    
  • 数值和布尔值的解构赋值
    let {toString:s} =123;
    console.log(s);//12
    
  • 用途
    //1 变量的交换
    let x =20;
    let y =30;
    [x,y] =[y,x]
    
    //2 函数返回多个值,然后取值
    function example() {
      return [1, 2, 3];
    }
    let [a, b, c] = example();
    
    //3 函数定义参数(能够匹配任意位置对应的参数值)
    function fn({x,y,r}{....}
    fn({x:10,y:2,r:30})
    
    //4 提取JSON字符串
    let jsonData = {
      id: 42,
      status: "OK",
      data: [867, 5309]
    };
    
    let { id, status, data: number } = jsonData;
    
    console.log(id, status, number);
    // 42, "OK", [867, 5309]
    

三、字符串、数值、数组、对象的拓展

2.1.1字符串拓展

  • 字符串遍历for …of
    // for..of() 创建一个可迭代对象
        let str = 'codePonit';
        for (let item of str) {
          console.log(item);
        }//这个遍历器最大的优点是可以识别大于0xFFFF的码点
        let text = String.fromCodePoint(0x20BB7);
    
    for (let i = 0; i < text.length; i++) {
      console.log(text[i]);
    }
    // " "
    // " "
    
    for (let i of text) {
      console.log(i);
    }
    // "𠮷"
    
  • 模板字符串(可以放入js表达式、可以运算、引用对象属性,调用函数)
    es5
    var age = 10;
    innerText="年龄是"+age+"岁了";
    
    es6
    innerHTML=`年龄是${age}岁了`
    
    //也可以进行运算
    innerHTML=`年龄是${2*10}岁了`
    
    //调用函数
    function fn() {
      return "Hello World";
    }
    
    `foo ${fn()} bar`
    // foo Hello World bar
    
    
    
  • 模板标签(紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串,函数调用的一种新式,标签指的是函数,紧跟的是参数)
    alert`hello`;
    等同于
    alert(['hello']let a = 5;
    let b = 10;
    
    tag`Hello ${ a + b } world ${ a * b }`;
    // 等同于
    tag(['Hello ', ' world ', ''], 15, 50);
    
  • 模板标签的应用
    let message =
      SaferHTML`<p>${sender} has sent you a message.</p>`;
    
    function SaferHTML(templateData) {
      let s = templateData[0];
      for (let i = 1; i < arguments.length; i++) {
        let arg = String(arguments[i]);
    
        // Escape special characters in the substitution.
        s += arg.replace(/&/g, "&amp;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;");
    
        // Don't escape special characters in the template.
        s += templateData[i];
      }
      return s;
    }
    
    //应用
    let sender = '<script>alert("abc")</script>'; // 恶意代码
    let message = SaferHTML`<p>${sender} has sent you a message.</p>`;
    
    message
    // <p>&lt;script&gt;alert("abc")&lt;/script&gt; has sent you a message.</p>
    

2.1.2 字符串方法拓展

  • includes(parm1,param2)返回布尔值 判断是否包含指定的字符 参数1 :指定字符 参数2: 指定开始下标

  • startsWith(parm1,param2) 返回布尔值 判断是否以指定的字符开始

  • endsWith(parm1,param2) 返回布尔值 判断是否以指定的字符结尾

    let s = 'Hello World';
        console.log(s.includes('e'));//true
    

mplate.
s += templateData[i];
}
return s;
}

//应用
let sender = ‘’; // 恶意代码
let message = SaferHTML<p>${sender} has sent you a message.</p>;

message
//

<script>alert(“abc”)</script> has sent you a message.


### 2.1.2 字符串方法拓展

- includes(parm1,param2)返回布尔值 判断是否包含指定的字符 参数1 :指定字符  参数2: 指定开始下标

- startsWith(parm1,param2) 返回布尔值 判断是否以指定的字符开始

- endsWith(parm1,param2) 返回布尔值 判断是否以指定的字符结尾

```js
let s = 'Hello World';
    console.log(s.includes('e'));//true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值