Es6浅析

2019-12-04 17:05:18 浏览数 (1)

本文作者: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

0 人点赞