• ES6


    ES6简介

    ES6 是 ECMAScript 6.0 的简写,即 JavaScript 语言的下一代标准,已经在 2015年6月正式发布了,它的目标是让JS能够方便的开发企业级大型应用程序,因此,ES6的一些规范正在逐渐向Java、C# 等后端语言标准靠近。在 ES6 规范中,比较重大的变化有以下几个方面:

    • 新增 let、const 命令 来声明变量,和var 相比,let 声明的变量不存在变量提升问题,但没有改变JS弱类型的特点,依然可以接受任意类型变量的声明;const 声明的变量不允许在后续逻辑中改变,提高了JS语法的严谨性。
    • 新增解构赋值、rest 语法、箭头函数等,这些都是为了让代码看起来更简洁,而包装的语法糖。
    • 新增模块化机制,这是 JavaScript 走向规范比较重要的一步,让前端更方便的实现工程化。
    • 新增类和继承的概念,配合模块化,JavaScript 也可以实现高复用、高扩展的系统架构。
    • 新增模板字符串功能,高效简洁,结束拼接字符串的时代。
    • 新增 Promise 机制,解决异步回调多层嵌套的问题。

    ES诞生

    1997年 ECMAScript 1.0 诞生

    1999年12月 ECMAScript 3.0诞生,它 是一个巨大的成功,在业界得到了广泛的支持,它奠定了JS的基本语法,被其后版本完全继承。直到今天,我们一开始学习JS,其实就是在学3.0版的语法

    2000年的ECMAScript4.0是当下ES6的前身,但由于这个版本太过激烈,对ES3做了彻底升级,所以暂时被“和谐”了

    2009年12月,ECMAScript5.0版正式发布。ECMA专家组预计ECMAScript的第五个版本会在2013年中期到2018年作为主流的开发标准。2011年6月,ES5.1版发布,并且成为ISO国际标准

    2013年,ES6草案冻结,不再添加新的功能,新的功能将被放到ES7中;2015年6月,ES6正式通过,成为国际标准

    好的,介绍es6的诞生,我们简单来学几个es6的语法,仅仅的只是为了后面咱们vue的课程做课前准备。如果感兴趣的同学可以查看

    http://es6.ruanyifeng.com/

    ES6语法

    let

    let声明的变量只在let命令所在的代码块内有效

    ES6新增了let命令,用于声明变量。其用法类似var,但是声明的变量只在let命令所在的代码块内有效,var是全局有效。

    {
        let x = 10;
        var y = 20;
    }
    
    x  // ReferenceError: x is not defined
    y  // 20

    let不允许在相同的作用域内重复声明同一个变量。 

    function foo(){
        let x = 10;
        var x = 20;
    }  // 报错
    function foo(){
        let y = 10;
        let y = 20;
    }  // 报错
    function func(arg) {
      let arg; // 报错
    }
    
    function func(arg) {
      {
        let arg; // 不报错
      }
    }

    let不存在变量提升。

    var声明变量存在变量提升。也就是在声明变量之前就可以使用该变量。

    console.log(x)  // undefined,var声明变量之前可以使用该变量
    var x = 10;

    这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。

    为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

    console.log(x)  // ReferenceError: x is not defined,let声明变量之前不可以使用该变量
    let x = 10;

    ES5中只有全局作用域和函数作用域,并没有块级作用域。

    请看下面的示例: 

    var name = 'Q1mi'
    
    function foo(){
        console.log(name)
        if (false){
            var name = 'Bob'
        }
    }
    foo()  // undefined
    出现上述现象的原因就是在函数内部,由于变量提升导致内存的name变量覆盖了外层的name变量。
    类似的情况还出现在 for循环的计数变量最后会泄露为全局变量。 
    for (var i=0;i<5;i++){
        console.log('哈哈');
    }
    console.log(i);  // 5

    ES6中的let声明变量的方式实际上就为JavaScript新增了块级作用域。

    var name = 'Q1mi'
    
    function foo(){
        console.log(name)
        if (false){
            let name = 'Bob'
        }
    }
    foo()  // Q1mi

    此时,在foo函数内容,外层代码块就不再受内层代码块的影响。所以类似for循环的计数变量我们最好都是用let来声明。

     

    再来看一个例子,var里的坑

    var a = [];
    for (var i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6]();

    上面代码中,变量ivar命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10

    如果使用let,声明的变量仅在块级作用域内有效,最后输出的是 6

    var a = [];
    for (let i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6]();

    上面代码中,变量ilet声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算

    const

    const声明一个只读的常量。一旦声明,常量的值就不能改变。

    const PI = 3.1415;
    PI // 3.1415
    
    PI = 3;
    // TypeError: Assignment to constant variable.

    不赋值就报错

    const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化

    const foo;
    // SyntaxError: Missing initializer in const declaration

    const的作用域与let命令相同:只在声明所在的块级作用域内有效。

    if (true) {
      const MAX = 5;
    }
    
    MAX // Uncaught ReferenceError: MAX is not defined

    全局对象的属性:

    ES6规定:var命令和function命令声明的全局变量依旧是全局对象的属性;let命令、const命令和class命令声明的全局变量不属于全局对象的属性。

    查看下面的示例代码:

    var x = 10;
    let y = 20;
    window.x  // 10
    window.y  // undefined

    字符串

    模板字符串

    模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当做普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。在模板字符串中嵌入变量,需要将变量名写入${}中。

    var name = 'Q1mi', age = 18;
    `My name is ${name}, I’m ${age} years old.`

    传统的JavaScript语言,输出模板通常是这样的写的。

    拼接十分麻烦:

    $('#result').append(
      'There are <b>' + basket.count + '</b> ' +
      'items in your basket, ' +
      '<em>' + basket.onSale +
      '</em> are on sale!'
    );

    上面这种写法相当繁琐不方便,ES6 引入了模板字符串解决这个问题。

    $('#result').append(`
      There are <b>${basket.count}</b> items
       in your basket, <em>${basket.onSale}</em>
      are on sale!
    `);

    模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量

    // 普通字符串
    `In JavaScript '
    ' is a line-feed.`
    
    // 多行字符串
    `In JavaScript this is
     not legal.`
    
    console.log(`string text line 1
    string text line 2`);
    
    // 字符串中嵌入变量
    let name = "Bob", time = "today";
    `Hello ${name}, how are you ${time}?`

    上面代码中的模板字符串,都是用反引号表示。如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。

    let greeting = `\`Yo\` World!`;
    // 输出结果:`Yo` World!

    如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。

    $('#list').html(`
    <ul>
      <li>first</li>
      <li>second</li>
    </ul>
    `);

    ES6新增三个字符串方法

    在此之前,JavaScript中只有indexOf方法可用来确定一个字符串是否包含在另一个字符串中。

    ES6中又提供了3种新方法:

    includes():返回布尔值,表示是否找到了参数字符串。

    stratsWith():返回布尔值,表示参数字符串是否在源字符串的开始位置。

    endsWith():返回布尔值,表示参数字符串是否在源字符串的结尾位置。

    示例:

    var s = "Hello world!";
    
    s.includes("o")  // true
    s.startsWith("Hello")  // true
    s.endsWith("!")  // true

    这三个方法都支持第2个参数,表示开始匹配的位置。

    示例:

    s.includes("o", 8)  // false
    s.startsWith("world", 6)  // true
    s.endsWith("Hello", 5)  // true

    箭头函数

    ES6允许使用“箭头”(=>)定义函数

    var f = a = > a
    
    //等同于
    var f = function(a){
       return a;  
    }

    如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

    //无形参
    var f = () => 5;
    // 等同于
    var f = function () { return 5 };
    
    //多个形参
    var sum = (num1, num2) => num1 + num2;
    // 等同于
    var sum = function(num1, num2) {
      return num1 + num2;
    };

    使用箭头函数注意点:

    箭头函数有几个使用注意点。

    (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

    var name = '张三'var person = {
           name:'小马哥',
           age:18,  
           fav:function(){        
               console.log(this)
               console.log(this.name)
           }
       }
    person.fav();

    我们发现,打印的结果为

    此时this指向的是使用它的对象,也就是person对象

    var person2 = {
       name:'小马哥',
       age:18,
       fav: ()=>{
            // 当前this指向了定义时所在的对象(window)
            console.log(this);
         }
       }
    person2.fav();

     打印的结果:

    使用箭头函数,它表示定义时所在的对象window。

    再看一个例子吧!

    function foo() {
      setTimeout(() => {
        console.log('id:', this.id);
      }, 100);
    }
    
    var id = 21;
    
    foo.call({ id: 42 });
    // id: 42

    上面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到 100 毫秒后。如果是普通函数,执行时this应该指向全局对象window,这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id: 42}),所以输出的是42

    (2)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

             var person3 = {
                 name:'小马哥',
                 age:18,
                 fav: ()=>{
                     console.log(argument);
                 }
             }
    
             person3.fav('把妹','把爷');

    报出如下❎:

     

    对象的单体模式

    为了解决箭头函数this指向的问题 推出来一种写法 对象的单体模式

    var person = {
        name:'张三',
        age:18,
        fav(){
            console.log(this.name,this.age);
        }
      }
    person.fav();

     打印出:

     

    面向对象

    JavaScript 语言中,生成实例对象的传统方法是通过构造函数。

           function Animal(name,age){
                this.name = name;
                this.age = age;
    
            }
            Animal.prototype.showName = function(){
                console.log(this.name);
                console.log(this.age);
            }
    
            var a = new Animal('小黄',5);
            a.showName();

    上面这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大,很容易让新学习这门语言的程序员感到困惑。

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

    基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用 ES6 的class改写,就是下面这样

    class Animal{    
        // 构造器  当你创建实例之后 constructor()方法会立刻调用 通常这个方法初始化对象的属性
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
        showName(){
            console.log(this.name);
        }
    }
    var a2 = new Animal('点点',3);

    上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5 的构造函数Animal,对应 ES6 的Animal类的构造方法。

    Animal类除了构造方法,还定义了一个showName方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。

    ES6 的类,完全可以看作构造函数的另一种写法。

    console.log(Animal2===Animal2.prototype.constructor);//true

    上面代码表示,类本身就指向了类的构造函数。

    使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。

    constructor方法

    constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

    class Animal {
    }
    
    // 等同于
    class Animal {
      constructor() {}
    }

    上面代码中,定义了一个空的类Point,JavaScript 引擎会自动为它添加一个空的constructor方法。

  • 相关阅读:
    Lucene.Net 2.3.1开发介绍 —— 二、分词(一)
    控制‘控制台应用程序’的关闭操作
    详解for循环(各种用法)
    敏捷软件开发
    Sql Server的一些知识点
    在SharePoint 2010 中配置Remote Blob Storage FILESTREAM Provider
    使用LotusScript操作Lotus Notes RTF域
    JOpt Simple 4.5 发布,命令行解析器
    John the Ripper 1.8.0 发布,密码破解工具
    PacketFence ZEN 4.0.1 发布,网络接入控制
  • 原文地址:https://www.cnblogs.com/lxfpy/p/11009698.html
Copyright © 2020-2023  润新知