本文作者:IMWeb 朱灵子 原文出处:IMWeb社区 未经同意,禁止转载
Es6浅析
Babel 是一个 JavaScript编译器,它可以把我们编写的符合 ECMAScript 6 标准的代码完美地转换为 ECMAScript 5 标准的代码,并且可以确保转换后的语言良好地运行在所有主流 JavaScript引擎中。我们可以把babel简单地理解为从源代码到源代码的编译器。
以下是ES6新特性在Babel下的兼容性列表
今天我就使用babel编译器这个强大的工具来理解Es6的一些语法,主要从以下几个方面的对比来进行理解:
- Let、const与var
- 箭头函数与普通函数
- 原型方法静态方法
let、const与var
使用babel编译工具我们发现let const编译以后都变成了var,那他们和var到底有哪些方面的区别呢?
我们通过几个小小的栗子来进行区别,首先请看这段es5代码:
代码语言:javascript复制function testLet(){
var i=1;
console.log(i);
console.log(j);
var j=2;
}
testLet();
console.log(i);
使用es5的语法第一个console输出的是1,第二个输出是undefine,第三个输出1
接下来请看使用es6语法编译后的代码:
代码语言:javascript复制function testLet(){
let i=1;
console.log(i);
console.log(j);
let j=2;
}
testLet();
console.log(i);
代码执行完后,我们会发现第一个仍然输出1,但是第二个和第三个产生了ReferenceError的错误。
通过对比这两个小例子我们发现let的作用域比var更加严格了,有点类似于java中的变量定义
- 必须先定义再使用
- 有着严格的作用域,变量只作用域当前隶属的代码块
下面我们通过babel来理解let的块级作用域
代码语言:javascript复制let a1 = 1;
{
let a1 = 2;
{
let a1 = 3;
}
}
a1 = 4;
这段代码我们使用Babel编译以后变成了
代码语言:javascript复制var a1 = 1;
{
var _a = 2;
{
var _a2 = 3;
}
}
a1 = 4;
通过对比这两个例子我们可以发现let块级作用域的实质就是改变一下变量名,使变量名与外层不同。
那const关键字又如何理解呢?
const代表一个值的常量索引,也就是说变量名字在内存中的指针不能够改变,但是指向这个变量的值可能改变。
下面举一个简单的小例子:
代码语言:javascript复制const testConst=[] ;
testConst.push(“1”) ;
console.log (testConst) ;
我们创建了一个拥有常量索引的数组变量,然后添加值到这个数组中,但并不改变它的索引,所以上面的代码可以运行。
代码语言:javascript复制const testConst= [ ] ;
testConst=[];
在上面的例子中我们想修改索引到一个新的数组,所以会报出TypeError的错误。
箭头函数与普通函数
箭头函数相当于匿名函数,并且简化了函数定义。 箭头函数有两种格式,一种只包含一个表达式,连{ ... }和return都省略掉了,另外一种可以包含多条语句,这时候就不能省略{ ... }和return。箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别,那就是箭头函数内部的this是词法作用域,由上下文确定。
下面我们通过一个简单的小栗子来进行理解哦~
代码语言:javascript复制var testObj = {
prop: 1,
func: function() {
var innerFunc = () => {
this.prop = 1;
};
var innerFunc1 = function() {
this.prop = 1;
};
},
};
这段小代码我们通过babel进行编译以后如下所示
代码语言:javascript复制var testObj = {
prop: 1,
func: function func() {
var _this = this;
var innerFunc = function innerFunc() {
_this.prop = 1;
};
var innerFunc1 = function innerFunc1() {
this.prop = 1;
};
}
};
对比箭头函数与普通函数定义的方法编译后函数内this的指向,我们就可以发现剪头函数可以让我们直接使用外层的this而不用担心context切换的问题。
原型方法与静态方法;
ES6中定义类是这样的方式:首先定义一个class,每一个使用class方式定义的类默认都有一个constructor函数, 这个函数是构造函数的主函数,该函数体内部的this指向生成的实例, 我们可以在这个类上定义我们的原型方法与静态方法。
那这两者有什么区别呢?我们举一个简单的栗子来进行区分
代码语言:javascript复制class testStaticfunc {
constructor(name) {
this.name = name;
}
sayHi () {
console.log("say hi");
}
static sayHello () {
console.log("say hello");
}
};
在这里我们定义了一个类testStaticfunc,并在这个类上面定义了一个原型方法sayHi以及静态方法sayHello ,我们将这段代码使用babel进行编译,编译以后的结果如下所示:
代码语言:javascript复制var testStaticfunc = function () {
function testStaticfunc(name) {
_classCallCheck(this, testStaticfunc);
this.name = name;
}
testStaticfunc.prototype.sayHi = function sayHi() {
console.log("say hi");
};
testStaticfunc.sayHello = function sayHello() {
console.log("say hello");
};
return testStaticfunc;
}();
我们可以这样调用原型方法
代码语言:javascript复制var instance = new testStaticfunc ();
instance.sayHi ()
但是我们可以直接这样调用静态方法
代码语言:javascript复制testStaticfunc.sayHello ()
调用静态方法我们不需要再new一个实例,可以直接调用方法,因此静态方法一般用来提供一些工具方法。
参考资料
- https://github.com/lcxfs1991/blog/issues/9