zoukankan      html  css  js  c++  java
  • ES6 笔记

    箭头函数

    箭头函数里的this会引用 定义 箭头函数时,外部作用域 的 this 。箭头函数只是 引用 外部作用域的 this ,本身不存在 this。同时因为没有 this ,所以 无法用new生成实例,例:

    var name = 'window';
    function test(){
        //实际等同于这样
        //var _this = this;
        this.name = 1;
        this.method = ()=>{
            //console.log(_this.name);
            console.log(this.name);
        }
    }
    var b = new test();
    setTimeout(b.method, 500);  //1

    这个例子中,箭头函数的 this 在定义 method 方法时,引用了test的上下文,而不是执行时引用 this ,所以 setTimeout 方法执行的 method 方法时,this 还是指向了 test 。

      

    function test(){
        this.method = ()=>{
            function foo(){
                console.log(this);                      //Window
                console.log(this instanceof Window);    //true
            }
            foo();
        }
    }
    var b = new test();
    setTimeout(b.method, 500);                        //1

    这个例子中,这个例子中 this 之所以没有引用箭头函数外层,是因为 foo 函数里的 this 作用域此时属于Window,也就不用往 foo 函数外层查找this了,所以 this 指向了 Window。

    参数默认值

    ES6之前,参数不能给定默认值,只能通过下面的形式给参数设定默认值。

    function a(x){  
      x? x: x = 1; 
      //或者
      if(typeof x === 'undefined'){
          x = 1;
      }
    }
    

    ES6只要下面的形式就能给参数设定默认值

    function a(x = 1){
      console.log(x);    //1
    }
    

    如果给参数赋予一个默认的函数,就会出现特殊情况。例1:

    var x = 0;
    function a(x, y = ()=> {x = 1; console.log(x); /* 1 */ }){
      var x = 10;
      y();
      console.log(x);   //10
    }
    a();
    console.log(x);     //0
    

    参数y里的代码执行之后,函数 y 里的 x 确实已经被赋值了 1,但是函数体内的 x 值还是10,同时全局变量 x 也还是0。

    假如把例1里的函数 y 从默认值里放到函数 a 内部,则会变成这样。

    var x = 0;
    function a(x, y){
      if(typeof y === 'undefined'){    
        y = ()=> {
         x = 1;
        }
      }
      var x = 10;
      y();
      console.log(x);   //1
    }
    a();
    console.log(x);     //0
    

    结果是 x = 1 把前面的 x = 10 给覆盖了,当然全局变量依然没有变化。

    这两个例子看似一样,但实际上,ES6的机制是:参数默认值是一个函数时,会生成一个参数级作用域。导致这两个例子本质上有所差别,同时函数体内部是函数级作用域,函数外部是外部作用域。三个作用域互相独立,又由作用域链引用。从内往外的顺序是:

    函数级作用域 => 参数级作用域 => 外部作用域 

    函数a => 参数 x, y 所在的括号部分 => 全局变量        以例1为例)

    注意下面这种情况:

    function a(x, y = ()=> {var b = 10; console.log(b)}){
      y();              //10
      console.log(b);   //报错 b is not defined
    }
    a();

    参数级作用域只是参数声明的括号部分,而参数 y 内部的作用域对参数级作用域不可见。

    也就是变量 b 被函数 y 的作用域隔离开了,不属于参数级作用域,也就无法给函数 a 所捕获。

    而例1 中在声明函数的时候,会同时(也许是执行的时候,暂不清楚)声明变量 x 与 函数 y。由于已经声明了变量 x,同时 x 和 y 同属块级作用域。以及作用域链的存在,外部作用域无法查找内部作用域里的变量,只能往外查找变量。按照 函数级作用域 => 块级作用域 => 外部作用域 的顺序,参数部分的块级作用域无法调用函数内部的变量。

    所以例子中的 x 实际上被定义了3次,每一个作用域各1次,也就导致了每个作用域中的 x 的值互相独立赋值。

    所以实际上例1编译成ES5的代码是下面这样的:

    var x = 0;
    function a(x, y){
      y = function() {
        x = 1;            //参数里已经声明了变量x,所以不是全局里的x
        console.log(x);   //1
      }
      return function(){  
        var x = 10;       
        y();
        console.log(x);   //10
      }()
    }
    a();
    console.log(x);       //0
    

    ES6里实现则是:

    var x = 0;
    function a(x, y){
      y = function() {
        x = 1;            //参数里已经声明了变量x,所以不是全局里的x
        console.log(x);   //1
      }
      {  
        let x = 10;       //用let声明一个块级变量
        y();
        console.log(x);   //10
      }
    }
    a();
    console.log(x);       //0
    

    假设把例1改成下面这样:

    var x = 0;
    function a(x, y = ()=> {x = 1; console.log(x); /* 1 */ }){
      x = 10;           //去掉var
      y();
      console.log(x);   //1
    }
    a();
    console.log(x);     //0
    

    在去掉了函数级作用域里的 var 关键字后,变量 x 和 参数 x 都处于同一作用域(chrome控制台显示为local,也就是函数级作用域,可能是为了兼容ES5)。此时 y 里的 x = 1 就覆盖了 x = 10。

    Generator 函数与异步

    Generator函数的yield没有本身不会有返回值,除非在next方法里带上参数,这个参数会变成上一个yield语句的返回值。

    例:

    function* f() {
        for(var i = 0; true; i++) {
            var reset = yield i;
            console.log(reset, i);
            if(reset) { i = -1; }
        }
    }
    
    var g = f();
    
    g.next() 
    //undefined, 0
    // { value: 0, done: false }
    
    g.next() 
    //undefined, 1
    // { value: 1, done: false }
    
    g.next(true)
    //true, 0
    // { value: 0, done: false }
    

    如果内部有return一个值, 那么无论后面是否还有yield,直接返回对象。对象中的value属性就是那个值,done值为true,也即完成。

  • 相关阅读:
    java高并发程序设计模式-并发级别:阻塞、无障碍、无锁、无等待【转载】
    Java创建线程的三种主要方式
    Java乐观锁实现之CAS操作
    Java解释执行和编译执行
    手把手教你使用百度大脑地址识别API
    详解百度大脑EdgeBoard出色的视频处理技术
    一步到位!!百度大脑语音合成快速搞定会员到访提醒功能
    一文带你了解百度大脑云狐语音全攻略(附代码)
    AI小程序之语音听写来了,十分钟掌握百度大脑语音听写全攻略!!
    快速上手百度大脑EasyDL专业版·物体检测模型(附代码)
  • 原文地址:https://www.cnblogs.com/NKnife/p/6202101.html
Copyright © 2011-2022 走看看