ES5实现let和const
前言
网上找了几篇文章,发现最终都参考自参考资料1。但我觉得参考资料1写得不够好,特别是实现const,并没有考虑完整。作者将常量挂在了window上,导致全局不能出现同名的常量。并且如果在某个函数内用const声明的常量,在函数外应该是访问不到的,而由于挂在了window上,导致函数内声明的常量也能在函数外访问,这是不对的。
当然,挑毛病的同时,也得感谢作者把实现的草稿发了出来,我才能根据此发现问题,并找到自己想要的答案。让我自己摸索可能要花费一定的功夫。
实现let
let定义一个仅作用于该代码块的变量,可以使用立即执行函数来实现。
for (var i=0; i<10; i++) {
(function(i){ // 实参的副本
console.log(i)
})(i) // 把i值传进去
}
实现const
const声明一个常量,其由如下特点:
- 一旦声明,值就不能改变;
- 函数内部声明的常量不能在函数外部访问;
- 用delete无法删除;
好,先将我们的const实现给出来:
var __const = function __const(data, value) {
Object.defineProperty(this, data, { // 利用Object.defineProperty的能力劫持当前对象,并修改其属性描述符
enumerable: false,
configurable: false,
get: function () {
return value
},
set: function (data) {
throw new TypeError('Assignment to constant variable.')
}
})
}
先不考虑在函数内部声明:
// 定义常量
__const('a', 10)
console.log(a)
// 无法删除
delete a
console.log(a)
// 因为const定义的属性在global下也是不存在的,所以用到了enumerable: false来模拟这一功能
for (let item in window) {
if (item === 'a') { // 因为不可枚举,所以不执行
console.log(window[item])
}
}
// 重新赋值,报错
a = 20
10
10
Uncaught TypeError: Assignment to constant variable.
at set (index.html:12)
at index.html:33
再考虑再函数内部声明:
function test() {
// 定义常量
__const('a', 10)
console.log(a)
// 无法删除
delete a
console.log(a)
// 因为const定义的属性在global下也是不存在的,所以用到了enumerable: false来模拟这一功能
for (let item in window) {
if (item === 'a') { // 因为不可枚举,所以不执行
console.log(window[item])
}
}
// 重新赋值,报错
a = 20
}
test()
// 函数外访问不到a
console.log(a)