变量、闭包
变量
var
- var 可以重复声明
- 作用域:全局作用域 和 函数作用域
- 会进行预解析
let
- 统一作用域下不能重复声明
- 作用域:全局作用域 和 块级作用域
- 不进行预解析
let 和 var 比较
- var 声明的变量只能是全局或者整个函数块的
- let 允许声明一个在作用域限制在块级的变量、语句或者表达式(块级作用域)
- let 不能重复声明
- let 存在临时死区(temporal dead zone)
- let 不会被预解析(hoisting)
const
- let 有的它也有
- 初始化必须赋值
- 赋值后不能改动类型
暂时性死区
只要块级作用域内存在 let/const 命令,它所声明的变量就绑定这个区域,不再受外部的影响。在代码块内,使用 let/const 声明变量之前,该变量都是不可用的,所以叫 “暂时性死区”。
函数作用域和块级作用域
- 函数作用域:在 JavaScript 中定义一个函数,函数内部的变量只能通过函数内部访问,同时它可以修改和影响外部变量。
- 块级作用域:变量在离开定义的块级代码后立即被回收,存在暂时性死区的特性。块语句用于组合零个或者多个语句,这个块由一对大括号 界定。
提示
在 ES5 中只有全局作用域和函数作用域,没有块级作用域,这会带来些许麻烦:
- 内层变量覆盖外层变量
- 循环的变量泄露为全局变量
- ES5 形成块级作用域的方法
(function () {
var a = 1;
})();
- ES6 通过 界定
{
var x = 1; // 或者 const x = 1;
}
闭包
当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。
- 简单来说:
在函数 A 中还有函数 B,函数 B 调用了函数 A 中的变量,那么函数 B 就称为函数 A 的闭包。
闭包好处和坏处
-
好处:
- 缓存。将变量隐藏起来不被 GC 回收。
- 实现柯里化。利用闭包特性完成柯里化
-
坏处:
- 内存消耗。闭包产生的变量无法被销毁。
- 性能问题。由于闭包内部变量优先级高于外部变量,所以需要多查找作用域链的一个层次,一定程度影响查找速度
this
important
this永远指向最后调用它的那个对象- 普通函数中 this 的指向,是 this 执行时的上下文
- 箭头函数中 this 的指向,是 this 定义时的上下文