• ES5和ES6那些你必须知道的事儿(三)


    ES5和ES6那些你必须知道的事儿

    ES6新增的东西

    一、块级作用域:关键字let,常量const

      let与var的区别:

        a、不会进行变量声明提升

        b、变量不允许被重复定义

        c、变量不允许被删除

        d、在for循环中可以保留i的值

        e、循环的变量只能在当前块级作用域中使用

      const和var的区别:

        a、常用于声明常量时或声明不可被修改的变量的时候

        b、const的值不允许被修改

        c、不会进行变量声明提升

        d、常量不允许被删除    

    二、对象字面量属性赋值简写

    var name = “我是name”;
    var age = 18var obj = {
        name,
        age      
    }
    
    //此处的对象的key值与value值是一样的,所以简写
    
    //不简写的话就是
    
    var obj = {
        name:name,    //即name:“我是name”
        age:age     //即age:18
    }

    三、解构赋值

    let singer = { first: "Bob", last: "Dylan" };
    let { first: f, last: l } = singer; // 相当于 f = "Bob", l = "Dylan"
    let [all, year, month, day] =  /^(dddd)-(dd)-(dd)$/.exec("2015-10-25");
    let [x, y] = [1, 2, 3]; // x = 1, y = 2

    四、展开运算符... 

    var arr=[1,2,3,4];
    
    console.log(...arr)
    
    //打印出来不是一个数组,
    //而是将数组里的内容分开打印
    //1 2 3 4

    五、箭头函数

    //正常函数的写法:
    
    function a(){
        //内容  
    }
    
    //如果改成箭头函数
    
    a()=>{
       //内容
    }
    //箭头函数的简写
    
    x => x * x
    
    //上面的代码相当于下面的代码
    
    function (x) {
        return x * x;
    }
    
    //如果参数不是一个,就需要用括号()括起来:
    
    // 两个参数:
    (x, y) => x * x + y * y
    
    // 无参数:
    () => 3.14
    
    // 可变参数:
    (x, y, ...rest) => {
        var i, sum = x + y;
        for (i=0; i<rest.length; i++) {
            sum += rest[i];
        }
        return sum;
    }
    
    
    //如果要返回一个对象,就要注意,写成下面这样
    
    x => ({ foo: x })

    要注意箭头函数的this

    普通函数下的this:

    • 在普通函数中的this总是代表它的直接调用者,在默认情况下,this指的是window,
    • 在严格模式下,没有直接调用者的函数中的this是 undefined使用
    • call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象

    箭头函数中的this:

    •  箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),
    •  而不是执行时的对象, 定义它的时候,可能环境是window,也有可能是其他的。

    看下面这段代码:

    function a() { 
       console.log(this);  //window
     }  
     a(); 

    因为a是一个全局函数,也就是挂载在window对象下的,所以a(),等价于window.a();

    var obj = {  
       say: function () {  
         setTimeout(function () {  
           console.log(this);   //window   
         });  
       }  
     }   
     obj.say(); 

    定时器中的函数,由于没有默认的宿主对象,所以this指向window

    var obj = {  
       func: function() {},  
       say: function () {  
         console.log(this);//obj,此时的this是obj对象    
         setTimeout(function () {   
           console.log(this);  //window
           that.func();  
         });   
       }  
     }  
     obj.say(); 

    此时say的宿主环境是obj,所以say里面的this是obj,定时器中的函数, 由于没有默认的宿主对象,所以默认this指向window

    箭头函数中的this:

    var obj = {  
       say: function () {  
         setTimeout(() => {  
           console.log(this);// obj    
         });  
       }  
     }  
     obj.say(); 

    此时的 this继承自obj, 指的是定义它的对象obj, 而不是 window!

     

    var obj = {  
    say: function () {  
      var f1 = () => {  
        console.log(this); // obj  
        setTimeout(() => {  
          console.log(this); // obj  
        })  
      }  
      f1();  
      }  
    }   
    obj.say()
    因为f1定义时所处的函数 中的 this是指的 obj, setTimeout中的箭头函数this继承自f1,所以不管有多层嵌套,都是 obj


    var obj = {  
    say: function () {  
      var f1 = function () {  
        console.log(this); // window, f1调用时,没有宿主对象,默认是window  
        setTimeout(() => {  
          console.log(this); // window  
        })  
      };  
      f1();  
      }  
    }  
    obj.say() 

    结果: 都是 window,因为 箭头函数在定义的时候它所处的环境相当于是window, 所以在箭头函数内部的this函数window

    换个理解方式:因为箭头函数没有this,当需要判断当前this是什么的时候,把箭头函数去掉,看剩下的代码此处的this指向哪里即可。

            var a=10;
            var obj={
                a:50,
                getA(){
                    return this.a
                },
                b:()=>{
                    return this.a
                }
            }
            console.log(obj.getA())//50
            console.log(obj.b())//10
            console.log(obj.getA.call())//10

    六、字符串模版` `

    var name = "Bob", time = "today";
    `Hello ${name}, how are you ${time}?`
    // return "Hello Bob, how are you today?"

    七、迭代器

    八、生成器

    九、class

    Class,有constructor、extends、super,但本质上是语法糖(对语言的功能并没有影响,但是更方便程序员使用)。

    class Artist {
        constructor(name) {
            this.name = name;
        }
    
        perform() {
            return this.name + " performs ";
        }
    }
    
    class Singer extends Artist {
    
        constructor(name, song) {
            super.constructor(name);
            this.song = song;
        }
    
        perform() {
            return super.perform() + "[" + this.song + "]";
        }
    }
    
    let james = new Singer("Etta James", "At last");
    james instanceof Artist; // true
    james instanceof Singer; // true
    
    james.perform(); // "Etta James performs [At last]"

    十一、Map() Set()

    // Sets
    var s = new Set();
    s.add("hello").add("goodbye").add("hello");
    s.size === 2;
    s.has("hello") === true;
    
    // Maps
    var m = new Map();
    m.set("hello", 42);
    m.set(s, 34);
    m.get(s) == 34;

    十二、一些新的API

    一些新的API
    
    Number.EPSILON
    Number.isInteger(Infinity) // false
    Number.isNaN("NaN") // false
    
    Math.acosh(3) // 1.762747174039086
    Math.hypot(3, 4) // 5
    Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2
    
    "abcde".includes("cd") // true
    "abc".repeat(3) // "abcabcabc"
    
    Array.from(document.querySelectorAll('*')) // Returns a real Array
    Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
    
    [0, 0, 0].fill(7, 1) // [0,7,7]
    [1, 2, 3].find(x => x == 3) // 3
    [1, 2, 3].findIndex(x => x == 2) // 1
    [1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]
    ["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
    ["a", "b", "c"].keys() // iterator 0, 1, 2
    ["a", "b", "c"].values() // iterator "a", "b", "c"
    
    Object.assign(Point, { origin: new Point(0,0) })

    十三、proxy

    Proxy 让我们能够以简洁易懂的方式控制外部对对象的访问。其功能非常类似于设计模式中的代理模式。

    使用 Proxy 的好处是:对象只需关注于核心逻辑,一些非核心的逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)可以让 Proxy 来做。从而达到关注点分离,降级对象复杂度的目的。

    var p = new Proxy(target, handler);

    其中,target 为被代理对象。handler 是一个对象,其声明了代理 target 的一些操作。p 是代理后的对象。

    当外界每次对 p 进行操作时,就会执行 handler 对象上的一些方法。handler 能代理的一些常用的方法如下:

    • get:读取
    • set:修改
    • has:判断对象是否有该属性
    • construct:构造函数
    • ...
    var target = {
       name: 'obj'
     };
     var logHandler = {
       get: function(target, key) {
         console.log(`${key} 被读取`);
         return target[key];
       },
       set: function(target, key, value) {
         console.log(`${key} 被设置为 ${value}`);
         target[key] = value;
       }
     }
     var targetWithLog = new Proxy(target, logHandler);
     targetWithLog.name; // 控制台输出:name 被读取,执行的get
     targetWithLog.name = 'others'; // 控制台输出:name 被设置为 others,执行了set
    console.log(target.name); // 控制台输出: others
    • targetWithLog 读取属性的值时,实际上执行的是 logHandler.get :在控制台输出信息,并且读取被代理对象 target 的属性。
    • 在 targetWithLog 设置属性值时,实际上执行的是 logHandler.set :在控制台输出信息,并且设置被代理对象 target 的属性的值。
    实现私有变量
     
    代理中把以 _ 开头的变量都认为是私有的。
    var api = {
      _secret: 'xxxx',
      _otherSec: 'bbb',
      ver: 'v0.0.1'
    };
    
    api = new Proxy(api, {
      get: function(target, key) {
        // 以 _ 下划线开头的都认为是 私有的
        if (key.startsWith('_')) {
          console.log('私有变量不能被访问');
          return false;
        }
        return target[key];
      },
      set: function(target, key, value) {
        if (key.startsWith('_')) {
          console.log('私有变量不能被修改');
          return false;
        }
        target[key] = value;
      },
      has: function(target, key) {
        return key.startsWith('_') ? false : (key in target);
      }
    });
    
    api._secret; // 私有变量不能被访问
    console.log(api.ver); // v0.0.1
    api._otherSec = 3; // 私有变量不能被修改
    console.log('_secret' in api); //false
    console.log('ver' in api); //true

    使用代理(Proxy)监听对象的操作,然后可以做一些相应事情。

    可监听的操作: get、set、has、deleteProperty、apply、construct、getOwnPropertyDescriptor、defineProperty、getPrototypeOf、setPrototypeOf、enumerate、ownKeys、preventExtensions、isExtensible。

    十四、Symbol

    Symbol是一种基本类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的。

    var key = Symbol("key");
    var key2 = Symbol("key");
    key == key2  //false

    十五、promise

    Promises是处理异步操作的对象,使用了 Promise 对象之后可以用一种链式调用的方式来组织代码,让代码更加直观

    function fakeAjax(url) {
      return new Promise(function (resolve, reject) {
        // setTimeouts are for effect, typically we would handle XHR
        if (!url) {
          return setTimeout(reject, 1000);
        }
        return setTimeout(resolve, 1000);
      });
    }
    
    // no url, promise rejected
    fakeAjax().then(function () {
      console.log('success');
    },function () {
      console.log('fail');
    });

    异步操作的同步代码

      

     

  • 相关阅读:
    错误1053:服务没有及时响应启动或控制请求
    错误号码2003 Can't connect to MySQL server 'localhost' (0)
    分析slow-log 每小时慢sql情况
    用spring annotation声明的bean,当打包在jar中时,无法被扫描到
    mysql 锁查看
    linux 使用expect
    tomcat启动报错:java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener
    Spring LDAP authenticate method with Pooling
    一步步教你使用Proguard混淆Java源代码
    JAVA获取CLASSPATH路径
  • 原文地址:https://www.cnblogs.com/yangyangxxb/p/10128947.html
Copyright © 2020-2023  润新知