zoukankan      html  css  js  c++  java
  • ES6基础知识

    一、声明 let、const

    1. let

    1). 作用域是块级作用域(在ES6之前,js只存在函数作用域以及全局作用域)

    if(1){
      let a=1;
      console.log(a)
    }

    2). 不存在变量声明提前;

    console.log(b); //ReferenceError: b is not defined
    let b=2;

    3). 不能重复定义

    let a=1;
    let a=2;
    console.log(a);//Identifier 'a' has already been declared

    4). 存在暂时性死区:可以这样来理解

    var a=1if(1){
     console.log(a); 
      let a=2;
    }

    ① 在一个块级作用域中,变量唯一存在,一旦在块级作用域中用let声明了一个变量,那么这个变量就唯一属于这个块级作用域,不受外部变量的影响;

    ② 无论在块中的任何地方声明了一个变量,那么在这个块级作用域中,任何使用这个名字的变量都是指这个变量,无论外部是否有其他同名的全局变量;

    ③ 暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

    ④ 暂时性死区的意义:让我们标准化代码。将所有的变量的声明放在作用域的最开始。

    2.  const

    const一般用来声明常量,且声明的常量是不允许改变的,只读属性,因此就要在声明的同时赋值。const与let一样,都是块级作用域,存在暂时性死区,不存在变量声明提前,不允许重复定义

    const A=1;//重新给常量A赋值会报错 
    A=3;// Uncaught TypeError: Assignment to constant variable.
    //错误:赋值给常量

    二、解构赋值(es6允许按照一定的模式,从数组或对象中提取值,给变量进行赋值)

    //解构赋值,两边格式要一致
    let [a,b,c] = [1,2,3];let [a,[b,c]] = [1,[2,3]];
    //交互数据
    let a = 10;
    let b = 20;
    [a,b] = [b,a];

    三、声明类与继承:class、extend

    用class关键字定义对象类型,用extends关键字实现继承

    const private2 = Symbol('I am symbol value')
    class A {
       a1 = '1'  // ES7 实例属性,需要new实例来访问, ES6规定class没有静态属性,只有静态方法所以只能在constructor中定义属性
       static a2 = '2'  // ES7的静态属性,直接 A.a2 访问,不需要new实例
       getA1() {
             return  this.a1      // this指向new实例
       }
       static  getA2() {
            return   ‘2’    // 静态方法
       }
       constructor(name) {
             //一定要有构造方法,如果没有默认生成空构造方法
            this.a3 = '3'   // 这里定义实例属性
            this.name = name
        }
    
       // 私有方法写法
       publicMethod() {
             private1()    // 私有方法1,可以写在class体外
             private2()   // 利用Symbol值来定义
       }
       [private2]() {
           // 这里是私有方法
       }
    }
    const private1 = function() { // 这里也是私有方法,但别export出去}
    // 最后export class
    export default A
    
    // 通过extends继承
    class B extends A{
        constructor() {
          // 一定要在构造函数的第一句调用super
          super()    // 这是调用父类的构造方法
          this.b1 = '11'
          this.b2 = super.a1    // super直接调用时指向父类构造方法,范围属性时,指向父类实例,或调用父类静态方法
        }
    }

    四、Promise的使用与实现

    Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一。

    1. Promise 处理多个相互关联的异步请求

    const request = url => { 
        return new Promise((resolve, reject) => {
            $.get(url, data => {
                resolve(data)
            });
        })
    };
    
    // 请求data1
    request(url).then(data1 => {
        return request(data1.url);   
    }).then(data2 => {
        return request(data2.url);
    }).then(data3 => {
        console.log(data3);
    }).catch(err => throw new Error(err));

    2. Promise使用

    2.1 Promise 是一个构造函数, new Promise 返回一个 promise对象 接收一个excutor执行函数作为参数, excutor有两个函数类型形参resolve reject

    const promise = new Promise((resolve, reject) => {
           // 异步处理
           // 处理结束后、调用resolve 或 reject
    });

    2.2 promise相当于一个状态机

    promise的三种状态

    • pending
    • fulfilled
    • rejected

    ①promise 对象初始化状态为 pending
    ②当调用resolve(成功),会由pending => fulfilled
    ③当调用reject(失败),会由pending => rejected

    注意:promsie状态 只能由 pending => fulfilled/rejected, 一旦修改就不能再变

    2.3 promise对象方法

    1)then方法注册 当resolve(成功)/reject(失败)的回调函数,then方法是异步执行的

    // onFulfilled 是用来接收promise成功的值
    // onRejected 是用来接收promise失败的原因
    promise.then(onFulfilled, onRejected);

    2)resolve(成功) onFulfilled会被调用

    const promise = new Promise((resolve, reject) => {
       resolve('fulfilled'); // 状态由 pending => fulfilled
    });
    promise.then(result => { // onFulfilled
        console.log(result); // 'fulfilled' 
    }, reason => { // onRejected 不会被调用
        
    })

    3)reject(失败) onRejected会被调用

    const promise = new Promise((resolve, reject) => {
       reject('rejected'); // 状态由 pending => rejected
    });
    promise.then(result => { // onFulfilled 不会被调用
      
    }, reason => { // onRejected 
        console.log(rejected); // 'rejected'
    })

    4)promise.catch

    在链式写法中可以捕获前面then中发送的异常

    promise.catch(onRejected)
    相当于
    promise.then(null, onRrejected);
    
    // 注意
    // onRejected 不能捕获当前onFulfilled中的异常
    promise.then(onFulfilled, onRrejected); 
    
    // 可以写成:
    promise.then(onFulfilled)
           .catch(onRrejected); 

    3. promise chain

    promise.then方法每次调用 都返回一个新的promise对象 所以可以链式写法

    function taskA() {
        console.log("Task A");
    }
    function taskB() {
        console.log("Task B");
    }
    function onRejected(error) {
        console.log("Catch Error: A or B", error);
    }
    
    var promise = Promise.resolve();
    promise
        .then(taskA)
        .then(taskB)
        .catch(onRejected) // 捕获前面then方法中的异常

    4. Promise的静态方法

    1)Promise.resolve 返回一个fulfilled状态的promise对象

    Promise.resolve('hello').then(function(value){
        console.log(value);
    });
    
    Promise.resolve('hello');
    // 相当于
    const promise = new Promise(resolve => {
       resolve('hello');
    });

    2)Promise.reject 返回一个rejected状态的promise对象

    Promise.reject(24);
    new Promise((resolve, reject) => {
       reject(24);
    });

    3)Promise.all 接收一个promise对象数组为参数

    只有全部为resolve才会调用 通常会用来处理 多个并行异步操作

    const p1 = new Promise((resolve, reject) => {
        resolve(1);
    });
    
    const p2 = new Promise((resolve, reject) => {
        resolve(2);
    });
    
    const p3 = new Promise((resolve, reject) => {
        reject(3);
    });
    
    Promise.all([p1, p2, p3]).then(data => { 
        console.log(data); // [1, 2, 3] 结果顺序和promise实例数组顺序是一致的
    }, err => {
        console.log(err);
    });

    4)Promise.race 接收一个promise对象数组为参数

    Promise.race 只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理

    function timerPromisefy(delay) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                resolve(delay);
            }, delay);
        });
    }
    var startDate = Date.now();
    Promise.race([
        timerPromisefy(10),
        timerPromisefy(20),
        timerPromisefy(30)
    ]).then(function (values) {
        console.log(values); // 10
    });

    5. promise实现

    /**
     * 摘自https://www.cnblogs.com/minigrasshopper/p/9141307.html
     * Promise类实现原理
     * 构造函数传入一个function,有两个参数,resolve:成功回调; reject:失败回调
     * state: 状态存储 [PENDING-进行中 RESOLVED-成功 REJECTED-失败]
     * doneList: 成功处理函数列表
     * failList: 失败处理函数列表
     * done: 注册成功处理函数
     * fail: 注册失败处理函数
     * then: 同时注册成功和失败处理函数
     * always: 一个处理函数注册到成功和失败
     * resolve: 更新state为:RESOLVED,并且执行成功处理队列
     * reject: 更新state为:REJECTED,并且执行失败处理队列
    **/
    
    class PromiseNew {
      constructor(fn) {
        this.state = 'PENDING';
        this.doneList = [];
        this.failList = [];
        fn(this.resolve.bind(this), this.reject.bind(this));
      }
    
      // 注册成功处理函数
      done(handle) {
        if (typeof handle === 'function') {
          this.doneList.push(handle);
        } else {
          throw new Error('缺少回调函数');
        }
        return this;
      }
    
      // 注册失败处理函数
      fail(handle) {
        if (typeof handle === 'function') {
          this.failList.push(handle);
        } else {
          throw new Error('缺少回调函数');
        }
        return this;
      }
    
      // 同时注册成功和失败处理函数
      then(success, fail) {
        this.done(success || function () { }).fail(fail || function () { });
        return this;
      }
    
      // 一个处理函数注册到成功和失败
      always(handle) {
        this.done(handle || function () { }).fail(handle || function () { });
        return this;
      }
    
      // 更新state为:RESOLVED,并且执行成功处理队列
      resolve() {
        this.state = 'RESOLVED';
        let args = Array.prototype.slice.call(arguments);
        setTimeout(function () {
          this.doneList.forEach((item, key, arr) => {
            item.apply(null, args);
            arr.shift();
          });
        }.bind(this), 200);
      }
    
      // 更新state为:REJECTED,并且执行失败处理队列
      reject() {
        this.state = 'REJECTED';
        let args = Array.prototype.slice.call(arguments);
        setTimeout(function () {
          this.failList.forEach((item, key, arr) => {
            item.apply(null, args);
            arr.shift();
          });
        }.bind(this), 200);
      }
    }
    
    // 下面一波骚操作
    new PromiseNew((resolve, reject) => {
      resolve('hello world');
      // reject('you are err');
    }).done((res) => {
      console.log(res);
    }).fail((res) => {
      console.log(res);
    })

    五、generator(异步编程、yield、next()、await 、async)

    使用Generator可以很方便的帮助我们建立一个处理Promise的解释器;

    async/await这样的语法,可以让我们以接近编写同步代码的方式来编写异步代码(无需使用.then()或者回调函数)

    1. Generator

    Generator是一个函数,可以在函数内部通过yield返回一个值(此时,Generator函数的执行会暂定,直到下次触发.next()) 创建一个Generator函数的方法是在function关键字后添加*标识。

    在调用一个Generator函数后,并不会立即执行其中的代码,函数会返回一个Generator对象,通过调用对象的next函数,可以获得yield/return的返回值。 无论是触发了yield还是returnnext()函数总会返回一个带有valuedone属性的对象。 value为返回值,done则是一个Boolean对象,用来标识Generator是否还能继续提供返回值。 P.S. Generator函数的执行时惰性的,yield后的代码只在触发next时才会执行。

    function * oddGenerator () {
      yield 1
      yield 3
      return 5
    }
    let iterator = oddGenerator()
    let first = iterator.next()  // { value: 1, done: false }
    let second = iterator.next() // { value: 3, done: false }
    let third = iterator.next()  // { value: 5, done: true  }

    2. Async

    function getRandom () {
      return new Promise(resolve => {
        setTimeout(_ => resolve(Math.random() * 10 | 0), 1000)
      })
    }
    
    async function main () {
      let num1 = await getRandom()
      let num2 = await getRandom()
    
      return num1 + num2
    }
    
    console.log(`got data: ${await main()}`)

    Async函数始终返回一个Promise

    async function throwError () {
      throw new Error()
    }
    async function returnNumber () {
      return 1
    }
    
    console.log(returnNumber() instanceof Promise) // true
    console.log(throwError() instanceof Promise)   // true

    Await是按照顺序执行的,并不能并行执行,JavaScript是单线程的,这就意味着await一只能一次处理一个,如果你有多个Promise需要处理,则就意味着,你要等到前一个Promise处理完成才能进行下一个的处理,这就意味着,如果我们同时发送大量的请求,这样处理就会非常慢。

    function delay () {
      return new Promise(resolve => setTimeout(resolve, 1000))
    }
    
    let tasks = [1, 2, 3, 4]
    
    //要4s才能执行完
    async function runner (tasks) {
      for (let task of tasks) {
        await delay()
      }
    }
    //优化,缩短执行时间
    async function runner (tasks) {
      tasks = tasks.map(delay)
      await Promise.all(tasks)
    }
    
    console.time('runner')
    await runner(tasks)
    console.timeEnd('runner')

    Generatorasync function都是返回一个特定类型的对象:

    • Generator: 一个类似{ value: XXX, done: true }这样结构的Object
    • Async: 始终返回一个Promise,使用await或者.then()来获取返回值

    Generator是属于生成器,一种特殊的迭代器,用来解决异步回调问题感觉有些不务正业了。。 而async则是为了更简洁的使用Promise而提出的语法,相比Generator + co这种的实现方式,更为专注,生来就是为了处理异步编程。

    六、箭头函数this指向问题、拓展运算符

    // 两个参数:
    (x, y) => x * x + y * y
    
    // 无参数:
    () => 3.14
    
    // 可变参数:
    (x, y, ...rest) => {
        var i, sum = x + y;
        for (i=0; i<rest.length; i++) {
            sum += rest[i];
        }
        return sum;
    }

    1. 不绑定this

    var obj = {
       age: 1,
       say: function() {
          setTimeout(function() {
             console.log(this, this.age); // window undefined
          }, 0);
       },
    }
    var obj1 = {
       age: 1,
       say: function() {
          setTimeout(() => {
             console.log(this, this.age); // obj1 1
          }, 0);
       }
    };

    这里可以看出箭头函数中访问的this实际上是其父级作用域中的this,箭头函数本身的this是不存在的,这样就相当于箭头函数的this是在声明的时候就确定了(即this总是指向词法作用域,也就是外层调用者handler),这个特性是很有用的,所以,call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略。

    var handler = {
       id: '111',
       doSomething: function(e) {
           console.log(e);
       },
       init: function() {
          document.addEventListener('click', (event) => { // 这里绑定事件,函数this就可以访问到handler的方法doSomething
             this.doSomething(event);
          }, false);
       }
    }
    handler.init();

    2. 不可以作为构造函数来使用

    var Person = (name) => { // Uncaught TypeError: Person is not a constructor
        this.name = name;
    }
    var person = new Person('Jack');

    3. 不绑定arguments(如果有要使用arguments的时候可以使用rest参数代替)

    var foo = (val) => {
        console.log(arguments); // Uncaught ReferenceError: arguments is not defined
    };
    foo();
    //这个特性也很好测试,但是实在要使用arguments对象要怎么办呢?我们可以使用es6的另一个新特性rest参数,完美替代
    var foo = (...args) => {
        console.log(args); // [1, 2, 3]
    };
    foo(1, 2, 3);

    4. 不可以使用yield命令,因此箭头函数不能用作Generator函数

    七、map和set有没有用过,如何实现一个数组去重,map数据结构有什么优点?

    JavaScript的默认对象表示方式{}可以视为其他语言中的MapDictionary的数据结构,即一组键值对。但是JavaScript的对象有个小问题,就是键必须是字符串。但实际上Number或者其他数据类型作为键也是非常合理的。为了解决这个问题,最新的ES6规范引入了新的数据类型Map。

    Map的遍历

    • keys():返回键名的遍历器。
    • values():返回键值的遍历器。
    • entries():返回所有成员的遍历器。
    • forEach():遍历 Map 的所有成员。
    • 需要特别注意的是,Map 的遍历顺序就是插入顺序
    var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
    m.get('Michael'); // 95
    
    //初始化Map需要一个二维数组,或者直接初始化一个空Map。Map具有以下方法:
    var m = new Map(); // 空Map
    m.set('Adam', 67); // 添加新的key-value
    m.set('Bob', 59);
    m.has('Adam'); // 是否存在key 'Adam': true
    m.get('Adam'); // 67
    m.delete('Adam'); // 删除key 'Adam'
    m.get('Adam'); // undefined
    //由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉
    //遍历Map
    var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
    m.forEach(function (value, key, map) {
        console.log(value);
    });

    SetMap类似,也是一组key的集合,但不存储value。由于key不能重复,所以,Set中,没有重复的key

    //要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set:
    var s1 = new Set(); // 空Set
    var s2 = new Set([1, 2, 3]); // 含1, 2, 3
    
    //重复元素在Set中自动被过滤:
    var s = new Set([1, 2, 3, 3, '3']);
    s; // Set {1, 2, 3, "3"}
    
    //通过add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果:
    s.add(4);
    s; // Set {1, 2, 3, 4}
    s.add(4);
    s; // 仍然是 Set {1, 2, 3, 4}
    
    //通过delete(key)方法可以删除元素:
    var s = new Set([1, 2, 3]);
    s; // Set {1, 2, 3}
    s.delete(3);
    s; // Set {1, 2}
    
    //遍历Set
    var s = new Set(['A', 'B', 'C']);
    s.forEach(function (element, sameElement, set) {
        console.log(element);
    });

    数组去重

    //1.for循环嵌套,利用splice去重
    function newArr(arr){
        for(var i=0;i<arr.length;i++){
            for(var j=i+1;j<arr.length;j++)
                if(arr[i]==arr[j]){ 
                //如果第一个等于第二个,splice方法删除第二个
                arr.splice(j,1);
                j--;
                }
            }
        }
        return arr;
    }
    var arr = [1,1,2,5,6,3,5,5,6,8,9,8];
    console.log(newArr(arr))
    
    //2.建新数组,利用indexOf去重
    function newArr(array){ 
        //一个新的数组 
        var arrs = []; 
        //遍历当前数组 
        for(var i = 0; i < array.length; i++){ 
            //如果临时数组里没有当前数组的当前值,则把当前值push到新数组里面 
            if (arrs.indexOf(array[i]) == -1){ 
                arrs.push(array[i])
            }; 
        } 
        return arrs; 
    }
    var arr = [1,1,2,5,5,6,8,9,8];
    console.log(newArr(arr))
    
    //3.ES6中利用Set去重
    function newArr(arr){
        return Array.from(new Set(arr))
    }
    var arr = [1,1,2,9,6,9,6,3,1,4,5];
    console.log(newArr(arr))

    八、ES6怎么编译成ES5,css-loader原理,过程

    现在的Chrome浏览器已经支持ES6了,但是有些低版本的浏览器还是不支持ES6的语法,这就需要我们把ES6的语法自动的转变成ES5的语法。Webpack是有自动编译转换能力的,除了Webpack自动编译,还可以使用用Babel来完成。

    • 初始化项目
      打开终端或者通过cmd打开命令行工具,进入项目目录,输入下边的命令:
       npm init -y 
      -y代表全部默认同意,就不用一次次按回车了。命令执行完成后,会在项目根目录下生产package.json文件。
    {
      "name": "es6",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo "Error: no test specified" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }

    可以根据自己的需要进行修改,比如我们修改name的值为es6。

    • 全局安装Babel-cli
       npm install -g babel-cli 
    • 本地安装babel-preset-es2015 和 babel-cli
       npm install --save-dev babel-preset-es2015 babel-cli 
    • 新建.babelrc
      在根目录下新建.babelrc文件,并打开录入下面的代码
    {
        "presets":[
            "es2015"
        ],
        "plugins":[]
    }

    这个文件我们建立完成后,现在可以在终端输入的转换命令了,这次ES6成功转化为ES5的语法。 babel dist/index.js -o src/index.js 

    • 简化转化命令:
      在学习vue 的时候,可以使用npm run build 直接利用webpack进行打包,在这里也希望利用这种方式完成转换。打开package.json文件,把文件修改成下面的样子。
    {
      "name": "es6",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "build": "babel src/index.js -o dist/index.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "babel-cli": "^6.24.1",
        "babel-preset-es2015": "^6.24.1"
      }
    }

    修改好后,以后我们就可以使用  npm run build  来进行转换了。

    webpack的loaders是一块很重要的组成部分。我们都知道webpack是用于资源打包的,里面的所有资源都是“模块”,内部实现了对模块资源进行加载的机制。但是Webpack本身只能处理 js模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。 

    Loader 可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果,例如可以使用loader加载器可以快速编译预处理器(less,sass,coffeeScript)。 Loader 可以在require()引用模块的时候添加,也可以在 webpack 全局配置中进行绑定,还可以通过命令行的方式使用。

    loader的特性是: 

    • loaders可以串联,他们应用于管道资源,最后的loader将返回javascript,其它的可返回任意格式(传递给下一个loader)
    • loaders 可以同步也可以异步
    • loaders在nodejs下运行并且可以做一切可能的事 loader接受参数,可用于配置里 
    • loaders可以绑定到extension/RegExps 配置 
    • loaders可以通过npm发布和安装 正常的模块儿可以到处一个
    • loader除了 loaders可以访问配置 插件可以给loaders更多的特性
    • loaders可以释放任意额外的文件
    本部分摘自链接:https://www.jianshu.com/p/059c5b68d9d5

    九、import和export    AMD

    ES6之前已经出现了js模块加载的方案,最主要的是CommonJS和AMD规范。commonjs主要应用于服务器,实现同步加载,如nodejs。AMD规范应用于浏览器,如requirejs,为异步加载。同时还有CMD规范,为同步加载方案如seaJS。

    ES6在语言规格的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。

    ES6模块主要有两个功能:export和import

    export用于对外输出本模块(一个文件可以理解为一个模块)变量的接口

    import用于在一个模块中加载另一个含有export接口的模块。

    CommonJS模块的重要特性是加载时执行,即脚本代码在require的时候,就会全部执行。一旦出现某个模块被“循环加载”就只输出已经执行的部分,还没有执行的部分是不输出的。

    ES6模块是动态引用,如果使用import从一个模块加载变量,那些变量不会缓存,而是成为一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值

    impor/export(都是语法糖啦)最终都是编译为require/exports来执行的

    CommonJS规范规定,每个模块内部,module变量代表当前模块,这个变量是一个对象,他的exports属性是对外的接口,加载某个模块,其实是加载该模块module.exports属性。export命令规定的是对外的接口,必须与模块内部的变量建立一一对应的关系

    AMD是RequireJS在推广过程中对模块定义的规范化产出,它是一个概念,RequireJS是对这个概念的实现,就好比JavaScript语言是对ECMAScript规范的实现。AMD是一个组织,RequireJS是在这个组织下自定义的一套脚本语言

    CMD---是SeaJS在推广过程中对模块定义的规范化产出,是一个同步模块定义,是SeaJS的一个标准,SeaJS是CMD概念的一个实现,SeaJS是淘宝团队提供的一个模块开发的js框架

    CommonJS规范---是通过module.exports定义的,在前端浏览器里面并不支持module.exports,通过node.js后端使用的。Nodejs端是使用CommonJS规范的,前端浏览器一般使用AMD、CMD、ES6等定义模块化开发的

    十、ES6转成ES5的常见例子

    bable.js

    babel是一个转译器,感觉相对于编译器compiler,叫转译器transpiler更准确,因为它只是把同种语言的高版本规则翻译成低版本规则,而不像编译器那样,输出的是另一种更低级的语言代码。
    但是和编译器类似,babel的转译过程也分为三个阶段:parsing、transforming、generating,以ES6代码转译为ES5代码为例,babel转译的具体过程如下:

    ES6代码输入 ==》 babylon进行解析 ==》 得到AST
    ==》 plugin用babel-traverse对AST树进行遍历转译 ==》 得到新的AST树
    ==》 用babel-generator通过AST树生成ES5代码

    此外,还要注意很重要的一点就是,babel只是转译新标准引入的语法,比如ES6的箭头函数转译成ES5的函数;而新标准引入的新的原生对象,部分原生对象新增的原型方法,新增的API等(如Proxy、Set等),这些babel是不会转译的。需要用户自行引入polyfill来解决

    //摘自博客:https://blog.csdn.net/qq_42149830/article/details/88295747
    function _defineProperties(target,prop){
            prop.forEach(ele => {        //可能会传入多个属性
                Object.defineProperty(target,ele.key,{
                    value:ele.value,
                    writable:true,
                    configurable:true,
                })
            });//设置所设置的属性是否可写,可枚举
    }
    
    function _createClass(_constructor,_prototypeProperties,_staticProperties){ //这里传入的三个参数分别是构造函数,原型上的属性,静态属性
        if(_prototypeProperties){   //设置公有属性
            _defineProperties(_constructor.prototype,_prototypeProperties)
        }
        if(_staticProperties){  //设置静态属性
            _defineProperties(_constructor,_staticProperties)
        }
    }
    
    function _classCallCheck(_this,_constructor){
        if(!(_this instanceof _constructor)){     //判断是否是通过new(创建实例)来调用_constructor
                throw "TypeError: Class constructor AirPlane cannot be invoked without 'new'"
        }
    }
    var FatherPlane=(function(){
        function FatherPlane(name,color){
            _classCallCheck(this,FatherPlane)
            this.name=name||'liu';
            this.color=color||'red'
        }
        _createClass(FatherPlane,[
            {
                key:'fly',
                value:function(){
                    console.log('fly')
                }
            }
        ],[
            {
               key:'static',
               value:function(){
                   console.log('static')
               } 
            }
        ])
        return FatherPlane;
    })()
    var airplane=new FatherPlane()
  • 相关阅读:
    Spring的历史和哲学
    CORS简介
    LDAP概念了解
    Restful levels&HATEOAS
    python/mysql connector
    Session&Cookie 简介及使用
    XML简介
    Json简介
    《魅族官网》
    期末设计部分代码截图
  • 原文地址:https://www.cnblogs.com/lxy-starry/p/11239376.html
Copyright © 2011-2022 走看看