详解JavaScript常量定义
发布时间 - 2026-01-10 22:15:24 点击率:次相信同学们在看见这个标题的时候就一脸懵逼了,什么?JS能常量定义?别逗我好吗?确切的说,JS当中确实没有常量(ES6中好像有了常量定义的关键字),但是深入一下我们可以发现JS很多不为人知的性质,好好利用这些性质,就会发现一个不一样的JS世界。

首先,在JS当中,对象的属性其实还含有自己的隐含性质,比如下面对象:
var obj = {};
obj.a = 1;
obj.b = 2;
在这里我们定义了一个对象 obj ,并且定义了这个对象的两个属性 a 、 b ,我们可以修改这两个属性的值,可以用 delete 关键字删除这两个属性,也可以用 for ... in ... 语句枚举 obj 对象的所有属性,以上的这些操作叫做对象属性的性质,在我们平常编写代码的时候我们会不知不觉的默认了这些性质,把他们认作为JS应有的性质,殊不知这些性质其实是可以修改的。我通常的定义的属性的方法,默认了属性的性质,不过我们也可以在定义属性的时候修改属性的性质,比如:
var obj = {};
obj.a = 1;
obj.b = 2;
//等价于
var obj = {
a: 1,
b: 2
}
//等价于
var obj = {};
Object.defineProperty(obj, "a", {
value: 1, //初始值
writable: true, //可写
configurable: true, //可配置
enumerable: true //可枚举
});
Object.defineProperty(obj, "b", {
value: 2, //初始值
writable: true, //可写
configurable: true, //可配置
enumerable: true //可枚举
});
这里涉及到了一个方法,Object.defineProperty(),该方法是ES5规范中的,该方法的作用是在对象上定义一个新属性,或者修改对象的一个现有属性,并对该属性加以描述,返回这个对象,我们来看一下浏览器兼容性:
| 特性 | Firefox (Gecko) | Chrome | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| 基本支持 | 4.0 (2) | 5 | 9 [1] | 11.60 | 5.1 [2] |
还是天煞的IE8,如果你的项目要求兼容IE8,那么这个方法也就不适用了,不过IE8也对该方法进行了实现,只能在DOM对象上适用,而且有一些独特的地方,在这里就不讲解了。
Object.defineProperty() 方法可以定义对象属性的数据描述和存储描述,这里我们只讲数据描述符,不对存储描述符讲解,数据描述符有以下选项:
configurable 当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false。 enumerable 当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false。 value 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。 writable 当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。
注意,当我们用常规方法定义属性的时候,其除 value 以外的数据描述符默认均为 true ,当我们用 Object.defineProperty() 定义属性的时候,默认为 false。
也就是说,当我们把 writable 设置为 false 的时候,该属性是只读的,也就满足了常量了性质,我们把常量封装在CONST命名空间里面:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: false, //设置属性只读
configurable: true,
enumerable: true
});
console.log(CONST.A); //1
CONST.A = 2; //在严格模式下会抛错,在非严格模式下静默失败,修改无效。
但是这样定义的常量不是绝对的,因为我们依然可以通过修改属性的数据描述符来修改属性值:
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); //2
CONST.A = 3;
console.log(CONST.A); //3
想要做到真正的常量,还需要将属性设置为不可配置:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: false, //设置属性只读
configurable: false, //设置属性不可配置
enumerable: true
});
console.log(CONST.A); //1
CONST.A = 2; //错误!属性只读
Object.defineProperty(CONST, "A", {
value: 2,
writable: true,
configurable: true,
enumerable: true
}); //错误!属性不可配置
但是如果只设置属性为不可配置状态,依然可以对属性值进行修改:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: true, //设置可写
configurable: false, //设置属性不可配置
enumerable: true
});
console.log(CONST.A); //1
CONST.A = 2;
console.log(CONST.A); //2
进而我们可以推断出,configurable 描述符仅冻结属性的描述符,不会对属性值产生影响,也就是说该描述符会冻结 writable、configurable、enumerable 的状态,不会对属性值加以限制:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: false, //设置不可写
configurable: false, //设置属性不可配置
enumerable: false //设置不可枚举
});
Object.defineProperty(CONST, "A", {
value: 2, //该属性本身不受 configurable 的影响,但由于属性不可写,受 writable 的限制
writable: true, //错误!属性不可配置
configurable: true, //错误!属性不可配置
enumerable: true //错误!属性不可配置
});
但是 configurable 的限制有一个特例,就是 writable 可以由 true 改为 false,不能由 false 改为 true:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: true, //设置可写
configurable: false, //设置属性不可配置
enumerable: false //设置不可枚举
});
Object.defineProperty(CONST, "A", {
value: 2, //该属性本身不受 configurable 的影响,由于属性可写,修改成功
writable: false,
configurable: false,
enumerable: false
});
console.log(CONST.A); //2
CONST.A = 3; //错误!属性只读
可枚举描述符用于配置属性是否可以枚举,也就是是否会出现在 for ... in ... 语句中:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
writable: false,
configurable: false,
enumerable: true //可枚举
});
Object.defineProperty(CONST, "B", {
value: 2,
writable: false,
configurable: false,
enumerable: false //不可枚举
});
for (var key in CONST) {
console.log(CONST[key]); //1
};
有了以上的基础,我们也就学会一种定义常量的方法,使用属性的数据描述符,下次我们需要用到常量的时候,就可以定义一个 CONST 命名空间,将常量封装在该命名空间里面,由于属性描述符默认为 false,所以我们也可以这样定义:
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
enumerable: true
});
Object.defineProperty(CONST, "B", {
value: 2,
enumerable: true
});
以上方法是从属性的角度的去定义一组常量,不过我们还可以用另外一种方法,从对象的角度去配置一个对象包括它的所有属性,Object.preventExtensions() 方法可以让一个对象不可扩展,该对象无法再添加新的属性,但是可以删除现有属性:
var CONST = {};
CONST.A = 1;
CONST.B = 2;
Object.preventExtensions(CONST);
delete CONST.B;
console.log(CONST); //CONST: { A: 1}
CONST.C = 3; //错误!对象不可扩展
在该方法的基础之上,我们可以使用 Object.seal() 来对一个对象密封,该方法会阻止对象扩展,并将该对象的所有属性设置为不可配置,但是可写:
var CONST = {};
CONST.A = 1;
CONST.B = 2;
Object.seal(CONST);
CONST.A = 3;
console.log(CONST.A); //3
Object.defineProperty(CONST, "B", {
value: 2,
writable: true,
configurable: true, //错误!属性不可配置
enumerable: false, //错误!属性不可配置
})
CONST.C = 3; //错误!对象不可扩展
也就是说 Object.seal() 方法相当于帮助我们批量的将属性的可配置描述符设置为 false ,所以说在代码实现层面相当于:
Object.seal = function (obj) {
Object.preventExtensions(obj);
for (var key in obj) {
Object.defineProperty(obj, key, {
value: obj[key],
writable: true,
configurable: false,
enumerable: true
})
};
return obj;
}
在以上两个方法基础上,我们可以 Object.freeze() 来对一个对象进行冻结,实现常量的需求,该方法会阻止对象扩展,并冻结对象,将其所有属性设置为只读和不可配置:
var CONST = {};
CONST.A = 1;
CONST.B = 2;
Object.freeze(CONST);
CONST.A = 3; //错误!属性只读
Object.defineProperty(CONST, "B", {
value: 3, //错误!属性只读
writable: true, //错误!属性不可配置
configurable: true, //错误!属性不可配置
enumerable: false, //错误!属性不可配置
})
CONST.C = 3; //错误!对象不可扩展
从代码实现层面上相当于:
Object.freeze = function (obj) {
Object.preventExtensions(obj);
for (var key in obj) {
Object.defineProperty(obj, key, {
value: obj[key],
writable: false,
configurable: false,
enumerable: true
})
};
return obj;
}
最后我们在来看一下这三个方法的兼容性:
Object.preventExtensions()
| Feature | Firefox (Gecko) | Chrome | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| Basic support | 4 (2.0) | 6 | 9 | 未实现 | 5.1 |
Object.seal()
| Feature | Firefox (Gecko) | Chrome | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| Basic support | 4 (2.0) | 6 | 9 | 未实现 | 5.1 |
Object.freeze()
| Feature | Firefox (Gecko) | Chrome | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| Basic support | 4.0 (2) | 6 | 9 | 12 | 5.1 |
到底还是万恶的IE,均不兼容IE8
现在,我们也就有了两种方法在JS中定义常量,第一种方法是从属性层面上来实现,在命名空间上可以继续添加多个常量,而第二种方法是从对象层面上来实现,对冻结对象所有属性以及对象本身:
//第一种方法:属性层面,对象可扩展
var CONST = {};
Object.defineProperty(CONST, "A", {
value: 1,
enumerable: true
});
//第二种方法:对象层面,对象不可扩展
var CONST = {};
CONST.A = 1;
Object.freeze(CONST);
关于JS常量的问题就讲到这里了,许多书籍在介绍JS基础的时候都会提到JS当中没有常量,导致许多JS开发者在一开始就默认了JS是没有常量的这一说法。从严格语法意义上来讲,JS确实是没有常量的,但是我们可以通过对知识的深入和创造力来构建我们自己的常量,知识是死的,人是活的,只要我们不停的探索,满怀着创造力,就会发现其中不一样的世界。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
# js
# 常量
# 简单掌握JavaScript中const声明常量与变量的用法
# 在JavaScript里嵌入大量字符串常量的实现方法
# IE6下出现JavaScript未结束的字符串常量错误的解决方法
# JavaScript 未结束的字符串常量常见解决方法
# JavaScript中全局变量、函数内变量以及常量表达式的效率测试
# JavaScrip关于创建常量的知识点
# 也就
# 设置为
# 默认为
# 我们可以
# 种方法
# 可以用
# 是从
# 自己的
# 当我们
# 就会
# 在这里
# 出现在
# 这两个
# 可以通过
# 不受
# 也就是说
# 会对
# 来实现
# 才能够
# 装在
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
实例解析Array和String方法
Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理
如何快速搭建安全的FTP站点?
免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?
微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】
ChatGPT常用指令模板大全 新手快速上手的万能Prompt合集
Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】
如何快速上传自定义模板至建站之星?
大连网站制作公司哪家好一点,大连买房网站哪个好?
如何挑选优质建站一级代理提升网站排名?
jQuery 常见小例汇总
Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】
iOS验证手机号的正则表达式
实例解析angularjs的filter过滤器
如何在 React 中条件性地遍历数组并渲染元素
高性能网站服务器部署指南:稳定运行与安全配置优化方案
ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法
Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱动更新修复【详解】
济南网站建设制作公司,室内设计网站一般都有哪些功能?
企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?
Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】
公司门户网站制作流程,华为官网怎么做?
Laravel如何保护应用免受CSRF攻击?(原理和示例)
Laravel如何生成URL和重定向?(路由助手函数)
Laravel模型事件有哪些_Laravel Model Event生命周期详解
网站图片在线制作软件,怎么在图片上做链接?
文字头像制作网站推荐软件,醒图能自动配文字吗?
Laravel如何实现全文搜索_Laravel Scout集成Algolia或Meilisearch教程
免费网站制作appp,免费制作app哪个平台好?
打开php文件提示内存不足_怎么调整php内存限制【解决方案】
Laravel如何正确地在控制器和模型之间分配逻辑_Laravel代码职责分离与架构建议
如何在景安云服务器上绑定域名并配置虚拟主机?
Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程
laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法
Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程
Laravel怎么生成URL_Laravel路由命名与URL生成函数详解
UC浏览器如何设置启动页 UC浏览器启动页设置方法
Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置
Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】
如何用AWS免费套餐快速搭建高效网站?
Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知
如何确认建站备案号应放置的具体位置?
html5audio标签播放结束怎么触发事件_onended回调方法【教程】
弹幕视频网站制作教程下载,弹幕视频网站是什么意思?
laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法
大连 网站制作,大连天途有线官网?
edge浏览器无法安装扩展 edge浏览器插件安装失败【解决方法】
谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复

