zoukankan      html  css  js  c++  java
  • ES6新特性

    ES6 主要是为了解决 ES5 的先天不足,在原先ES5的基础上新增了许多内容,本篇文章将列举出ES6中新增的10大特性。

      一、 let 和 const

      与var不同,let和const都是用于命名局部变量,都是块级作用域。具体可参考阮一峰老师的文章:http://es6.ruanyifeng.com/#docs/let

      这三者的用法区别如下:

    复制代码
     1 var val = "全局变量";
     2 
     3 {
     4   let val = "局部变量";
     5   console.log(val);     // 局部变量
     6 }
     7 
     8 console.log(val);       // 全局变量
     9 
    10 const val = "常量";
    11 val = "123";            // Uncaught TypeError: Assignment to constant variable.
    复制代码

      前面说const声明的是常量,一旦声明就不可再进行修改。但是当用const声明对象时,又会出现一种新情况,举个栗子:

    1 const person = {name: "Peter", age: "22"};
    2 person.age = 23;                      // 不会报错,person的age变量会被改成23
    3 person = {name: "Lily", age: "18"};   // 报错

      如果用const声明一个对象,对象所包含的值是可以被修改的。换一句话来说,只要对象指向的地址不被修改,就是允许的。

      关于let和const有几个小tips:

    1. let 关键词声明的变量不具备变量提升(变量提升:https://blog.csdn.net/qq_42606051/article/details/82016733)特性;
    2. let 和 const 声明只在最靠近的一个块中有效;
    3. 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING;
    4. const 在声明时必须被赋值,否则会报错。
    5. 使用let会出现暂时性死区,原因是let所声明的变量会锁在它所在的作用域里,不允许访问,就是说,它也会先扫描一遍,把let声明的变量保存起来,但是不允许使用,这时候你访问a,由于此作用域中有a,就不用访问外面的a了,但是你不能在它声明之前访问它。
    var a = 1;
    if(ture){
        console.log(a);  //ReferrenceError
        let a = 1;
    }

      6. 使用let和const时不能重复声明。

      7. 使用var声明的全局变量或者未声明的变量都会归属到window对象下,但是使用let和const声明全局变量时不会发生这种情况。

      拓展: 如何使用ES5标准来实现let,换言之就是如何实现块级作用域。(答:使用匿名函数)

      二、 模版字符串

      在过去我们想要将字符串和变量拼接起来,只能通过运算符“+”来实现,若内容过多还要用“”来表示换行,如:

    var person = {name: "Peter", age: 22, career: "student"};
    $(".introduction").html("Hello, my name is " + person.name + ", and my 
    career is " + person.career + ".");

      而在ES6中,可以将反引号(``)将内容括起来,在反引号中,可以使用${}来写入需要引用到的变量。如:

    var person = {name: "Peter", age: 22, career: "student"};
    $(".introduction").html(`Hello, my name is ${person.name}, and my career is ${person.career}.`);

      所以在ES6中,我们可以更方便地将字符串和变量连接起来。

      三、 箭头函数

      在ES6中引入了一种新的函数表达方式,它是函数的一种简写方法,有以下三个特点:

    1. 不需要用关键字function来定义函数;
    2. 一般情况下可以省略return;
    3. 在箭头函数内部,this并不会跟其他函数一样指向调用它的对象,而是继承上下文的this指向的对象。

      在上面的三点中,第三点尤为重要,初学者在使用时经常会忽略这一点。

      下面举几个箭头函数的使用方法:

    复制代码
     1 /*
     2 ** 对应上面所说的第3点
     3 ** 在箭头函数中,this的指向与它的上下文有关
     4 ** 在本例中,箭头函数fun的上下文是window,所以this指向的也是window
     5 */
     6 window.val = 12;
     7 let fun = () => {
     8     let val = 13;
     9     console.log(val);               // 13
    10     console.log(this.val);          // 12
    11     console.log(this == window);    // true
    12 }
    13 fun();
    14 
    15 /*
    16 ** 普通函数使用
    17 */
    18 
    19 let add = function(a, b){
    20     return a + b;
    21 }
    22 
    23 /*
    24 ** 箭头函数使用
    25 */
    26 let add1 = (a, b) => a + b;
    27 
    28 // 当参数只有一个时,可以将括号省略
    29 let sqrt = a => a*a;
    复制代码

      四、 函数可以设置默认参数值

      在这之前,我们想要在函数中设置默认值,只能通过以下方法进行设置:

    复制代码
    1 function printText(text){
    2     var text = text || "hello world!";
    3     console.log(text);
    4 }
    5 
    6 printText("My name is Peter");          // "My name is Peter";
    7 printText();                            // "hello world!";    
    复制代码

      但是在ES6中定义了一种新方法,开发者可以直接使用如下方法设置函数的参数默认值:

    复制代码
    1 function printText(text = "hello world!") {
    2     console.log(text);
    3 }
    4 
    5 printText("My name is Peter");  // "My name is Peter";
    6 printText();                    // "hello world!";
    复制代码

      五、 Spread / Rest 操作符

      Rest运算符用于获取函数调用时传入的参数。举个栗子:

    复制代码
    1 let fun = function(...args) {
    2     console.log(args);
    3 }
    4 
    5 const list = ["Peter", "Lily", "Tom"];
    6 fun(list);    // ["Peter", "Lily", "Tom"]
    复制代码

      Spread运算符用于数组的构造,析构,以及在函数调用时使用数组填充参数列表。再举个栗子:  

    复制代码
     1 /*
     2 ** 使用Spread运算符合并数组
     3 */
     4 const list1 = ["Peter", "Tom"];
     5 const list2 = ["Lily", "Mary"];
     6 const list = [...list1, ...list2];
     7 console.log(list); // ["Peter", "Tom", "Lily", "Mary"]]
     8 
     9 /*
    10 ** 使用Spread运算符析构数组
    11 */
    12 const [person, ...list3] = list;
    13 console.log(person);        // Peter
    14 console.log(list3);         // ["Tom", "Lily", "Mary"]
    复制代码

      更多关于Rest和Spread运算法的使用方法,可以参考一下阮一峰老师的文章:http://es6.ruanyifeng.com/#docs/array

      六、 二进制和八进制的字面量

      ES6支持二进制和八进制的字面量,通过在数字前面增加0o或者0O可以将数字转换为八进制。

    1 let val1 = 0o10;
    2 console.log(val1);      // 8,八进制的0o10对应十进制的8
    3 
    4 let val2 = 0b10;
    5 console.log(val2);      // 2,二进制的0b10对应十进制的2

      七、 对象和数组解构

      ES6可以将对象中的属性或者数组中的元素进行解构,操作方式与前面所提到的Rest和Spread操作符类似,看一下下面这个栗子:

    复制代码
    1 let person = {
    2     name: "Peter",
    3     age: 22,
    4     career: "student"
    5 }
    6 
    7 const {name, age, career } = person;
    8 console.log(`Hello, my name is ${name}, and my career is ${career}.`);        
    9 //Hello, my name is Peter, and my career is student.
    复制代码

      八、 允许在对象中使用super方法

      super方法应该都不陌生,在java中用来代表调用父类的构造函数。由于js不是面向对象语言,所以也没有继承这以说法。但是在ES6中,可以通过调用setPrototypeOf()方法来设置一个对象的prototype对象,与面向对象语言中的继承有相似之处,所以也可以理解成这是js中用来实现继承的方法。(这段话纯属个人理解,如果有误请指出。)所以,在ES6中,通过使用super可以调用某个对象的prototype对象的方法或获取参数。栗子如下:

    复制代码
     1 var father = {
     2     text: "Hello from the Father.",
     3     foo() {
     4         console.log("Hello from the Father.");
     5     }
     6 }
     7 
     8 var son = {
     9     foo() {
    10         super.foo();
    11         console.log(super.text);
    12         console.log("Hello from the Son.");
    13     }
    14 }
    15 
    16 /*
    17 ** 将father设置成son的prototpe
    18 ** 当在son中调用super时,可以直接调用到它的prototype对象,即father的方法和变量
    19 */
    20 Object.setPrototypeOf(son, father);
    21 son.foo(); 
    22 // Hello from the Fater.
    23 // Hello from the Fater.
    24 // Hello from the Son.
    复制代码

      九、 迭代器iterator、for...of和for...in

      首先你要理解什么是iterator,可参考http://es6.ruanyifeng.com/#docs/iterator#for---of-%E5%BE%AA%E7%8E%AF

      了解完iterator之后,便可以来深入了解一下for...of和for...in这两种方法了。用一句话来总结就是,无论是for…in还是for…of语句,都是用来迭代数据,它们之间的最主要的区别在于它们的迭代方式不同。

    • for…in 语句以原始插入顺序迭代对象的可枚举属性,简单理解就是for...in是用来循环遍历属性,遍历出的是自身和原型上的可枚举非symbol属性,但是遍历不一定按照顺序(tips:for...in在ES5中就已经出现了)
    • for…of 语句遍历可迭代对象定义要迭代的数据,也就是说,for...of只可以循环可迭代对象的可迭代属性,不可迭代属性在循环中被忽略了。(tips:for...of是ES6才提出来的)

      关于for...in和for...of的用法,可以看以下栗子:

    复制代码
     1 Object.prototype.objCustom = function() {};
     2 Array.prototype.arrCustom = function() {};
     3 
     4 let iterable = [3, 5, 7];
     5 iterable.foo = 'hello';
     6 //for in 会继承
     7 for (let i in iterable) {
     8     console.log(i); // 依次打印 0, 1, 2, "foo", "arrCustom", "objCustom"
     9 }
    10 
    11 for (let i in iterable) {
    12     if (iterable.hasOwnProperty(i)) {
    13         console.log(i); // 依次打印 0, 1, 2, "foo"
    14     }
    15 }
    16 
    17 // for of
    18 for (let i of iterable) {
    19     console.log(i); // 依次打印 3, 5, 7
    20 }
    复制代码

      对于这一块的应用,我自己也不是很理解。例子是参考别的博主写的。在实际开发过程中,似乎不太建议使用for...in,因为不同环境下对for...in的遍历算法的实现不一样,而且在for...in的过程中对这个对象属性的添加,修改,删除操作不能被保证, MDN不建议用这个来遍历对象。

      十、 class

      ES6 提供了更接近传统语言的写法,引入了 class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

      基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。在ES5中,我们更多是使用原型链来实现继承。

  • 相关阅读:
    Spring Cloud Ribbon实现客户端负载均衡
    Spring Boot 初步小结
    日志配置
    外部属性文件的使用
    运行jar
    类型安全的配置文件
    java动态代理中的invoke方法是如何被自动调用的(转)
    数据库为什么要用B+树结构--MySQL索引结构的实现(转)
    Java transient关键字使用小记(转)
    面试题思考:Java 8 / Java 7 为我们提供了什么新功能
  • 原文地址:https://www.cnblogs.com/keyng/p/12917289.html
Copyright © 2011-2022 走看看