专栏首页FundebugES6的const并非一定为常量

ES6的const并非一定为常量

摘要: const定义的变量一定为常量吗?No!

对于ES6的const变量,大家一直存在误会,这篇博客将试着解开真相。

const的本质

const定义的变量并非常量,并非不可变。使用const定义的对象或者数组,其实是可变的。下面的代码并不会报错:

const foo = {};
foo.name = "Fundebug";
console.log(foo.name); // 打印"Fundebug"

为什么会这样?下面引用大神阮一峰的ECMAScript 6 入门

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

因此,当我们使用赋值运算符, 一元运算符以及后缀运算符对const变量进行修改时,会出现“TypeError:Assignment to constant variable”报错:

const foo = 27;

// 下面任意一个表达式都会报错:TypeError: Assignment to constant variable.
foo = 42; 
foo *= 42;
foo /= 42;
foo %= 42;
foo += 42;
foo -= 42;
foo <<= 0b101010;
foo >>= 0b101010;
foo >>>= 0b101010;
foo &= 0b101010;
foo ^= 0b101010;
foo |= 0b101010;


--foo;
++foo;


foo--;
foo++;

如果你需要监控线上应用的BUG的话,欢迎免费试用Fundebug

如何定义常量?

对于数值、字符串和布尔值变量,使用const定义的话是不可变的:

const name = "Fundebug";
name = "云麒"; // 报错:TypeError: Assignment to constant variable.

使用Object.freeze()可以让对象不可变,这个API从ES5开始就有了。

const foo = Object.freeze(
{
    'name': "Fundebug"
});

foo.name = "云麒"; // 严格模式("use strict")下报错:Uncaught TypeError: Cannot assign to read only property 'bar' of object '#<Object>'

console.log(foo.name); // 非严格模式下打印"Fundebug"

注意,Object.freeze()是有局限性的,对象中嵌套对象仍然可以被修改。MDN提供了一下deepFreeze示例代码,是利用Object.freeze()实现的,可以让嵌套对象也不可变。

另外,Object.freeze()仅对键值对有效。对于Date, Map和Set,目前还没有相应方法。因此有人提议在ECMAScript标准中添加不可变的Map和Set等数据类型。

const和let如何选择?

const和let的唯一区别在于,const可以让数值、字符串和布尔变量不可变。

以上所说的内容都是事实,下面我想表达一下自己的观点。

const可以提高代码的可读性,因为const定义的数值、字符串和布尔变量是不可变的,而const定义的对象始终指向同一个对象。而使用let时,不能保证这些。因此,对于let和const,我们应该这样选择:

  • 默认使用const
  • 仅当变量需要修改时使用let
  • 不要使用var

你是否同意我的观点呢?欢迎大家交流讨论~

参考

版权声明

转载时请注明作者 Fundebug以及本文地址: https://blog.fundebug.com/2018/07/25/es6-const/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JS常用正则表达式备忘录

    正则表达式或“regex”用于匹配字符串的各个部分 下面是我创建正则表达式的备忘单。

    Fundebug
  • 大神是怎样用函数式JavaScript计算数组平均值的

    函数式编程中用于操作数组的方法就像“毒品”一样,它让很多人爱上函数式编程。因为它们真的十分常用而且又超级简单。 .map() 和 .filter()都仅需一个参...

    Fundebug
  • 掌握 Async/Await

    前端工程师肯定都经历过 JS 回调链狱的痛苦过程,我们在使用 Promise 的时候总是不尽人意。这时候 Async/Await 应运而生,它到底有什么魔力,我...

    Fundebug
  • 分享一些你绝对需要的小工具

    今天不谈技术,放松一下。给大家分享一些个人感觉比较实用的小工具。希望能够帮助到各位。

    我的小碗汤
  • IPv6排障工具之ping6完整过程细节剖析

    导语 | 关于ping的原理详解,网上搜索一下可以搜索出很多相关内容,而ping6的详解,我暂时还没有看见高质量的文章。希望本文能够让更多朋友了解ping6的原...

    binwenli
  • 理解以太坊ABI - 应用程序二进制接口

    阅读本文前,你应该对以太坊、智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么。

    Tiny熊
  • 从SAP最佳业务实践看企业管理(2)

    先简单的介绍一下SAP,首先SAP是一家德国公司名称,是系统System、应用Application、产品Product的简称,当年是IBM的几个工程师出来创建...

    SAP最佳业务实践
  • Java大型互联网公司经典面试题,论JDK源码的重要性的无限思考

    论JDK源码的重要性:一道面试题引发的无限思考!大家在看到这个标题时想的是什么?小编我为什么要讲这个问题呢?

    Java后端技术
  • 配置docker实现python+sel

    一)安装前检查(使用securable.exe 或 LeoMoon CPU-V.exe):

    py3study
  • 大数据之数据采集

    浏览器页面采集: 主要是收集页面的 浏览日志(PV/UV等) 和 交互操作日志(操作事件)。

    奎哥

扫码关注云+社区

领取腾讯云代金券