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)

参考资料

  1. 如何用es5写const和let
posted @ 2021-09-12 17:56  hdxg  阅读(96)  评论(0)    收藏  举报
// 侧边栏目录 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css