博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6中var let const的区别以及箭头函数
阅读量:5832 次
发布时间:2019-06-18

本文共 3610 字,大约阅读时间需要 12 分钟。

  hot3.png

1. var let const的区别

随着ES6规范的到来,Js中定义变量的方法已经由单一的 var 方式发展到了 var、let、const 三种之多。

下文来讨论下这三种方式的区别

1.1 Js没有块级作用域

请看这样一条规则:在JS函数中的var声明,其是函数体的全部

for(var i=0;i<10;i++){     var a = 'a';}console.log(a);

跳出了循环的变量a和i,在循环外能被访问到。

首先解释一下变量提升:

JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。

这就导致了var声明的变量没有块级作用域。

1.2 循环内变量过度共享

for (var i = 0; i < 3; i++) {    setTimeout(function () {      console.log(i)    }, 1000);}

输出结果为3,3,3而不是0,1,2。循环本身及三次 timeout 回调均共享唯一的变量 i 。当循环结束执行时,i 的值为3。所以当第一个 timeout 执行时,调用的 i 当让也为 3 了。

1.3 let与const

ES6中let解决了上面var的问题,其特点概括如下:

  • let声明的变量拥有块级作用域。 也就是说用let声明的变量的作用域只是外层块,而不是整个外层函数。let 声明仍然保留了提升特性,但不会盲目提升,在示例一中,通过将var替换为let可以快速修复问题,如果你处处使用let进行声明,就不会遇到类似的bug。
  • let声明的全局变量不是全局对象的属性。这就意味着,你不可以通过window.变量名的方式访问这些变量。它们只存在于一个不可见的块的作用域中,这个块理论上是Web页面中运行的所有JS代码的外层块。
  • 形如for (let x...)的循环在每次迭代时都为x创建新的绑定。
    这是一个非常微妙的区别,拿示例二来说,如果一个for (let...)循环执行多次并且循环保持了一个闭包,那么每个闭包将捕捉一个循环变量的不同值作为副本,而不是所有闭包都捕捉循环变量的同一个值。
    所以示例二中,也以通过将var替换为let修复bug。
    这种情况适用于现有的三种循环方式:for-of、for-in、以及传统的用分号分隔的类C循环。
  • 用let重定义变量会抛出一个语法错误(SyntaxError)。这个很好理解,用代码说话
    let a = 'a';let a = 'b';
    上述写法是不允许的,浏览器会报错,因为重复定义了。

const更好理解,可以想象成Java中的final(不过,const 关键字并不会限制对 object 的修改),这里不多做阐述了。

经验阐述:能用 const 尽量用 const,不要轻易的 mutate object,代码结构复杂后会有好处。

2. 箭头函数

ES6标准新增了一种新的函数:Arrow Function(箭头函数)。

x => x * x

上面的箭头函数相当于:

function (x) {    return x * x;}

箭头函数相当于匿名函数(

(function(){...})();

),并且简化了函数定义。箭头函数有两种格式,一种像上面的,只包含一个表达式,连{ ... }return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ ... }return

x => {    if (x > 0) {        return x * x;    }    else {        return - x * x;    }}

如果参数不是一个,就需要用括号()括起来:

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

如果要返回一个对象,就要注意,如果是单表达式,这么写的话会报错:

// SyntaxError:x => { foo: x }

因为和函数体的{ ... }有语法冲突,所以要改为:

// ok:x => ({ foo: x })

2.1 this

箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,由上下文确定。

回顾前面的例子,由于JavaScript函数对this绑定的错误处理,下面的例子无法得到预期结果:

var obj = {    birth: 1990,    getAge: function () {        var b = this.birth; // 1990        var fn = function () {            return new Date().getFullYear() - this.birth; // this指向window或undefined        };        return fn();    }};

现在,箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj

var obj = {    birth: 1990,    getAge: function () {        var b = this.birth; // 1990        var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象        return fn();    }};obj.getAge(); // 25

如果使用箭头函数,以前的那种hack写法:

var that = this;

就不再需要了。

由于this在箭头函数中已经按照词法作用域绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略:

var obj = {    birth: 1990,    getAge: function (year) {        var b = this.birth; // 1990        var fn = (y) => y - this.birth; // this.birth仍是1990        return fn.call({birth:2000}, year);    }};obj.getAge(2015); // 25

3. call & apply

call和apply作用很相似,函数执行时,在某个指定作用域下调用。只是参数的写法不同,

call(this,arg1,arg2..)apply(this.argunments)

比如

obj1.method1.call(obj2,argument1,argument2)

call的作用就是把obj1的方法放到obj2上使用,后面的argument1..这些做为参数传入。 

function add(a,b) {     alert(a+b); } function sub(a,b) {     alert(a-b); } add.call(sub,3,1);

上述代码的意思就是用add来替换sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4); // 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。 

 

 

Reference:

1. http://www.jianshu.com/p/4e9cd99ecbf5

2. http://www.cnblogs.com/52fhy/p/5117267.html

3. https://www.zhihu.com/question/34294629?sort=created

4. http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001438565969057627e5435793645b7acaee3b6869d1374000

5. http://www.cnblogs.com/sweting/archive/2009/12/21/1629204.html

转载于:https://my.oschina.net/hosee/blog/906960

你可能感兴趣的文章
被需求搞的一塌糊涂,怎么办?
查看>>
c_数据结构_队的实现
查看>>
jquery 选择器总结
查看>>
Qt设置背景图片
查看>>
【阿里云文档】常用文档整理
查看>>
java中的Volatile关键字
查看>>
前端自定义图标
查看>>
实验二
查看>>
独立开发一个云(PaaS)的核心要素, Go, Go, Go!!!
查看>>
MyBatis使用DEMO及cache的使用心得
查看>>
网站文章如何能自动判定是抄袭?一种算法和实践架构剖析
查看>>
【OpenCV学习】滚动条
查看>>
ofo用科技引领行业进入4.0时代 用户粘性连续8个月远甩摩拜
查看>>
兰州青年志愿者“中西合璧”玩快闪 温暖旅客回家路
查看>>
计划10年建10万廉价屋 新西兰政府:比想象中难
查看>>
甘肃发首版《3D打印职业教育教材》:校企合作育专才
查看>>
李娜入选国际网球名人堂 成亚洲第一人
查看>>
为找好心人抚养孩子 浙江一离婚父亲将幼童丢弃公园
查看>>
晚婚晚育 近20年巴西35岁以上孕妇增加65%
查看>>
读书:为了那个美妙的咔哒声
查看>>