最近看到一个面试题——用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. js 经纬度计算直线距离

    function getRad(d) { var PI = Math.PI; return d * PI / 180.0; } function getDistance(lat1, lng1, lat ...

  2. 洛谷P1435 回文子串

    题目背景 IOI2000第一题 题目描述 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 “A ...

  3. Activity组件(三):通过对象实现信息添加及展示

    在对组件进行注册时,只注册了EditText,却忘记了Button,导致程序一直闪退 输入信息 点击添加 成功跳转页面,并将数据传递 User.java package com.example.reg ...

  4. goweb-goweb基础

    goweb DNS工作原理 在浏览器中输入www.qq.com域名,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析. 如果hosts里没 ...

  5. 编译x64c++出错,errorC1900:P1和P2之间 Il 不匹配问题

    搜索了下相关资料,有一个说法是编译x64时本地缺失一些东西,2015安装update3就行. 我的是2013update4,找了下最新的有update5,安装然而并没有什么用. 最后还是重新找对应版本 ...

  6. reactor-core

    <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core&l ...

  7. Spring Boot Session 超时时间

    springboot session https://www.jianshu.com/p/523572937db8 springboot2以上版本设置session超时时间 https://blog. ...

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

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

  9. 前端框架Bootstrap(10.7国庆补写)

    框架的官网地址:https://v3.bootcss.com/ 主要学习Bootstrap框架提供的样式.组件.插件的使用. 首先下载到本地,在项目中导入使用: 下载的文件中包含:min.css的是压 ...

  10. 《杜拉拉升职记》//TODO

    目录 简介 杜拉拉升职记 杜拉拉2-年华似水 杜拉拉3-我在这战斗的一年里 杜拉拉大结局-与理想有关 结束语 简介 作者李可,女作家,某名校本科毕业,十余年外企生涯,职业经理人,"李可&qu ...