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中,我们更多是使用原型链来实现继承。

  • 相关阅读:
    SPOJ 694 (后缀数组) Distinct Substrings
    POJ 2774 (后缀数组 最长公共字串) Long Long Message
    POJ 3693 (后缀数组) Maximum repetition substring
    POJ 3261 (后缀数组 二分) Milk Patterns
    UVa 1149 (贪心) Bin Packing
    UVa 12206 (字符串哈希) Stammering Aliens
    UVa 11210 (DFS) Chinese Mahjong
    UVa (BFS) The Monocycle
    UVa 11624 (BFS) Fire!
    HDU 3032 (Nim博弈变形) Nim or not Nim?
  • 原文地址:https://www.cnblogs.com/keyng/p/12917289.html
Copyright © 2011-2022 走看看