最近看到一个面试题——用ES5实现const。作为JS初学者的笔者知道在ES6中有const命令,可以用来声明常量,一旦声明,常量的值就不可改变。例如:

1
2
3
4
5
6
7
8
9
10
11
const Pi = 3.1415;
Pi
Pi = 3;
// TypeError: Assignment to constant variable. const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

但是让我困惑的是,怎么才能使用ES5来实现const呢?说到这里我就想起了下半年···中美合拍···两开花···啊不对!!是想起了最近在学习Vue框架,而Vue在实现响应式原理时使用到了Object.defineProperty()方法,该方法可以定义对象属性的数据描述符,比如configurable、writable、enumerable等等,通过这些描述符就可以设置对象属性是否可读可写可配置可枚举,进而就可以实现类似定义常量的功能。

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。语法如下:

Object.defineProperty(obj, prop, descriptor)

其中descriptor代表将被定义或修改的属性描述符。属性描述符有两种主要形式:数据描述符存取描述符。本文只讨论数据描述符,数据描述符有以下选项:

  • configurable

    当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false

  • enumerable

    当且仅当该属性的enumerabletrue时,该属性才能够出现在对象的枚举属性中。默认为 false

  • value

    该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined

  • writable

    当且仅当该属性的writabletrue时,value才能被赋值运算符改变。默认为 false

此时我们设想,当我们讲对象属性中的writable设为false的时候,该属性是只读的,就能满足我们对常量的要求了。

1
2
3
4
5
6
7
8
9
var _const = {};
Object.defineProperty(_const, "A", {
value: 1,
writable: false, //设置属性只读
configurable: true,
enumerable: true
});
console.log(_const.A); //1
_const.A = 2; //在严格模式下会抛错,在非严格模式下静默失败,修改无效。

但此时,我们只要修改属性的数据描述符来修改属性值,依然可以对属性值进行修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var _const = {};
Object.defineProperty(_const, "A", {
value: 1,
writable: false,
configurable: true,
enumerable: true
}); Object.defineProperty(_const, "A", {
value: 2,
writable: true,
configurable: true,
enumerable: true
});
console.log(_const.A); 大专栏  浅谈在ES5环境下实现constspan class="comment">//2
_const.A = 3;
console.log(_const.A); //3

如此我们就需要将configurable设置为false,这样属性就不可配置了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var _const = {};
Object.defineProperty(_const, "A", {
value: 1,
writable: false,
configurable: false,
enumerable: true
});
console.log(_const.A) //1
_const.A = 2; //Cannot redefine property: A
Object.defineProperty(_const, "A", {
value: 2,
writable: true,
configurable: true,
enumerable: true
}); //报错!属性不可配置

但是configurable特性表示对象的属性是否可以被删除,以及除writable特性外的其他特性是否可以被修改。所以writable特性依旧可以修改,仅限于由true改为false,不能由false改为true。并且value值的设置也不会应此受到影响,则会出现下述情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var _const = {};
Object.defineProperty(_const, "A", {
value: 1,
writable: true,
configurable: false,
enumerable: true
});
console.log(_const.A); //1
Object.defineProperty(_const, "A", {
value: 2, //该属性不受configurable的影响
writable: false,
configurable: false,
enumerable: true
});
console.log(_const.A); //2
_const.A = 3;
console.log(_const.A); //2 修改无效

因此,通过Object.defineProperty() 方法,使用属性的数据描述符,可以定义一个命名空间,将常量封装在命名空间里面。由于属性描述符默认为false,所以可以这样定义:

1
2
3
4
5
6
7
8
9
var _const = {};
Object.defineProperty(_const, "A", {
value: 1,
enumerable: true
});
Object.defineProperty(_const, "B", {
value: 2,
enumerable: true
});

参考链接:

1.JavaScript 常量定义

2.Object.defineProperty()

3.ECMAScript 6 入门-阮一峰

浅谈在ES5环境下实现const的更多相关文章

  1. 浅谈Java语言环境搭建-JDK8

    title: 浅谈Java语言环境搭建-JDK8 blog: CSDN data: Java学习路线及视频 1.What's the JDK,JRE JDK(Java Development Kit ...

  2. 浅谈Vue不同场景下组件间的数据交流

    浅谈Vue不同场景下组件间的数据“交流”   Vue的官方文档可以说是很详细了.在我看来,它和react等其他框架文档一样,讲述的方式的更多的是“方法论”,而不是“场景论”,这也就导致了:我们在阅读完 ...

  3. 【Vue】浅谈Vue不同场景下组件间的数据交流

    浅谈Vue不同场景下组件间的数据“交流”   Vue的官方文档可以说是很详细了.在我看来,它和react等其他框架文档一样,讲述的方式的更多的是“方法论”,而不是“场景论”,这也就导致了:我们在阅读完 ...

  4. 浅谈JS执行环境及作用域

     今天刚刚开通博客,也是第一次写博文,略感紧张.作为一个表达能力弱弱的人来说,自己花三分钟理解一个知识点,当别人问起时,也许需要30分钟才只是让别人知道自己在说什么,一点也不夸张,希望在博客上可以练习 ...

  5. 浅谈.net jenkins svn下自动化集成环境安装 搭建 配置

    本人做.net研发已有3年多了,之前一直偏向于技术研究,自己学了很多技术,现在突然发现学了那么多技术有什么用呢?真正用到的并不多. 现在?算是一只小鸟吧,自嘲下.....毕竟我是90后,很多领导对于9 ...

  6. Appium自动化—浅谈iOS自动化测试环境搭建

    在日常的测试工作中,我们会发现有些测试工作重复率极高,测试人员需要花费大量的时间进行这些重复性的测试,浪费了大量的人力与时间.若能够将常用的测试场景进行自动化,那必定能节省许多的人力与时间.作为一个初 ...

  7. 浅谈ES6——ES6中let、const、var三者的区别

    在了解let.const.var的区别之前,先了解一些什么是es6 Es6 全称ECMAscript 是JavaScript语言的一个标准,其实Es6本质就是JavaScript的一个版本,为什么叫E ...

  8. 浅谈export 以及环境变量

    简要说一下env,set,export的区别:env命令显示环境变量,set和export显示环境变量和自定变量. export:可以讲自定变量转化为环境变量之前有一个疑惑,我们定义环境变量PATH时 ...

  9. 技术分析 | 浅谈在MySQL体系下SQL语句是如何在系统中执行的及可能遇到的问题

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 SQL语句大家并不陌生,但某种程度上来看,我们只是知道了这条语句是什么功能,它可 ...

随机推荐

  1. Python常用模块小结

    目录 Python常用模块小结 一.Python常用模块小结 1.1 time模块 1.2 datetime模块 1.3 random模块 1.4 os模块 1.5 sys模块 1.6 json模块 ...

  2. 四十三、LAMP与LNMP web架构深度优化实战-第二部

    1. 配置nginx gzip压缩功能    服务器对发出的内容进行压缩,带宽少了,体验好,速度快,但是服务端压,会使cpu使用高,压缩比高的进行压缩:文本.程序文件.数据文件.图片视频不要压缩,一般 ...

  3. java基本类型和包装类型

          int 是基本类型,直接存数值 Integer是类,产生对象时用一个引用指向这个对象 Java把内存划分成两种:一种是栈内存,另一种是堆内存 在函数中定义的一些基本类型的变量和对象的引用变 ...

  4. linux下 c语言调用c++

    /*****************************g++编译cpp 文件为库文件.编译C文件时gcc 要链接 -l stdc++ 这个库**(非常重要)*///定义c++ class 头文件 ...

  5. xcode垃圾目录以及Mac隐藏显示文件快捷键

    ~/Library/Developer/Xcode/DerivedData 显示:defaults write com.apple.finder AppleShowAllFiles -bool tru ...

  6. 有关于i++,i=i++等符号的笔记

    最近在看一些基础知识,发现自己以前忽略掉了很多东西,而这些东西恰恰是面试笔试中最常考到的 1.i=i+1 这个是最简单,最明了的一个表达式 2.有关于i++和++i的区别 i++和++i都是代表i=i ...

  7. django rest framework 小小心得

    這篇主要是針對於個人目前學習django rest framework的一些小小心得,在開發django而言,想要撰寫restful api,是有幾個套件可以選擇的 rest framework ta ...

  8. linux_cat命令

    cat 命令可以用来显示文本文件的内容(类似于 DOS 下的 type 命令),也可以把几个文件内容附加到另一个文件中,即连接合并文件. 关于此命令,有人认为写 cat 命令的人是因为喜欢猫,因此给此 ...

  9. 基于css完成网页的国际化

    css完成国际化 前提 在日常处理国际化的时候,通常是将key通过类似intl.xx(key)转换为对应环境的文案,可是如果需要在css中加入对应逻辑应该怎么做呢(比如在after的伪元素中显示不同的 ...

  10. 网站爬取-案例一:猫眼电影TOP100

    今天有小朋友说想看一下猫眼TOP100的爬取数据,要TOP100的名单,让我给发过去,其实很简单,先来看下目标网站: 建议大家都用谷歌浏览器: 这是我们要抓取的内容,100个数据,很少 我们看一下页面 ...