美文网首页
JavaScript核心技术开发解密读书笔记(第十章上)

JavaScript核心技术开发解密读书笔记(第十章上)

作者: BeLLESS | 来源:发表于2018-08-06 22:54 被阅读15次

    本文关于ES6的讲解比较简单,如有兴趣还请阅读阮一峰大佬的ECMAScript
    6入门

    第十章 ES6与模块化

    1. 常用语法知识
    let/const

    在ES5中,使用var来声明一个变量。在ES6中,新的变量声明方式带来了一些不一样的特性,其中最重要的就是具备了块级作用域并且不再有变量提升(这很重要)。
    下面通过一个简单的例子来说明。

    // ES5
    console.log(a); // undefined
    var a = 20;
    
    // ES6
    console.log(a); // Uncaught ReferenceError: a is not defined
    let a = 20;
    

    ES5存在变量提升,其实ES6也存在,但是并不会给这个变量赋值为undefined。也就是说,虽然声明提前了,但是该变量并没有任何引用,所以上例才会报ReferenceError。
    由于不会默认赋值undefined,加上let/const存在自己的作用于,因此会出现一个叫作暂时性死区的现象。
    因此在编写ES6代码中要注意,尽量将申明主动放置在代码的前面。
    要想使用ES6,就需要全面使用let/const来替换之前非常常用的var,那么什么时候用let,什么时候用const呢?

    一般来说,声明一个引用可以被改变的变量时用let,声明一个引用不能被改变的变量时用const。

    例如:

    let a = 20;
    a = 30;
    a = 40;
    console.log(a); // 40
    
    const PI = 3.1415;
    const MAX_LENGTH = 100;
    
    PI = 3; // Uncaught TypeError: Assignment to constant variable
    

    除此之外,当声明一个引用类型的数据时,也会使用const。尽管可能会改变该数据的值,但是必须保持它的引用不变。

    const a = [];
    a.push(1);
    console.log(a); // [1]
    
    const b = {};
    b.max = 20;
    b.min = 0;
    console.log(b); // {max: 20, min: 0}
    
    箭头函数

    与function相比,箭头函数是一个用起来更加舒服的语法。

    // ES5
    var fn = function (a, b) {
      return a + b;
    }
    
    // ES6
    const fn = (a, b) => a + b;
    
    // ES5
    var foo = function () {
      var a = 20;
      var b = 30;
      return a + b;
    }
    
    // ES6
    const foo = () => {
      const a = 20;
      const b = 30;
      return a + b;
    }
    

    需要注意,箭头函数只能替换函数表达式,即使用var/let/const声明的函数。而直接使用function声明的函数是不能使用箭头函数替换的。

    箭头函数中的this,就是声明函数时所处上下文中的this,它不会被其他方式所改变。

    // ES5
    var name = 'Tom';
    var getName = function () {
      console.log(this.name);
    }
    var person = {
      name: 'Alex',
      getName: getName
    }
    var other = {
      name: 'Joe'
    }
    getName(); // Tom,默认绑定,this指向window
    person.getName(); // Alex,由person调用,this指向person
    getName.call(other); // Joe,显示绑定,通过call使this指向other
    
    // ES6
    var name = 'Tom';
    var getName = () => {
      console.log(this.name);
    }
    var person = {
      name: 'Alex',
      getName: getName
    }
    var other = {
      name: 'Joe'
    }
    getName(); // Tom
    person.getName(); // Tom
    getName.call(other); // Tom
    

    除此之外,arguments还有一个需要大家注意的地方,即在箭头函数中,没有arguments对象。

    // ES5
    var add = function (a, b) {
      console.log(arguments);
      return a + b;
    }
    add(1, 2); // Arguments(2) [1, 2, callee: f, Symbol(Symbol.iterator): f]
    
    // ES6
    var add = (a, b) => {
      console.log(arguments);
      return a + b;
    }
    add(1, 2); // Uncaught ReferenceError: arguments is not defined
    
    2. 模板字符串

    模板字符串是为了解决传统字符串拼接不便利而出现的。

    // ES5
    var a = 20;
    var b = 30;
    var string = a + "+" + b + "=" + (a + b);
    
    // ES6
    const a = 20;
    const b = 30;
    const string = `${a} + ${b} = ${a + b}`;
    

    模板字符串使用反引号`将整个字符串包裹起来,变量或表达式则使用${}来包裹。
    除了能够在字符串中嵌入变量,还可以用来定义多行字符串,其中所有的空格、缩进、换行都会被保留下来。

    var elemString = `<div>
      <p>I like brother black.</p>
      <p>I am sorry to lose you. ${word}</p>
    </div>`
    

    如果是用传统的+拼接这段字符串,则会非常麻烦(各种转义)。
    ${}中可以放入一个变量、表达式,甚至一个函数。

    const hello = 'hello';
    let message = `${hello}, world!`;
    
    const a = 20;
    const b = 30;
    let result = `the result is: ${a + b}`;
    
    let fn = () => {
      const result = `you are the best`;
      return result;
    }
    let str = `he said: ${fn()}`;
    
    3. 解析结构(解构赋值)

    解构赋值是一种从对象或者数组中取得值的一种全新的写法,只需通过一个简单的例子就能立刻明白是怎么回事(实际开发用的很多)。

    // 假设存在这样一个json数据
    var tom = {
      name: 'Tom',
      age: 20,
      gender: 1,
      job: 'student'
    }
    
    // ES5
    var name = tom.name;
    var age = tom.age;
    var gender = tom.gender;
    var job = tom.job;
    
    // ES6
    const {name, age, gender, job} = tom;
    

    可以看到ES6解构赋值比传统赋值方便了很多,我们还可以给变量指定默认值或者重命名。

    const {name = 'Jake', stature = '170'} = tom;
    console.log(name); // Tom,如果数据中找到name,则变量的值与数据中相等
    console.log(stature); // 170,如果数据中找不到stature,则使用默认值
    
    const {gender: t, job} = tom;
    console.log(gender); // Uncaught ReferenceError: gender is not defined
    console.log(t); // 1,重命名后gender将无法访问
    

    我们还可以利用解构赋值获取嵌套数据中的值。

    const peoples = {
      counts: 100,
      detail: {
        tom: {
          name: 'Tom',
          age: 20,
          gender: 1,
          job: 'student'
        }
      }
    }
    // 获取tom
    const {detail: {tom}} = peoples;
    // 获取tom的age与gender
    const {detail: {tom: {age, gender}}} = peoples;
    

    此外,数组也有自己的解构赋值。当然,写法与对象的解构赋值略有不同。

    const arr = [1, 2, 3];
    const [a, b, c] = arr;
    
    // 等价于
    const a = arr[0];
    const b = arr[1];
    const c = arr[2];
    

    与对象不同的是,数组中变量和值得关系与索引是一一对应的,这是一个有序的对应关系,而对象则是根据键值对一一对应的,这是一个无序的对应关系系。因此在实践中,对象的解构赋值使用的更加频繁与便利。

    4. 展开运算符

    在ES6中,使用...来表示展开运算符,它可以展开数组/对象。

    // 首先声明一个数组
    const arr1 = [1, 2, 3];
    // 其次声明另一个数组,我们希望新数组中包含数组arr1的所有元素
    const arr2 = [...arr1, 4, 5, 6];
    console.log(arr2); // [1, 2, 3, 4, 5, 6]
    

    当然,展开对象也可以得到类似的结果。

    const object1 = {
      a: 1,
      b: 2,
      c: 3
    }
    const object2 = {
      ...object1,
      d: 4,
      e: 5,
      f: 6
    }
    console.log(object2); {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6}
    

    在解构赋值中,也常常使用展开运算符。

    const tom = {
      name: 'Tom',
      age: 20,
      gender: 1,
      job: 'student'
    }
    const {name, ...others} = tom;
    console.log(others); // {age: 20, gender: 1, job: 'student'}
    

    展开运算符还可以运用在函数参数中,放置于函数参数的最后一个参数(且只能放置在最后,具体原因参考阮一峰ECMAScript6入门),表示不定参。

    const add = (a, b, ...more) => {
      return more.reduce((m, n) => m + n) + a + n;
    }
    console.log(add(1, 23, 1, 2, 3, 4, 5)); // 39
    
    5. Promise
    同步与异步

    同步是指当发起一个请求时,如果未得到请求结果,代码将会等待,直到结果出来,才会执行后面的代码。
    异步是指当发起一个请求时,不会等待请求结果,而是直接继续执行后面的代码。
    我们使用Promise模拟一个发起请求的函数,该函数在执行后,会在1s之后返回数值30。

    function fn () {
      return new Promise(function (resolve, reject) {
        setTimeout(function () {
          resolve(30)
        }, 1000)
      })
    }
    
    // 在该函数的基础上,可以使用async/await语法来模拟同步的效果
    var foo = async function () {
      var t = await fn();
      console.log(t);
      console.log('next code');
    }
    foo(); // 1s之后输出30,next code
    

    而异步效果则会有不同的输出结果。

    var foo = function () {
      fn().then(function (resp) {
        console.log(resp);
      });
      console.log('next code');
    }
    foo(); // next code,1s之后输出30
    

    以上是我对JavaScript核心技术开发解密第十章(上)的读书笔记,码字不易,请尊重作者版权,转载注明出处。
    By BeLLESS 2018.8.5 15:18

    相关文章

      网友评论

          本文标题:JavaScript核心技术开发解密读书笔记(第十章上)

          本文链接:https://www.haomeiwen.com/subject/uyjbvftx.html