ECMAScript 6学习笔记

1.环境支持
首先,必须在网页头部加载Traceur库文件
   
   
   
   
  1. <!-- 加载Traceur编译器 -->
  2. <scriptsrc="http://google.github.io/traceur-compiler/bin/traceur.js" type="text/javascript"></script>
  3. <!-- 将Traceur编译器用于网页 -->
  4. <scriptsrc="http://google.github.io/traceur-compiler/src/bootstrap.js" type="text/javascript"></script>
  5. <!-- 打开实验选项,否则有些特性可能编译不成功 -->
  6. <script>
  7. traceur.options.experimental =true;
  8. </script>
  9. <scripttype="module">
  10. classCalc{
  11. constructor(){
  12. console.log('Calc constructor');
  13. }
  14. add(a, b){
  15. return a + b;
  16. }
  17. }
  18. var c =newCalc();
  19. console.log(c.add(4,5));
  20. </script>

注意,script标签的type属性的值是module(或者traceur),而不是text/javascript。这是Traceur编译器识别ES6代码的标识,编译器会自动将所有type=module的代码编译为ES5,然后再交给浏览器执行。

2.新增关键字

(1)let是ES6中新增关键字。它的作用类似于var,用来声明变量,但是所声明的变量,只在let命令所在的代码块内有效。

(2)const 声明的是常量,一旦声明,值将是不可变的。const 的特点:

  • 具有块级作用域
  • 不能变量提升(必须先声明后使用)
  • 不可重复声明
  • const 指令指向变量所在的地址,所以对该变量进行属性设置是可行的(未改变变量地址),如果想完全不可变化(包括属性),那么可以使用冻结Object.freeze

3.新增方法

(1)是否包含字符串

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
    这三个方法都支持第二个参数,表示开始搜索的位置。endsWith 的行为与其他两个方法有所不同,它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。

(2)重复字符串repeat()

repeat()返回一个新字符串,表示将原字符串重复n次。

(3)模版字符串

模板字符中,支持字符串插值:

   
   
   
   
  1. let first ='world';
  2. let last='中国';
  3. document.write(`Hello ${first} ${last}!`);
  4. // Hello world 中国!

(4)String.row()

若使用String.raw 作为模板字符串的前缀,则模板字符串可以是原始(raw)的。反斜线也不再是特殊字符,\n 也不会被解释成换行符:

   
   
   
   
  1. let raw =String.raw`Not a newline: \n`;
  2. document.write(raw ==='Not a newline: \\n');// true

(5)isFinite(),isNaN(),isInteger()

在Number对象上,新提供了Number.isFinite()Number.isNaN()两个方法,用来检查InfiniteNaN这两个特殊值

Number.isInteger()用来判断一个值是否为整数。需要注意的是,在JavaScript内部,整数浮点数是同样的储存方法,所以3和3.0被视为同一个值。

(6)Math对象新增方法

  • Math.trunc():去除一个数的小数部分,返回整数部分
  • Math.sign():判断一个数到底是正数、负数、还是零。它返回五种值:参数为正数,返回+1;参数为负数,返回-1;参数为0,返回0;参数为-0,返回-0;其他值,返回NaN

  • Math.cbrt:计算一个数的立方根
  • Math.fround:返回一个数的单精度浮点数形式
  • Math.hypot:返回所有参数的平方和的平方根。
  • Math.expm1(x):返回ex - 1。
  • Math.log1p(x):返回1 + x的自然对数。如果x小于-1,返回NaN。
  • Math.log10(x):返回以10为底的x的对数。如果x小于0,则返回NaN。
  • Math.log2(x):返回以2为底的x的对数。如果x小于0,则返回NaN
4.数组方法
(1).Array.from方法用于将两类对象转为真正的数组:类数组对象可遍历的对象(包括ES6新增的数据结构Set和Map).任何有length属性的对象,都可以通过Array.from方法转为数组
  1. let array =Array.from({0:"a",1:"b",2:"c", length:3});
  2. document.write(array);// [ "a", "b" , "c" ]
(2).Array.of方法用于将一组值,转换为数组。这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。只有当参数个数不少于2个,Array()才会返回由参数组成的新数组。
  1. Array(3)// [undefined, undefined, undefined]
  2. Array.of(3)// [3]
  3. Array.of(3).length // 1
(3).find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined
findIndex方法,用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。
  1. let array =[1,5,10,15].find(function(value, index, arr){
  2. return value >9;
  3. })
  4. document.write(array);// 10
(4).fill()使用给定值,填充一个数组。 fill 方法用于空数组的初始化非常方便。但是如果数组中已有元素,会被全部抹去。 fill()还可以接受第二个和第三个参数,用于指定填充的 起始位置 结束位置
(5).遍历数组新方法,它们都返回一个遍历器,可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
  • entries()
  • keys()
  • values()
  1. for(let index of ['a','b'].keys()){
  2. document.write(index);//0,1
  3. }
  4. for(let elem of ['a','b'].values()){
  5. document.write(elem);//'a','b'
  6. }
  7. for(let [index, elem] of ['a','b'].entries()){
  8. document.write(index, elem);//0a,1b
  9. }
5.对象
ES6允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内。
(1).Object.is()用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
(2).Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。只要有一个参数不是对象,就会抛出TypeError错误。
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
  1. var target={name:'张三'}
  2. var source={age:'19',sex:'男'}
  3. Object.assign(target, source1, source2); {"name":"张三","age":"19","sex":"男"}
(3).ES6引入了一种新的原始数据类型Symbol,表示独一无二的ID。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象

Symbol类型的值不能与其他类型的值进行运算,会报错。但是,Symbol类型的值可以转为字符串。

(4). Proxy 内置的一个代理工具,使用他可以在对象处理上加一层屏障, new Proxy() 表示生成一个Proxy实例,它的target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。
  1. var proxy =newProxy(target, handler)
6.函数
(1)函数绑定函数绑定运算符是并排的两个双引号(::),双引号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
  1. let log =::console.log;
  2. // 等同于var log = console.log.bind(console);
  3. foo::bar;
  4. // 等同于bar.call(foo);
  5. foo::bar(...arguments);
  6. // 等同于bar.apply(foo, arguments);
(2).箭头函数是使用=>语法的函数简写形式。同时支持表达式体语句体。与(普通的)函数所不同的是,箭头函数和其上下文中的代码共享同一个具有词法作用域的this
var array = [1, 2, 3];//传统写法
array.forEach(function(v, i, a) {console.log(v);});
//ES6
array.forEach(v = > console.log(v));
    箭头函数使用时应注意:
  • 函数体内的this对象,绑定定义时所在的对象,而不是使用时所在的对象。
  • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
  • 不可以使用arguments对象,该对象在函数体内不存在。

上面三点中,第一点尤其值得注意。this对象的指向是可变的,但是在箭头函数中,它是固定的。

(3).尾调用优化尾调用是指某个函数的最后一步是调用另一个函数。尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用记录,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。“尾调用优化”Tail call optimization),即只保留内层函数的调用帧,这样可以节省内存。
7.Set
数据结构Set类似于数组,但是成员的值都是唯一的,没有重复的值,Set函数可以接受一个数组作为参数,用来初始化向Set加入值的时候,不会发生类型转换,所以5“5”是两个不同的值.

(1).Set结构实例的属性:

  • Set.prototype.constructor:构造函数,默认就是Set函数。
  • Set.prototype.size:返回Set实例的成员总数。

(2).操作方法:

  • add(value):添加某个值,返回Set结构本身。
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否为Set的成员。
  • clear():清除所有成员,没有返回值。

(3).遍历方法:

  • keys():返回一个键名的遍历器
  • values():返回一个键值的遍历器
  • entries():返回一个键值对的遍历器
  • forEach():使用回调函数遍历每个成员
  1. let set=newSet(['red','green','blue']);
  2. for( let item of set.keys()){
  3. document.write(item);
  4. }
  5. for( let item of set.values()){
  6. document.write(item);
  7. }
  8. for( let item of set.entries()){
  9. document.write(item);
  10. }//["red", "red"]["green", "green"]["blue", "blue"]
  11. set.forEach(function(item){
  12. document.write(item);
  13. })

8.Map

Map 是一个“超对象”,其 key 除了可以是 String 类型之外,还可以为其他类型(如:对象),他的方法和 Set 差不多:

  • size:返回成员总数。
  • set(key, value):设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
  • get(key):读取key对应的键值,如果找不到key,返回undefined
  • has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
  • delete(key):删除某个键,返回true。如果删除失败,返回false。
  • clear():清除所有成员。
  • keys():返回键名的遍历器。
  • values():返回键值的遍历器。
  • entries():返回所有成员的遍历器。

9.Iterator遍历器

遍历器(Iterator就是统一的接口机制,来处理所有不同的数据结构。

Iterator的作用有三个:一是为各种数据结构,提供一个统一的简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。

Iterator的遍历过程

  • 创建一个指针,指向当前数据结构的起始位置。也就是说,遍历器的返回值是一个指针对象。
  • 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
  • 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
  • 调用指针对象的next方法,直到它指向数据结构的结束位置。

每一次调用next方法,都会返回当前成员的信息,具体来说,就是返回一个包含valuedone两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。

遍历器返回的指针对象除了具有next方法,还可以具有return方法和throw方法。其中,next方法是必须部署的,return方法和throw方法是否部署是可选的

return方法的使用场合是,如果for...of循环提前退出(通常是因为出错,或者有break语句或continue语句),就会调用return方法。如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return方法。

throw方法主要是配合Generator函数使用,一般的遍历器用不到这个方法。

10.Generator

Generator函数是一个函数的内部状态的遍历器(也就是说,Generator函数是一个状态机)。形式上,Generator函数是一个普通函数,但是有两个特征。

  • 一是,function命令与函数名之间有一个星号*
  • 二是,函数体内部使用yield语句,定义遍历器的每个成员,即不同的内部状态。
  1. function* helloWorldGenerator(){
  2. yield'hello';
  3. yield'world';
  4. return'ending';
  5. }
  6. var hw = helloWorldGenerator();
  7. hw.next()// { value: 'hello', done: false }
  8. hw.next()// { value: 'world', done: false }
  9. hw.next()// { value: 'ending', done: true }
  10. hw.next()// { value: undefined, done: true }

        总结一下,调用Generator函数,返回一个部署了Iterator接口的遍历器对象,用来操作内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着valuedone两个属性的对象。value属性表示当前的内部状态的值,是yield语句后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

    yield语句本身没有返回值,或者说总是返回undefinednext方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。

        for...of循环可以自动遍历Generator函数,且此时不再需要调用next方法。注意:一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象,所以return语句返回的对象,不包括在for...of循环之中。

    Generator 函数内部还可以部署错误处理代码,捕获函数体外抛出的错误。使用指针对象的 throw 方法抛出的错误,可以被函数体内的 try ... catch 代码块捕获。这意味着,出错的代码与处理错误的代码,实现了时间和空间上的分离,这对于异步编程无疑是很重要的。

11.Promise

所谓Promise,就是一个对象,用来传递异步操作的消息。

Promise对象有以下两个特点:

  • 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:Pending变为Resolved和从Pending变为Rejected只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

        有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

Promise也有一些缺点:

  • 首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。
  • 其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
  • 第三,当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

Promise对象是一个构造函数,用来生成Promise实例

    
    
    
    
  1. //创建promise
  2. var promise =newPromise(function(resolve, reject){
  3. // 进行一些异步或耗时操作
  4. if(/*如果成功 */){
  5. resolve("Stuff worked!");
  6. }else{
  7. reject(Error("It broke"));
  8. }
  9. });
  10. //绑定处理程序
  11. promise.then(function(result){
  12. //promise成功的话会执行这里
  13. document.write(result);// "Stuff worked!"
  14. },function(err){
  15. //promise失败会执行这里
  16. document.write(err);// Error: "It broke"
  17. });
  • resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
  • reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise实例具有then方法,也就是说,then方法是定义在原型对象,作用是为Promise实例添加状态改变时的回调函数。

then方法两个参数:

  • Resolved状态的回调函数;
  • Rejected状态的回调函数(可选)。

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

    
    
    
    
  1. getJSON("/posts.json").then(function(json){
  2. return json.post;
  3. }).then(function(post){
  4. // ...
  5. });

上面的代码使用then方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。

Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。

    
    
    
    
  1. getJSON("/posts.json").then(function(posts){
  2. // ...
  3. }).catch(function(error){
  4. // 处理前一个回调函数运行时发生的错误
  5. document.write('发生错误!', error);
  6. });

getJSON方法返回一个Promise对象,如果该对象状态变为Resolved,则会调用then方法指定的回调函数;如果异步操作抛出错误,状态就会变为Rejected,就会调用catch方法指定的回调函数,处理这个错误。

    
    
    
    
  1. var promise =newPromise(function(resolve, reject){
  2. thrownewError('test')
  3. });
  4. promise.catch(function(error){ document.write(error)});
  5. // Error: test

上面代码中,Promise抛出一个错误,就被catch方法指定的回调函数捕获。

Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

    
    
    
    
  1. getJSON("/post/1.json").then(function(post){
  2. return getJSON(post.commentURL);
  3. }).then(function(comments){
  4. // some code
  5. }).catch(function(error){
  6. // 处理前面三个Promise产生的错误
  7. });

上面代码中,一共有三个Promise对象:一个由getJSON产生,两个由then产生。它们之中任何一个抛出的错误,都会被最后一个catch捕获。

Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。

    
    
    
    
  1. var p =Promise.all([p1,p2,p3]);

上面代码中,Promise.all方法接受一个数组作为参数,p1、p2、p3都是Promise对象的实例。(Promise.all方法的参数不一定是数组,但是必须具有iterator接口,且返回的每个成员都是Promise实例。)

p的状态由p1、p2、p3决定,分成两种情况。

  • 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
  • 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例。

    
    
    
    
  1. var p =Promise.race([p1,p2,p3]);

上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的回调函数。

如果Promise.all方法和Promise.race方法的参数,不是Promise实例,就会先调用Promise.resolve方法,将现有对象转为Promise对象,如果Promise.resolve方法的参数,不是具有then方法的对象(又称thenable对象),则返回一个新的Promise对象,且它的状态为Resolved

    
    
    
    
  1. var p =Promise.resolve('Hello');
  2. p.then(function(s){
  3. document.write(s)
  4. });
  5. // Hello

由于字符串Hello不属于异步操作(判断方法是它不是具有then方法的对象),返回Promise实例的状态从一生成就是Resolved,所以回调函数会立即执行。

Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。

    
    
    
    
  1. var p =Promise.reject('出错了');
  2. p.then(null,function(s){
  3. document.write(s)
  4. });// 出错了

上面代码生成一个Promise对象的实例p,状态为rejected,回调函数会立即执行

12.Generator函数与Promise结合

使用Generator函数管理流程,遇到异步操作的时候,通常返回一个Promise对象

    
    
    
    
  1. function getFoo (){
  2. returnnewPromise(function(resolve, reject){
  3. resolve('foo');
  4. });
  5. }
  6. var g =function*(){
  7. try{
  8. var foo =yield getFoo();
  9. document.write(foo);
  10. }catch(e){
  11. document.write(e);
  12. }
  13. };
  14. function run (generator){
  15. var it = generator();
  16. function go(result){
  17. if(result.done)return result.value;
  18.  
  19. return result.value.then(function(value){
  20. return go(it.next(value));
  21. },function(error){
  22. return go(it.throw(value));
  23. });
  24. }
  25. go(it.next());
  26. }
  27. run(g);

上面代码的Generator函数g之中,有一个异步操作getFoo,它返回的就是一个Promise对象。函数run用来处理这个Promise对象,并调用下一个next方法。

13.Class

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

    
    
    
    
  1. //定义类
  2. classPoint{
  3. constructor(x, y){
  4. this.x = x;
  5. this.y = y;
  6. }
  7. toString(){
  8. return'('+this.x+', '+this.y+')';
  9. }
  10. }

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

constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。

(1).class的继承

Class之间可以通过extends关键字,实现继承。子类会继承父类的属性和方法。

    
    
    
    
  1. classColorPointextendsPoint{
  2. constructor(x, y, color){
  3. this.color = color;// ReferenceError
  4. super(x, y);
  5. this.color = color;// 正确
  6. }
  7. }

注意:ColorPoint继承了父类Point,但是它的构造函数必须调用super方法,super方法必须放在第一行。

在Class内部可以使用getset关键字,对某个属性设置存值函数和取值函数。

(2).class的静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。父类的静态方法,可以被子类继承。

  1. classFoo{
  2. static classMethod(){
  3. return'hello';
  4. }
  5. }
  6. Foo.classMethod()// 'hello'
  7. var foo =newFoo();
  8. foo.classMethod()
  9. // TypeError: undefined is not a function

(3).new.target属性

new是从构造函数生成实例的命令。ES6为new命令引入了一个new.target属性,(在构造函数中)返回new命令作用于的那个构造函数。如果构造函数不是通过new命令调用的,new.target会返回undefined,因此这个属性可以用来确定构造函数是怎么调用的。

  • Class内部调用new.target,返回当前Class。
  • 子类继承父类时,new.target会返回子类。

(4).修饰器

修饰器(Decorator)是一个表达式,用来修改类的行为。这是ES7的一个提案,目前Babel转码器已经支持。修饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,修饰器能在编译阶段运行代码。

    
    
    
    
  1. function testable(target){
  2. target.isTestable =true;
  3. }
  4. @testable
  5. classMyTestableClass{}
  6. console.log(MyTestableClass.isTestable)// true

上面代码中,@testable就是一个修饰器。它修改了MyTestableClass这个类的行为,为它加上了静态属性isTestable

基本上,修饰器的行为就是下面这样。

    
    
    
    
  1. @decorator
  2. class A {}
  3. // 等同于
  4. class A {}
  5. A = decorator(A)|| A;

修饰器函数可以接受三个参数,依次是目标函数属性名该属性的描述对象。后两个参数可省略。testable函数的参数target,就是所要修饰的对象。如果希望修饰器的行为,能够根据目标对象的不同而不同,就要在外面再封装一层函数。

    
    
    
    
  1. function testable(isTestable){
  2. returnfunction(target){
  3. target.isTestable = isTestable;
  4. }
  5. }
  6. @testable(true)classMyTestableClass(){}
  7. document.write(MyTestableClass.isTestable)// true
  8.  
  9. @testable(false)classMyClass(){}
  10. document.write(MyClass.isTestable)// false

如果想要为类的实例添加方法,可以在修饰器函数中,为目标类的prototype属性添加方法。

    
    
    
    
  1. function testable(target){
  2. target.prototype.isTestable =true;
  3. }
  4. @testable
  5. classMyTestableClass(){}
  6.  
  7. let obj =newMyClass();
  8.  
  9. document.write(obj.isTestable)// true

14.模块(module)

模块功能主要由两个命令构成:exportimport

  • export命令用于用户自定义模块,规定对外接口;
  • import命令用于输入其他模块提供的功能,同时创造命名空间(namespace),防止函数名冲突。

ES6允许将独立的JS文件作为模块,允许一个JavaScript脚本文件调用另一个脚本文件。ES6支持多重加载,即所加载的模块中又加载其他模块。

  1. // profile.js
  2. var firstName ='Michael';
  3. var lastName ='Jackson';
  4. var year =1958;
  5. export{firstName, lastName, year};

  6. // main.js
  7. import{firstName, lastName, year}from'./profile';
  8.  
  9. function sfirsetHeader(element){
  10. element.textContent = firstName +' '+ lastName;
  11. }

import命令接受一个对象(用大括号表示),里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

module命令可以取代import语句,达到整体输入模块的作用。module命令后面跟一个变量,表示输入的模块定义在该变量上。

  1. module profile from './profile';

为加载模块指定默认输出,使用export default命令。其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

  1. // export-default.js
  2. exportdefaultfunction(){
  3. document.write('foo');
  4. }
  5. // import-default.js
  6. import customName from'./export-default';
  7. customName();// 'foo'

上面代码的import命令,可以用任意名称指向export-default.js输出的方法。需要注意的是,这时import命令后面,不使用大括号。

你可能感兴趣的:(Promise,ECMAScript,Traceur,6,ES6,ES6新特性)