谈谈 var, let, const. var 也是一种选择
历史故事
在 ES6 之前, JavaScript 是一门被称为没有块级作用域的语言.
看看代码:
(function(){
'use strict';
console.log(i)
for (var i = 0; i < 10; ++i) { console.log(i) }
console.log('i=' + i)
})()
输出结果:
undefined
...
...
i=10
权威解析: i=10 这是因为 i 被声明在当前函数的作用域内, var 不管你声明在函数的什么位置, 在函数执行之前, 解析器会扫描当前函数作用域, 并将以 var 和 function 开头的语句的变量名添加到当前函数作用域内, 这意味着诸如 var func = function name() {}
这样的语句的右边的函数的名字是不会被添加到当前作用域内的( 但是在函数内部可以访问 ), 在 ES6 中的 class 也有同样的表现. 此时 var 声明的变量还没有值( undefined
), 这也是第一个输出语句为什么没报错而输出 undefined 的原因; function 声明的函数名会指向一个函数对象( 也就是 __proto__
属性指向 Function.prototype
).
这种现象对于习惯了块级作用域的程序猿来说是灾难般的. 于是搞标准的那帮人弄了 let
, const
这样的关键字出来. let 和 const 声明的变量不会在之前说的扫描阶段里被添加到当前作用域内, 并且会在当前大括号内的作用域块结束的时候被清理掉, 也就是说 ES6 有了块级作用域. 对于 const 还加了两条限制.
如果 const 的变量是基本类型( null, undefined, string, number ), 那么变量的值不能变.
如果 const 的变量是引用类型( object ), 那么其引用值不能改变.
看代码就知道了
(function(){
'use strict';
// 如果执行下面这行代码, 会报引用错误
// console.log(i) // Reference Error
// 如果执行下面这行代码, 会报引用错误
// 因为 i 在 for 循环结束后就被销毁了
setTimeout(() => console.log(i), 0)
for (let i = 0; i < 10; ++i) { console.log(i) }
const foo = 10
const bar = {}
foo = 11 // TypeError
bar.type = 'const' // OK
})()
我该怎么选择?
如果你稍微接触过 ES6, 别人会告诉你 绝对不要用 var
, 如果变量在将来不会改变就用 const
, 否则就用 let
.
这句话我是赞同的, 但是在我写代码的时候遇到某些情况不得不用 var, 看代码:
async function clearExpiredRss() {
try {
var connection = await pool.getConnection()
connection.query(`DELETE FROM ${TABLE_NAME} WHERE date+3600*1000 < ${Date.now()}`)
} catch (e) {
logger.error(e)
} finally {
connection && connection.release()
}
}
connection 变量如果用 let
或 const
声明的话, finally
内就没办法释放连接了. 有人说为什么不直接在 try
内写个 if
判断? 个人觉得在 finally 里看起来更优雅一些.
所以说, 有时候作用域链反倒是 javascript 这门语言的优势, 为此, 我不得不说, javascript 是世界上最好的语言!
最后想说的
你们有没有遇到过 github issues 上写文章的人... 我反正是看到了很多在 Github 上的 issues 写技术博客的人. 之前都喜欢用 Github 的 Subscribe 功能来订阅, 或者直接 Watching ... 这两天突发奇想, 能不能把 issues 转换成 RSS 呢? 所以就撸了一个小工具, github-issues-rss, 求关注, 求 star !
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。