java const关键字_const关键字:终于拥有真正的常量声明语句

你好,今天大叔想和你唠扯唠扯 ES6 新增的关键字 —— const。在说 const 关键字之前,大叔先和你唠唠大叔自己对 const 的感受 —— JavaScript 尼玛终于可以声明真正的常量啦!大叔为啥会发出这样滴感叹?实在是“天下苦秦久矣”呀~

话说 long long ago,当初大叔从 Java 技术栈转向前端技术栈,首先要搞定的就是 JavaScript。虽然都说 JavaScript 和 Java 语言有很多的地方是相似滴,但你知道直到大叔发现这货不能声明常量时候的感受吗?!那真是欲哭无泪啊~ 一个堂堂滴编程语言,居然尼玛不能声明常量?!也好意思说自己是个编程语言?!

01声明常量

好吧~ 大叔不吐槽了,还是说正事儿吧。其实,在 ES5 里面也不是不能声明常量,就是有那么一捏捏的别扭。你知道 Object 有个叫做 defineProperty() 的方法吧?它是用来给某个对象定义属性的。在 ES5 里面就可以通过这个方法间接地来声明常量。

比方说,你现在想在全局作用域里面声明一个常量,其实就可以看作是给顶级对象添加一个属性嘛。带入个场景比较好整明白,假设是一个 HTML 页面里面声明一个全局常量,就可以像下面这样整:

eb9673b79bb541f5364ee1e0046d6a6b.png

这段代码的意思就是给 window 对象增加一个名叫 a 的属性。writeable 的作用就是这个属性能不能写,值为 false 就是只能读不能写的意思。所以,这时的属性 a 就只能访问不能修改。不信咱可以试试:

d616e0d75ad04fe1197588647fb92755.png

这时打印的结果比较简单,就是 a。接下来咱们再修改一下试试看是啥结果:

ebbbc3676b5c2d273b891d6bdf5bd006.png

打印的结果还是 a,并没有把 a 的值改成 b。

其实,这样的用法已经很接近常量的用法了。但是,可但是,但可是~ 你不觉得别扭吗?!为啥?大叔给你屡屡:

尼玛我现在要声明的是一个常量,你现在用的是定义属性的语法。这个示例还好,因为是声明全局常量,可以加到 window 这种顶级对象上。要是在一个函数作用域里面咋办,我找不准上下文对象咋办?!即使就用这个办法能解决这个问题,也确实不能改值。但是,啥提示没有,你不难受吗?!常量就是常量,属性就是属性。至少从概念上就别尼玛混淆在一起,你说是不是?!所以,在 ES6 的新特性里面,大叔终于看到希望 —— const。这货才是真正用来定义常量滴!说到常量,大叔得先给你科普一下到底怎么样才算是常量。

所谓常量,简单来说就是不能变化的值。其实,不仅不能值变化,还不能重复赋值,也不能重复声明,这才算是对滴。

那接下来,大叔就给你看看 const 这货能不能做到这一点:

beaf323cd19ccf01709f8d78239b27a3.png

这段代码不难看出就是使用 const 关键字声明了一个常量,两处打印的结果分别为:

第一处打印的结果是 a第二处打印的结果是报错,报错的内容是:TypeError: Assignment to constant variable.,大概的意思就是你把常量当变量赋值了。看到了吧?!这才是常量。不仅不能改变值,而且会进行报错,告诉你改变值这种行为是不对滴。

02声明常量的注意事项

当然了,ES6 新增了这样的语法,附带的也有一些需要你注意的事儿 —— 就是在声明一个常量的时候,是必须把常量进行初始化的。不能像声明变量一样,声明和初始化可以分成两个步骤完成。比方说像下面这样婶儿做:

c04c938a29f743be363d626a6e636578.png

这段代码运行之后的结果就是给你报个大错,报错的内容是:SyntaxError: Missing initializer in const declaration,大概的意思就是说你在声明常量的时候没给人家初始化。

你看看,整得多明白!钉儿是钉儿,卯儿是卯儿的。

03块级作用域

再有就是,const 不仅提供一个真正可以声明变量的方式,还提供了块级作用域。啥?你还不知道呢?!那你就去看看大叔写的ES6新增了加强版的var,究竟有什么区别呢?这篇文章里面关于块级作用域的内容吧。

在这儿呢,大叔想再次重申一下块级作用域的好处 —— 就是会把之前暴露在全局作用域的一些变量全部限制在一个具体的块级作用域里面。比方说像下面这样婶儿的代码:

b210605d0caff1748684c9b7591a4f11.png

这段代码运行后打印的结果是报错,报错的内容是:ReferenceError: f is not defined。也就是说,你在一个块级作用域里面声明一个常量,在这个块级作用域之外是没办法访问到这个常量的。

04暂时性死区(TDZ)

既然唠到 const 声明的常量是具有块级作用域的,那就不能不说一下暂时性死区的问题了。啥意思呢?就是说使用 const 声明的常量也同样存在暂时性死区的,不信你来看段代码:

917a1ade48cbcc26b5b6c500b8d0360d.png

这段代码运行后的结果是报错,报错的内容还是暂时性死区的错误:ReferenceError: Cannot access 'a' before initialization。

存在了暂时性死区了,就说明 const 声明常量的时候也就不存在啥声明提前的事儿了。这两件事儿吧,其实说的是一个意思,你可得记明白了。

05声明常量对象或者数组

唠到这儿吧,其实基本上关于 const 都唠完了。这货除了可以真正声明一个常量之外,其实没啥可唠的啦。但是,但可是,可但是~ 嘿嘿~

大叔想问你的问题:如果咱们用 const 声明一个对象或者数组,那这个对象的属性或者数组里面的元素能不能修改呢?

寻思是寻思不明白的,咱们直接整代码吧,用事实来看看到是个啥情况。比方说咱们先声明一个这样婶儿的对象:

41fcb1c7086289f3463438772c0cb7c1.png

大叔今年都 37 啦,但是年轻的心还是有滴。所以,大叔想把 age 这个属性的值改成 18,就像这样婶儿的:

05154c3e73f94e0523126f647d890cf6.png

结果~ 咱们运行代码之后得到的结果就是这样婶儿的:

af4eb4ef502446a27b13190b339805ce.png

注意啊~ 注意啊~ age 属性的值被成功滴改成了 18!不对吧?const 声明的不是常量吗?常量不是不能改变值吗?这尼玛结果也不对啊?

灵魂三连问也没用,事实摆在眼吧前儿,咱就得认!但是,为啥会这样涅?别急,且听大叔给你慢慢道来~

想整明白这个事儿吧,咱们就得先唠扯唠扯 JavaScript 的存储结构了。JavaScript 的存储结构有俩儿,一个叫做“堆内存”,一个叫做“栈内存”。一般情况下吧,咱们定义的变量或者常量都是存储在堆内存里面的。但是吧,对象和数组算是 JavaScript 里面比较复杂的一种数据,所以实际上对象或者数组的存储形式是这样婶儿的:

d02017fc941307463a7f6df8644fc093.png

知道了这个事儿,你大概就能整明白为啥上面的代码运行的结果是这样婶儿的了吧?!说白了,const 声明的对象的值确实不能改变,但是对象的值存储的是一个引用地址,而具体的属性其实是存储在这个引用地址里面,const 是没办法限制的。

整到这儿,你是不是想问那这样婶儿的问题要怎么解决?嗯~ 也能解决的。你还记得 Object 提供了一个方法叫做 freeze() 吗?这个方法是用来冻结某个对象的。冻结之后不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。所以,就可以利用这个方法来解决上面提到的问题:

d30e884e84713ec66371a500b1ec7066.png

这样处理之后,咱们再来看看打印后的结果吧:

816adbf9eb44c024ad532e504d57b2fd.png

问题被完美滴解决了!等一下,真的是这样婶儿的吗?大叔想继续再操作一下下的,比方说像这样婶儿的:

fa5f9aefdfcbc8a1220922620d50eb3a.png

啥意思?就是说咱们在声明一个对象的时候,这个对象的属性也同样是一个对象或者数组,那现在的问题就是你利用 Object.freeze() 方法还能成功地冻结不?咱们就来试试吧:

17f5af1818f131f1314acf7f12890f8e.png

咱们得到的结果实际上是这样婶儿的:

6f1802a83671a9142c8c41ef7b96f28d.png

发现还是被修改了~ 这又是咋回事儿呢?这就说明 Object.freeze() 方法只能冻结当前对象的属性,但是如果某个属性的值还是一个对象或者数组的话,那就说明这个属性存储的还是一个引用地址,实际的数据是存储在这个引用地址中的。

想要解决这个问题其实也不算难,就是继续利用 Object.freeze() 方法来冻结这个值为对象或者数组的属性就行了。就像这样婶儿操作:

87bb3b13746d2f9dc189ba4773f37385.png

这样咱们得到的结果就是:

11ad4714c6a7a08e6c823c5ec2fd6ba6.png

也就是说,关于这个问题咱们想一劳永逸地解决掉,可以定义一个函数,把对象作为参数传递进去。然后,这个函数主要利用递归方式把对象中所有值为对象或者数组的属性分别进行冻结,穷尽为止就可以啦!

06写在最后的话

好了,整到这儿,ES6 新增的 const 关键字所有大叔想和你唠扯的内容都唠扯完了,也希望能对你有所帮助。最后再说一句:我是不想成熟的大叔,为前端学习不再枯燥、困难和迷茫而努力。你觉得这样学习前端技术有趣吗?有什么感受、想法,和好的建议可以在下面给大叔留言哦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/530303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

workerman高并发异步mysql_workerman怎么实现高并发

并发概念太模糊,这里以两种可以量化的指标并发连接数和并发请求数来说明。并发连接数是指服务器当前时刻一共维持了多少TCP连接,而这些连接上是否有数据通讯并不关注。 (推荐学习: workerman教程)例如一台消息推送服务器上可能维持了百万的设…

checkout 撤销修改_Git的4个阶段的撤销更改

虽然git诞生距今已有12年之久,网上各种关于git的介绍文章数不胜数,但是依然有很多人(包括我自己在内)对于它的功能不能完全掌握。以下的介绍只是基于我个人对于git的理解,并且可能生编硬造了一些不完全符合git说法的词语。目的只是为了让git通…

java访问权限最高_java 访问权限

Java语言中的访问权限修饰符有4种,但是仅有3个关键字,因为不写访问权限,在Java中被称为默认权限,或同包权限,本文中以(default)代替。下面按照权限从小到大的顺序对4中访问权限分别介绍。class我个人,我有很…

java中fork函数_java中的forkjoin框架的使用

fork join框架是java 7中引入框架,这个框架的引入主要是为了提升并行计算的能力。fork join主要有两个步骤,第一就是fork,将一个大任务分成很多个小任务,第二就是join,将第一个任务的结果join起来,生成最后…

java中已定义类型car_Java 8 习惯用语(8):Java 知道您的类型

Java™8是第一个支持类型推断的 Java 版本,而且它仅对 lambda 表达式支持此功能。在 lambda表达式中使用类型推断具有强大的作用,它将帮助您做好准备以应对未来的 Java版本,在今后的版本中还会将类型推断用于变量等更多可能。这里的诀窍在于恰…

java web 来源页_Java:Java Web--分页效果

先来看一看分页的实现原理万能公式.jpg项目目录.PNG首先,新建Java Web项目一. 梳理业务逻辑重定向到URL(跳转到StudentViewAction页面)//index.jsp页面1.从页面接收可变的值2.接收值有问题时,初始化为13.如果没有问题,把String类型接收值强转成Integer4.实例DAO方法,调用findSt…

java 浏览器 安全_安全策略-IE浏览器防黑十大秘籍

1.管理好Cookie在IE6.0中,打开“工具”→“Internet选项”→“隐私”对话框,这里设定了“阻止所有Cookie”、“高”、“中高”、“中”、“低”、“接受所有Cookie”六个级别,你只要拖动滑块就可以方便地进行设定,而点击下方的“编…

php截取指定字符串之后,php截取字符串(截取指定字符串之间的字符串)

一、PHP截取两个指定字符后边的字符$a "123abc#456";$b (strpos($a,""));$c (strpos($a,"#"));echo substr($a,$b1,$c-1);二、常用截取字符串技巧。//构造字符串$str "ABCDEFGHIJKLMNOPQRSTUVWXYZ";echo "原字符串:…

php 获取key的位置,PHP获取当前所在目录位置的方法

本文实例讲述了PHP获取当前所在目录位置的方法。分享给大家供大家参考。具体分析如下:如果要获取脚本文件的目录,要应用函数getcwd()来实现。函数声明如下:string getcwd ( void ) ;成功执行后返回当前目录字符串,失败返回FALSE。…

php连接数据库navicat,navicat数据库如何连接php

第一步,打开Navicat,新建数据库。第二步,在数据库中新建表。相关推荐:《Navicat for mysql使用图文教程》第三步,保存表。第四步,表中添加数据。第五步,打开ide,输入以下php代码&…

每日一题:LCR 095.最长公共子序列(DP)

题目描述: 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些…

php自动合并,php实现合并数组并去除重复的方法

php实现合并数组并去除重复的方法发布时间:2020-08-12 10:35:05来源:亿速云阅读:99作者:小新这篇文章主要介绍了php实现合并数组并去除重复的方法,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这…

linux内核运行关系图,一张图看懂Linux内核运行交互关系

很多朋友如果接触过Linux的都知道Kernel的含义,kernel是操作系统的核心或者最重要的部分。众所周知的是,几乎整个互联网都运行在 Linux上,从网络协议,到服务器,到你平常访问的绝大多数网站,都能看到它的身…

linux内核bios,BIOS的启动原理——Linux内核设计学习笔记

RAM:随机存取存储器,常见的内存条就是一类RAM,其特点是加电状态下可任意读、写,断电后信息消失。在RAM中什么程序也没有的时候,谁来完成加载软盘中操作系统的任务呢?答案是:BIOS。BIOS的启动原理…

Linux下仿windows任务管理器,开源任务管理器 Process Hacker (Windows)

Windows表面上没有工作在进行中,但不知为何负荷很重,究竟有什么进程在执行?会不会是系统已经被入侵?这是很多人都想知道的问题。但Windows自带的任务管理员实在太过简陋,解决办法便是安装这次介绍的Process Hacker。熟…

嵌入式linux中的锁机制,跟涛哥一起学嵌入式第11集:一个实现锁机制非常有意思的宏...

QQ群(宅学部落)有位学员问了一个很奇怪的宏,觉得很有意思,特拿来分享,它的定义如下:我们知道,宏定义其实就是为了方便,给一串代码字符串定义一个别名。有时候字符串过于复杂,我们可以分多行书写&#xff0c…

linux core 永久生效,【调试】Core Dump是什么?Linux下如何正确永久开启?

内容简介【调试】Core Dump是什么?Linux下如何正确永久开启?Core Dump是什么?Linux下如何正确永久开启?Core Dump是什么?Core Dump乍听之下很抽象。当程序运行的过程中异常终止或崩溃,操作系统会将程序当时…

用于用户C语言标识符,下列可用于C语言用户标识符的一组是( )

摘要:下列不属于骨肉瘤患者常见护理问题()于C语言用户组Since people send nonverbal signals through multiple channels simultaneously, it is impossible to increase our nonverbal communication competence by becoming more aware of how it operates in sp…

c语言猜四位数游戏猜10次,C语言猜数字游戏--随机生成4个不相同的数字从小到大排序,用户开始游戏,如果用户猜对数字和数字对应的位置,界面回馈A,如果数字正确位置不正确,则回馈B...

1.看程序运行截图吧!!由于博主本人较笨,就不动画演示了,如果动画的话可能将是一个漫长的过程!猜数字游戏.png2.游戏题目随机生成4个不相同的数字从小到大排序,用户开始游戏,如果用户猜对数字和数…

双端堆c语言,数据结构——双端堆(C语言)

定义双端堆:是一棵完全二叉树,该完全二叉树要么为空,要么同时满足下列性质:(1) 根节点不包含元素;(2) 左子树是一个最小堆;(3) 右子树是一个最大堆;(4) 如果右子树不空,令i是左子树中…