• ES6快速入门使用


     https://www.jianshu.com/p/061304806bda

    Babel-webpack的配置

    前段项目我想使用ES6的语法我应该怎么做呢?我们可以查看Babel的官方文档,就简单用webpack如何配置
    所以我们就可以先用ES6语言来写代码,然后用webpack打包生成ES5的文件,下面只是简单介绍一下,详细的可以查看官方文档,当然了这只是一种工具,我们只需要看官网怎么做的就可以

    1. Shell
    npm install --save-dev babel-loader babel-core
    
    2. webpack.config.js
    module: {
      rules: [
        { test: /.js$/, exclude: /node_modules/, loader: "babel-loader" }
      ]
    }
    
    3. create .babelrc
    npm install babel-preset-env --save-dev
    //JSON
    {
      "presets": ["env"]
    }
    

    var let const

    • var 可声明前置
    var a
    a = 1
    var a = 2
    

    ES6 新增了let命令,用来声明变量。它的用法类似于var,但也有区别:

    • let 不存在变量提升
    console.log(bar); // 报错ReferenceError
    let bar = 2;
    
    a = 1  //报错
    let a
    
    • let不允许在相同作用域内,重复声明同一个变量。
    // 报错
    function func() {
      let a = 10;
      var a = 1;
    }
    
    // 报错
    function func() {
      let a = 10;
      let a = 1;
    }
    
    let a = 3
    var a =4  //报错
    let a =5  //报错
    
    • 存在块级作用域
    for(let i =0;i<3;i++){
      console.log(i)
    }
    console.log(i)  //报错
    

    块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。

    (function(){
      var a = 1
    })()
    
    ==>
    
    {
      let a = 1
    }
    

    ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

    1. 内层变量可能会覆盖外层变量。
    var tmp = new Date();
    
    function f() {
      console.log(tmp);
      if (false) {
        var tmp = 'hello world';  // var tmp 变量提升
      }
    }
    
    f(); // undefined
    
    1. 用来计数的循环变量泄露为全局变量。
    var s = 'hello';
    
    for (var i = 0; i < s.length; i++) {
      console.log(s[i]);  // i泄露为全局变量
    }
    
    console.log(i); // 5
    
    • 暂时性死区(TDZ)
    var tmp = 123;
    
    if (true) {
      tmp = 'abc'; // ReferenceError
      let tmp;
    }
    

    只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
    暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

    • const

    const声明一个只读的常量。一旦声明,常量的值就不能改变。
    const一旦声明变量,就必须立即初始化,不能留到以后赋值。

    //基本类型
    const PI = 3.1415;
    PI // 3.1415
    PI = 3;  // TypeError: Assignment to constant variable.
    
    //引用类型
    const foo = {};
    // 为 foo 添加一个属性,可以成功
    foo.prop = 123;
    foo.prop // 123
    // 将 foo 指向另一个对象,就会报错
    foo = {}; // TypeError: "foo" is read-only
    

    适用let的也适用const


    解构赋值

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

    • 数组的解构赋值
    let [a,b,c] = [1,2,3]
    console.log(a,b,c)  // 1 2 3
    
    let [a, [b], c] = [1, [2], 3]
    a // 1
    b // 2
    c // 3
    
    let [x, , y] = [1, 2, 3] // x=1  y=3
    
    let [head, ...tail] = [1, 2, 3, 4];
    head // 1
    tail // [2, 3, 4]
    

    如果解构不成功,变量的值就等于undefined。

    let [foo] = [];
    let [bar, foo] = [1];
    
    // 报错
    let [foo] = 1;
    

    默认值
    解构赋值允许指定默认值。
    数组对应值有没有?如果没有(没有指undefined),使用默认值,有就使用对应值

    let [foo = true] = [];
    foo // true
    
    let [x, y = 'b'] = ['a']; // x='a', y='b'
    let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
    
    let [a=2,b=3] = [undefined, null]
    a  //2
    b  //null
    
    • 对象的解构赋值
      实际上说明,对象的解构赋值是下面形式的简写
    let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
    
    let { foo, bar } = { foo: "aaa", bar: "bbb" };
    foo // "aaa"
    bar // "bbb"
    

    对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

    let { bar, foo } = { foo: "aaa", bar: "bbb" };
    foo // "aaa"
    bar // "bbb"
    
    let { baz } = { foo: "aaa", bar: "bbb" };
    baz // undefined  没有同名的
    

    对象解构的默认值
    默认值生效的条件是,对象的属性值严格等于undefined。

    var {x = 3} = {};
    x // 3
    
    var {x, y = 5} = {x: 1};
    x // 1
    y // 5
    
    var {x: y = 3} = {};
    y // 3
    
    var {x: y = 3} = {x: 5};
    y // 5
    
    var { message: msg = 'Something went wrong' } = {};
    msg // "Something went wrong"
    
    • 字符串的解构赋值
    const [a, b, c, d, e] = 'hello';
    a // "h"
    b // "e"
    c // "l"
    d // "l"
    e // "o"
    
    类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
    
    let {length : len} = 'hello';
    len // 5
    
    • 数值和布尔值的解构赋值

    解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

    let {toString: s} = 123;
    s === Number.prototype.toString // true
    
    let {toString: s} = true;
    s === Boolean.prototype.toString // true
    

    解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

    let { prop: x } = undefined; // TypeError
    let { prop: y } = null; // TypeError
    
    • 函数参数的解构赋值
    function add([x, y] = [1,1]){
      return x + y;
    }
    add()  // 2
    add([2])  // 3 
    add([1, 2]); // 3
    
    function sum({x,y} = {x:0, y:0},{a=1,b=1}){
      return [x+a,y+b]
    }
    console.log(sum({x:1,y:2},{a:2}))  //[3,3]
    
    • 解构赋值的作用
    1. 交换变量的值
    let x = 1;
    let y = 2;
    
    [x, y] = [y, x];  // [2,1]
    
    1. 函数参数默认值
    function ajax(url , type='GET'){
      
    }
    ajax(url:'http://localhost')
    

    字符串常用

    • 字符串模板
    // ES5字符串拼接
    $('#result').append(
      'There are <b>' + basket.count + '</b> ' +
      'items in your basket, ' +
      '<em>' + basket.onSale +
      '</em> are on sale!'
    );
    

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

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

    模板字符串中嵌入变量,需要将变量名写在${}之中

    function authorize(user, action) {
      if (!user.hasPrivilege(action)) {
        throw new Error(
          // 传统写法为
          // 'User '
          // + user.name
          // + ' is not authorized to do '
          // + action
          // + '.'
          `User ${user.name} is not authorized to do ${action}.`);
      }
    }
    

    数组扩展常用

    • 扩展运算符
      扩展运算符(spread)是三个点(...)
    var a = [1,2]
    console.log(...a)  // 1,2
    var b = [...a,3]
    b  // [1,2,3]
    
    function add(x, y) {
      return x + y;
    }
    const numbers = [4, 38];
    add(...numbers) // 42
    
    ... 应用替代apply用法
    // ES5 的写法
    Math.max.apply(null, [14, 3, 77])
    // ES6 的写法
    Math.max(...[14, 3, 77])
    
    // ES5的 写法
    var arr1 = [0, 1, 2];
    var arr2 = [3, 4, 5];
    Array.prototype.push.apply(arr1, arr2);
    // ES6 的写法
    let arr1 = [0, 1, 2];
    let arr2 = [3, 4, 5];
    arr1.push(...arr2);
    
    函数参数的扩展
    function sort(...arr){
      console.log(arr.sort())
    }
    sort(3,1,5)  //[1,3,5]
    
    • Array.form()
      • Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。
    // NodeList对象
    let ps = document.querySelectorAll('p');
    Array.from(ps).forEach(function (p) {
      console.log(p);
    });
    
    // arguments对象
    function foo() {
      var args = Array.from(arguments);
      // ...
    }
    
    //  类数组对象
    let arrayLike = {
        '0': 'a',
        '1': 'b',
        '2': 'c',
        length: 3
    };
    // ES5的写法
    var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
    
    // ES6的写法
    let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
    

    函数扩展

    • 可以给参数添加默认值
    function log(x, y = 'World') {
      console.log(x, y);
    }
    log('Hello') // Hello World
    log('Hello', 'China') // Hello China
    log('Hello', '') // Hello
    
    //练习,区别?
    // 写法一
    function m1({x = 0, y = 0} = {}) {
      return [x, y];
    }
    // 写法二
    function m2({x, y} = { x: 0, y: 0 }) {
      return [x, y];
    }
    
    
    // 函数没有参数的情况
    m1() // [0, 0]
    m2() // [0, 0]
    
    // x 和 y 都有值的情况
    m1({x: 3, y: 8}) // [3, 8]
    m2({x: 3, y: 8}) // [3, 8]
    
    // x 有值,y 无值的情况
    m1({x: 3}) // [3, 0]
    m2({x: 3}) // [3, undefined]
    
    // x 和 y 都无值的情况
    m1({}) // [0, 0];
    m2({}) // [undefined, undefined]
    
    m1({z: 3}) // [0, 0]
    m2({z: 3}) // [undefined, undefined]
    
    //总结
    ex1: 调用函数需要你传递一个对象,如果你没传对象就用默认值对象{},默认值对象里面都是 undefined, 所以属性使用初始值
    
    ex2:参数需要是一个对象,如果没传对象,就用默认值对象{ x: 0, y: 0 }如果传了对象,就使用你传递的对象
    
    • 箭头函数
      • ES6 允许使用“箭头”(=>)定义函数。
    var f = v => v;
    //等价于
    var f = function(v) {
      return v;
    };
    
    var f = () => 5;
    // 等同于
    var f = function () { return 5 };
    
    var sum = (num1, num2) => num1 + num2;
    // 等同于
    var sum = function(num1, num2) {
      return num1 + num2;
    };
    

    如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。

    var sum = (num1, num2) => { return num1 + num2; }
    
    • 箭头函数的this

    函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。this对象的指向是可变的,但是在箭头函数中,它是固定的。

    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

    对象扩展

    • 属性的简洁表示法
      ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
    const foo = 'bar';
    const baz = {foo};
    baz // {foo: "bar"}
    
    // 等同于
    const baz = {foo: foo};
    
    function f(x, y) {
      return {x, y};
    }
    // 等同于
    function f(x, y) {
      return {x: x, y: y};
    }
    f(1, 2) // Object {x: 1, y: 2}
    
    //方法简写
    const o = {
      method() {
        return "Hello!";
      }
    };
    
    // 等同于
    
    const o = {
      method: function() {
        return "Hello!";
      }
    };
    

    Module的语法 模块化

    模块功能主要由两个命令构成:export和importexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

    一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。下面是一个 JS 文件,里面使用export命令输出变量。

    // profile.js
    export var firstName = 'Michael';
    export var lastName = 'Jackson';
    export var year = 1958;
    
    // profile.js
    var firstName = 'Michael';
    var lastName = 'Jackson';
    var year = 1958;
    export {firstName, lastName, year};
    
    //usage.js
    import {firstName, lastName, year} from './profile';
    

    export命令除了输出变量,还可以输出函数或类(class)。

    export function multiply(x, y) {
      return x * y;
    };
    
    • export default 命令
      使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载,为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。
    // export-default.js
    export default function () {
      console.log('foo');
    }
    

    其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

    // import-default.js
    import customName from './export-default';
    customName(); // 'foo'
    

    Class和继承

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

    //定义类
    class Point {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
    
      toString() {
        return '(' + this.x + ', ' + this.y + ')';
      }
    }
    
    //等价于
    
    function Point(x, y) {
      this.x = x;
      this.y = y;
    }
    
    Point.prototype.toString = function () {
      return '(' + this.x + ', ' + this.y + ')';
    };
    
    var p = new Point(1, 2);
    

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

    class Point {
      // ...
    }
    
    typeof Point // "function"
    Point === Point.prototype.constructor // true
    

    构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。

    class Point {
      constructor() {
        // ...
      }
    
      toString() {
        // ...
      }
    
      toValue() {
        // ...
      }
    }
    
    // 等同于
    
    Point.prototype = {
      constructor() {},
      toString() {},
      toValue() {},
    };
    

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

    class Point {
    }
    
    // 等同于
    class Point {
      constructor() {}
    }
    
    • Class静态方法
      类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
    class Foo {  //类
      static classMethod() {
        return 'hello';
      }
    }
    
    Foo.classMethod() // 'hello'
    
    var foo = new Foo();
    foo.classMethod()
    // TypeError: foo.classMethod is not a function
    

    上面代码中,Foo类的classMethod方法前有static关键字,表明该方法是一个静态方法,可以直接在Foo类上调用(Foo.classMethod()),而不是在Foo类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。

    • 继承
      Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
    class Point {
    }
    
    class ColorPoint extends Point {
    }
    

    super 关键字

    super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

    class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
    
      sayHello() {
        console.log( `hello, ${this.name}, i am ${this.age} years old`);
      }
    }
    class Student extends Person {
      constructor(name, age, score) {
        super(name, age); 
        this.score = score;
      }
    
      sayScore() {
         console.log(  `hello, ${this.name}, i am ${this.age} years old, i get ${this.score}`);
      }
    }
    
     
  • 相关阅读:
    Django学习手册
    Django学习手册
    django 学习手册
    Django学习手册
    python
    python
    osg学习笔记2, 命令行参数解析器ArgumentParser
    osg(OpenSceneGraph)学习笔记1:智能指针osg::ref_ptr<>
    Boost.Build 简明教程
    Boost1.6x+win7+VC2015编译
  • 原文地址:https://www.cnblogs.com/williamjie/p/9592506.html
Copyright © 2020-2023  润新知