专栏首页前端达人【ES6基础】const介绍
原创

【ES6基础】const介绍

在ES6之前,JavaScript被其他编程语言诟病没有定义常量的能力,甚至在大多数企业的开发文档中,对于常量的定义都使用var。一般经常会使用大写字母和下划线组成的变量名进行规范约束。当然这种妥协的“常量”是随时可变的。例如以下代码:

var MAX_COUNT=0;
MAX_COUNT=1 //WARNING

好在E6引入了const,让JavaScript获得了真正的定义常量的能力,接下来小编将和大家一起学习const,通过本篇文章,你将学到以下内容:

  • const介绍
  • 可变的对象变量
  • 如何让对象的属性不可变?
  • 作用域范围
  • 如何选择var/let/const

本篇文章阅读时间预计10分钟

const介绍

使用const语法创建变量,一旦创建初始化,我们就不能改变他们的值,因此这就称为常量。如果你尝试改变一个const变量,则会抛出异常。此外,如果你使用const只声明变量,不进行初始化,也会抛出异常。如以下代码,试图改变一个常量,引擎就会抛出异常:

const pi = 3.141;
pi = 4; // not possible in this universe, or in other terms, 
        // throws Read-only error

由于ES6可以为程序工程化提供内存安全的优势,便是因为const定义常量的原理是阻隔变量所对应的内存地址被改变。

变量与内存之间的关系由三个部分组成:变量名、内存绑定和内存地址。如下图所示:

ES6在对变量的引用进行读取时,会从该变量当前所对应的内存地址所指向内存空间中读取内容。当变量改变时,引擎会重新从内存分配一个新的内存空间以存储新值,并将新的内存地址与变量进行绑定。const的原理便是在变量名与内存地址之间建立不可变的绑定,当尝试重新分配新的内存空间时,引擎便会抛出异常。

在某些情况,并非值不可变。以V8引擎为例,如字符串、数字、布尔值、undined等值类型只占用一组内存空间的,这些类型的值再内存空间中是连续的、不可拆分的。而对于对象、数组等稀疏的引用类型值,由于属性值是可以变化的,所以为了最快地进行内存调度,当对象的属性被改变或添加了新的属性时,都需要重新计算内存地址偏移值。因此使用const定义对象时,由于所创建的内存只绑定一处的,所以默认情况下对象这种由若干内存空间片段组成的值并不会全部被锁定,因此使用const定义对象时,对象的属性值是可变的。

可变的对象变量

上一小节我们提及到,当我们使用const定义对象时,由于对象是引用类型值,而非对象本身,因此更改对象的属性是可行的,重新更改整个对象变量会抛出异常,如下段代码所示:

const a = {
  name: "Mehul"
};
console.log(a.name);
a.name = "Mohan";
console.log(a.name);
a = {}; //throws read-only exception

上述代码输出

Mehul
Mohan
<Error thrown>

在此示中,a变量是引用值类型,对象地址是不能改变的,但是这个对象本身的属性是可以改变的。因此,当我们尝试将顶一个对象分配给a变量时,引擎就会抛出异常。

如何让对象的属性值不可变呢?

上一小节,我们了解了,使用const定义变量时,变量的属性是可以更改的,如何让其不能更改呢,其实只要配合ES5中的Object.freeze()方法,便可以获得一个第一层属性(首层)不可变的对象。如果第一层属性中存在对象嵌套,嵌套对象的属性仍然是可以改变的。如下段代码所示:

const ob1 = {
   prop1 : 1,
    prop2 : {
        prop2_1 : 2 
    }
};
Object.freeze( ob1 );
ob1.prop1 = 4; // (frozen) ob1.prop1 is not modified 
ob1.prop2.prop2_1 = 4; // (frozen) modified, because ob1.prop2.prop2_1 is nested
ob1.prop2 = 4; // (frozen) not modified, bar is a key of obj1
ob1 = {}; // (const) ob2 not redeclared (used const)

如何实现所有层级的属性不可变呢?我们可以用递归的方式调用Object.freeze进行实现,如下段代码所示(代码来源MDN):

function deepFreeze(object) {

  // Retrieve the property names defined on object
  var propNames = Object.getOwnPropertyNames(object);

  // Freeze properties before freezing self
  
  for (let name of propNames) {
    let value = object[name];

    object[name] = value && typeof value === "object" ? 
      deepFreeze(value) : value;
  }

  return Object.freeze(object);
}

var obj2 = {
  internal: {
    a: null
  }
};

deepFreeze(obj2);

obj2.internal.a = 'anotherValue'; // fails silently in non-strict mode
obj2.internal.a; // null

作用域范围

关于作用域的概念,小编在这篇文章《【ES基础】——let和作用域》已经介绍过了,不清楚的可以点击链接进行查看,const和let一样,也是块作用域变量,他们遵循相同的作用域规则,如下段代码所示:

const a = 12; // accessible globally
function myFunction() {
  console.log(a);
  const b = 13; // accessible throughout function
  if(true) {
    const c = 14; // accessible throughout the "if" statement
    console.log(b);
  }
console.log(c);
}
myFunction();

上述代码输出

12
13
ReferenceError Exception

如何选择var/let/const

从ES6引入let的语法,设计的初衷便是替代var。从工程化的角度来说,我们应从ES6后遵从以下三原则:

  1. 一般情况下,使用const在定义常量。
  2. 只有明确值会被改变时,我们才使用let定义变量。
  3. 不再使用var。

结束语

今天的内容就介绍到这里,为了更好的使用ES6,我们应该尽快适应使用const定义常量,使用let定义变量。

更多精彩内容,请微信关注”前端达人”公众号!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【ES6基础】const介绍

    在ES6之前,JavaScript被其他编程语言诟病没有定义常量的能力,甚至在大多数企业的开发文档中,对于常量的定义都使用var。一般经常会使用所有字母大写和下...

    前端达人
  • 127个常用的JS代码片段,每段代码花30秒就能看懂(五)

    按照指定的长度生成字符串,如果字符串长度不够,可以按照设定的字符在其左右两端补齐,默认为空格字符串。

    前端达人
  • 127个常用的JS代码片段,每段代码花30秒就能看懂(五)

    按照指定的长度生成字符串,如果字符串不够,可以按照设定的字符串内容在左右两边进行填充,默认空格为填充字符。

    前端达人
  • 函数声明后面的const用法

    void function() const{} 通常我们会看到一些函数声明后面会跟着一个const,这个const是做什么的呢? 看一下下面的例子,就知道了。直...

    用户1154259
  • C++primer学习笔记(一)

    震八方紫面昆仑侠
  • QMap容器小知识

    Qt君
  • 【ES6基础】const介绍

    在ES6之前,JavaScript被其他编程语言诟病没有定义常量的能力,甚至在大多数企业的开发文档中,对于常量的定义都使用var。一般经常会使用所有字母大写和下...

    前端达人
  • 学习c++中的小问题总结

    徐飞机
  • C++雾中风景3:const用法的小结

    const关键字,翻译成中文是常量,常数的意思。所以在绝大多数场合之中,const是来定义常量的,定义常量也是好的编程习惯。在C类语言之中,定义常量通常会使用宏...

    HappenLee
  • 初级程序员面试不靠谱指南(二)

    3.read-only的const。如果你突然冒出一句看似很高深的话但又不解释一般都是装逼,就像前面提到过const准确的应该理解为一个read-only的变量...

    一心一怿

扫码关注云+社区

领取腾讯云代金券