Babel中的stage-0,stage-1,stage-2以及stage-3

大家知道,将ES6代码编译为ES5时,我们常用到Babel这个编译工具。大家参考一些网上的文章或者官方文档,里面常会建议大家在.babelrc中输入如下代码:

{
    "presets": [
      "es2015",
      "react",
      "stage-0"
    ],
    "plugins": []
  }

我们现在来说明下这个配置文件是什么意思。首先,这个配置文件是针对babel 6的。Babel 6做了一系列模块化,不像Babel 5一样把所有的内容都加载。比如需要编译ES6,我们需要设置presets为"es2015",也就是预先加载es6编译的相关模块,如果需要编译jsx,需要预先加载"react"这个模块。那问题来了,这个"stage-0"又代表什么呢? 有了"react-0",是否又有诸如"stage-1", "stage-2"等等呢?

事实上, ”stage-0"是对ES7一些提案的支持,Babel通过插件的方式引入,让Babel可以编译ES7代码。当然由于ES7没有定下来,所以这些功能随时肯能被废弃掉的。现在我们来一一分析里面都有什么。

1. 法力无边的stage-0

为什么说“stage-0” 法力无边呢,因为它包含stage-1, stage-2以及stage-3的所有功能,同时还另外支持如下两个功能插件:

用过React的同学可能知道,jsx对条件表达式支持的不是太好,你不能很方便的使用if/else表达式,要么你使用三元表达,要么用函数。例如你不能写如下的代码:

var App = React.createClass({

    render(){
        let { color } = this.props;

        return (
            <div className="parents">
                {
                    if(color == ‘blue‘) {
                        <BlueComponent/>;
                    }else if(color == ‘red‘) {
                        <RedComponent/>;
                    }else {
                        <GreenComponent/>; }
                    }
                }
            </div>
        )
    }
})

在React中你只能写成这样:

var App = React.createClass({

    render(){
        let { color } = this.props;

        const getColoredComponent = color => {
            if(color === ‘blue‘) { return <BlueComponent/>; }
            if(color === ‘red‘) { return <RedComponent/>; }
            if(color === ‘green‘) { return <GreenComponent/>; }
        }

        return (
            <div className="parents">
                { getColoredComponent(color) }
            </div>
        )
    }
})

transform-do-expressions 这个插件就是为了方便在 jsx写if/else表达式而提出的,我们可以重写下代码。

var App = React.createClass({

    render(){
        let { color } = this.props;

        return (
            <div className="parents">
                {do {
                    if(color == ‘blue‘) {
                        <BlueComponent/>;
                    }else if(color == ‘red‘) {
                        <RedComponent/>;
                    }else {
                        <GreenComponent/>; }
                    }
                }}
            </div>
        )
    }
})

再说说 transform-function-bind, 这个插件其实就是提供过 :: 这个操作符来方便快速切换上下文, 如下面的代码:

obj::func
// is equivalent to:
func.bind(obj)

obj::func(val)
// is equivalent to:
func.call(obj, val)

::obj.func(val)
// is equivalent to:
func.call(obj, val)

// 再来一个复杂点的样例

const box = {
  weight: 2,
  getWeight() { return this.weight; },
};

const { getWeight } = box;

console.log(box.getWeight()); // prints ‘2‘

const bigBox = { weight: 10 };
console.log(bigBox::getWeight()); // prints ‘10‘

// Can be chained:
function add(val) { return this + val; }

console.log(bigBox::getWeight()::add(5)); // prints ‘15‘

如果想更屌点,还可以写出更牛逼的代码:

const { map, filter } = Array.prototype;

let sslUrls = document.querySelectorAll(‘a‘)
                ::map(node => node.href)
                ::filter(href => href.substring(0, 5) === ‘https‘);

console.log(sslUrls);

2. 包罗万象的stage-1

stage-1除了包含stage-2和stage-3,还包含了下面4个插件:

今天就到这里了,改天我们接着分析下"stage-2"和"stage-3", 它们又有什么新的特性呢,让我们拭目以待吧。

深藏不露的stage-2

为什么说 stage-2深藏不露呢,因为它很低调,低调到你可以忽略它,但事实上,它很有内涵的。它除了覆盖stage-3的所有功能,还支持如下两个插件:

syntax-trailing-function-commas

这个插件让人一看觉得挺没趣的,让人甚至觉得它有点鸡肋。因它不是对ES6功能的增加,而是为了增强代码的可读性和可修改性而提出的。如下面的代码所示:


// 假设有如下的一个函数,它有两个参数
function clownPuppiesEverywhere(
  param1,
  param2
) { /* ... */ }

clownPuppiesEverywhere(
  ‘foo‘,
  ‘bar‘
);

// 有一天,它需要变成3个参数,你需要这样修改
function clownPuppiesEverywhere(
  param1,
- param2
+ param2, // 这一行得加一个逗号
+ param3  // 增加参数param3
) { /* ... */ }

clownPuppiesEverywhere(
  ‘foo‘,
- ‘bar‘
+ ‘bar‘, // 这里的修改为逗号
+ ‘baz‘  // 增加新的参数
);

// 看到没? 我们修改了4行代码。。啊啊。修改了4行代码。

修改了4行代码,嗯嗯嗯。。追求高效的程序猿想想了,以后如果有更多参数了,我是不是要改等多行,得想想,代码改的越少越好,于是有了下面的改动。。


// 我们来重新定义一下函数
function clownPuppiesEverywhere(
  param1,
  param2, // 注意这里,我们加了一个逗号哟
) { /* ... */ }

clownPuppiesEverywhere(
  ‘foo‘,
  ‘bar‘, // 这里我们也加了一个逗号
);

// 现在函数需要三个参数,我们来修改下
function clownPuppiesEverywhere(
  param1,
  param2,
+ param3, // 增加params3参数
) { /* ... */ }

clownPuppiesEverywhere(
  ‘foo‘,
  ‘bar‘,
+ ‘baz‘, // 增加第三个参数
);

// 叮叮当,我们只修改了两行代码就完成了,好开森

说实话吧,这个功能让人有点很无语。不过程序猿对干净代码的追求真的很让人感动,还是值得鼓励的。这个就是stage-2中"尾逗号函数”功能。哈哈哈哈。

transform-object-rest-spread

再来说transform-object-rest-spread, 其实它是对 ES6中解构赋值的一个扩展,因为ES6只支持对数组的解构赋值,对对象是不支持的。如下面的代码所示:

// 获取剩下的属性

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

// 属性展开
let n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }

大放异彩的stage3

为啥说stage3大放异彩呢?因为它支持大名鼎鼎的asyncawait, 这两个哥们可是解决(Ajax)回调函数的终极解决方法呀!管你什么异步,我都可以用同步的思维来写,ES7里面非常强悍的存在。总的来说,它包含如下两个插件:

transform-async-to-generator

transform-async-to-generator主要用来支持ES7中的asyncawait, 我们可以写出下面的代码:

const sleep = (timeout)=>{
    return new Promise( (resolve, reject)=>{
        setTimeout(resolve, timeout)
    })
}

(async ()=>{
    console.time("async");
    await sleep(3000);
    console.timeEnd("async");
})()

再来一个实际点的例子

const fetchUsers = (user)=>{
    return window.fetch(`https://api.douban.com/v2/user/${user}`).then( res=>res.json())
}

const getUser = async (user) =>{
    let users = await fetchUsers(user);
    console.log( users);
}

console.log( getUser("flyingzl"))

提示: 由于asycnawait是ES7里面的内容,现阶段不建议使用。为了顺利运行上面的代码,建议用webpack进行编译。

transform-exponentiation-operator

transform-exponentiation-operator这个插件算是一个语法糖,可以通过**这个符号来进行幂操作,想当于Math.pow(a,b)。如下面的样例


// x ** y

let squared = 2 ** 2;
// 相当于: 2 * 2

let cubed = 2 ** 3;
// 相当于: 2 * 2 * 2

// x **= y

let a = 2;
a **= 2;
// 相当于: a = a * a;

let b = 3;
b **= 3;
// 相当于: b = b * b * b;

很简单也很实用吧,哈。使用起来还是蛮方便的。

总结

通过以上的两篇文章,我们了解了stage-0,state-1stage-2以及stage-3的区别。在进行实际开发时,可以更具需要来设置对应的stage。如果省事懒得折腾,一般设置为stage-0即可。如果为了防止开发人员使用某些太新的功能,我们可以限制到某个特定的stage即可。如果有其他问题,欢迎大家留言 :-)。 更详细的请参考https://babeljs.io/docs/plugins/preset-stage-0/

时间: 2024-10-25 00:45:00

Babel中的stage-0,stage-1,stage-2以及stage-3的相关文章

spark1.1.0源码阅读-dagscheduler and stage

1. rdd action ->sparkContext.runJob->dagscheduler.runJob 1 def runJob[T, U: ClassTag]( 2 rdd: RDD[T], 3 func: (TaskContext, Iterator[T]) => U, 4 partitions: Seq[Int], 5 callSite: String, 6 allowLocal: Boolean, 7 resultHandler: (Int, U) => Unit

java中Integer i1= 0; Integer i2= 0; 为什么可以用 == 符号呢

java中Integer i1= 0; Integer i2= 0;  有i1 == i2,且有i1 = 1;那么i2为什么不会变成1呢? 我这个时候的想法是:这是因为java中整型常量是基于int的,而java中有自动包装机制,也就是说看起来i1,i2是Integer类型,但是其底层还是基于int类型的(不能理解的话在java中还有一个地方那就是Arrays.asList(T...args) 他返回一个基于数组的List,如果在List中改变其大小,那么将会引发异常[UnsupportedOp

Light oj 1138 - Trailing Zeroes (III) 【二分查找 &amp;&amp; N!中末尾连续0的个数】

1138 - Trailing Zeroes (III) PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in decimal notation. As you know N! = 1*2*...*N. F

(转)C语言中长度为0的数组

前面在看Xen的源码时,遇到了一段代码,如下所示: 注意上面最后一行的代码,这里定义了一个长度为的数组,这种用法可以吗?为什么可以使用长度为0 的数组?长度为的数组到底怎么使用?……这篇文章主要针对该问题进行简单的讲解.废话不多说了,现在就开始. 长度为的数组在标准c和c++中是不允许的,如果使用长度为的数组,编译时会产生错误,提示数组长度不能为.但在GNUc中,这种用法却是合法的.它的最典型的用法就是位于数组中的最后一项,如上面所示,这样做主要是为了方便内存缓冲区的管理.如果你将上面的长度为的

如何在Delphi中调用VC6.0开发的COM

上次写了如何在VC6.0下对Delphi写的COM进行调用,原本想马上写如何在Delphi中调用VC6.0开发的COM时,由于在写事例程序中碰到了个很怪的问题,在我机子上用VC写的接口程序编译能通过.但是调用就会出现问题,(在VC下调用也是一样的出现).但是用Delphi写的接口程序编译后,不管是在VC下还是在Delphi下调用都没有问题.后来我把VC开发的接口程序编译后,拷贝到其它机子上试,怪事,完全没有问题了.总结后才知道是我机子有点问题.我到现在还没有解决为什么在我的机子上不行,在其它机子

MyEclipse—怎样在MyEclipse中创建servlet3.0

servlet3.0随着Java EE6规范一起公布,那么怎样在MyEclipse中创建3.0版的servlet呢? 1.启动MyEclipse.获得下图: 2.点击上图"File"工具栏.获得下图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ2FvaHVhbmppZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" widt

CentOS-6.4-minimal版中安装MongoDB-x86_64-3.0.2

/** * CentOS-6.4-minimal版中安装MongoDB-x86_64-3.0.2 * @see -------------------------------------------------------------------------------------------------------- * @see 安装MongoDB * @see [[email protected] ~]$ cd /app/software/ * @see [[email protected

【翻译自mos文章】V$BACKUP_DATAFILE 中显示file#=0 有损坏

来源于: V$BACKUP_DATAFILE Shows Corruptions for File #0 (文档 ID 399113.1) 适用于: Oracle Database - Enterprise Edition - Version 9.2.0.1 to 11.1.0.6 [Release 9.2 to 11.1] Information in this document applies to any platform. 症状: 当查询v$backup_datafile时,发现对于fi

Mysql中前边有0的数据,0会被舍去的问题

最近由于项目的需求,需要频繁地拉取不同数据库中的数据,拉取数据的过程中,各种问题,十分悲催,真所谓,一个疏忽,你就要被推倒重来... 在经历了无数次被推倒又站起来,然后又被推倒的艰苦奋斗历程之后,终于完成了数据的迁移.更新.同步.修复.总结一下这期间遇到的部分问题: 1.Mysql中前边有0的数据,0会被舍去的问题 如一条数据为0371xxx,存入数据库后数据变为371xxx (1)如果字段类型必须为int,可以修改字段,增加zero fill,alter table 表名称 modify 字段

60.编程统计数组a中正数、0、负数的个数

#include<iostream> using namespace std; int main() { int x=0,y=0,z=0; int a[10]; cout<<"please input 10 numbers:"<<endl; for(int i=0;i<10;i++) { cin>>a[i]; } for(int j=0;j<10;j++) { if(a[j]==0) { x++; } } for(int m=