最近看到一个面试题——用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. Mac 终端实现快速定位命令 自动补全目录

    基于macOS oh-my-zsh 切换终端主题 incr.zsh 实现快速定位命令 自动补全目录 效果预览 步骤 1.安装 oh-my-zsh sh -c "$(curl -fsSL ht ...

  2. QMessageBox按钮自定义文字

    msgbox = QMessageBox()msgbox.setStandardButtons(QMessageBox.Yes|QMessageBox.No)msgbox.button(QMessag ...

  3. ios AVPlayer参考

    http://www.cnblogs.com/kenshincui/p/4186022.html#avPlayer

  4. spark mllib lda 中文分词、主题聚合基本样例

    github https://github.com/cclient/spark-lda-example spark mllib lda example 官方示例较为精简 在官方lda示例的基础上,给合 ...

  5. CF1137C Museums Tour(tarjan+DP)

    由于d很小,所以可以把每个点拆成d个点,然后对于边(x,y),连边时连接((x,i),(y,i+1))及((x,d),(y,1)).然后可以对这样连的边跑一遍tarjan缩点.然后直接暴力DP即可.不 ...

  6. 编译原理_P1003

    1. 语法分析 1.1 上下文无关文法的定义 ----  正规式能定义一下简单的语言,能表示给定结构的固定次数的重复或者没有指定次数的重复 例如:a(ba)5,a(ba)* ---- 正规式不能用于描 ...

  7. 量化投资_轻松实现MATLAB蒙特卡洛方法建模

    1 目录 * MATLAB随机数的产生 - Uniform,Normal & Custom distributions * 蒙特卡洛仿真 * 产生股票价格路径 * 期权定价 - 经典公式 - ...

  8. linux_nano命令

    nano是一个字符终端的文本编辑器,有点像DOS下的editor程序.它比vi/vim要简单得多,比较适合Linux初学者使用.某些Linux发行版的默认编辑器就是nano. nano命令可以打开指定 ...

  9. 用原生socket发送HTTP数据包

    分享一个写扫描器和POC时的小技巧. 有时候有的漏洞需要一些特殊的数据包,比如说畸形的HTTP头.畸形的Multipart.畸形的chunk包等,此时用编程语言自己的HTTP库可能构造不出这种数据包, ...

  10. Git ubuntu 升级

    外文文档 This team will distribute the most current stable package of Git for Ubuntu. Stable releases: h ...