全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

详解JavaScript常量定义

相信同学们在看见这个标题的时候就一脸懵逼了,什么?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关于创建常量的知识点  # 也就  # 设置为  # 默认为  # 我们可以  # 种方法  # 可以用  # 是从  # 自己的  # 当我们  # 就会  # 在这里  # 出现在  # 这两个  # 可以通过  # 不受  # 也就是说  # 会对  # 来实现  # 才能够  # 装在 


相关文章: 如何高效完成自助建站业务培训?  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  招贴海报怎么做,什么是海报招贴?  青浦网站制作公司有哪些,苹果官网发货地是哪里?  建站之星如何快速生成多端适配网站?  如何在香港免费服务器上快速搭建网站?  建站主机选哪种环境更利于SEO优化?  如何通过NAT技术实现内网高效建站?  如何在Golang中引入测试模块_Golang测试包导入与使用实践  如何在万网自助建站中设置域名及备案?  如何快速搭建高效WAP手机网站?  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  如何撰写建站申请书?关键要点有哪些?  公众号网站制作网页,微信公众号怎么制作?  商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?  济南网站制作的价格,历城一职专官方网站?  如何用搬瓦工VPS快速搭建个人网站?  建站之家VIP精选网站模板与SEO优化教程整合指南  如何使用Golang安装API文档生成工具_快速生成接口文档  制作网站的过程怎么写,用凡科建站如何制作自己的网站?  建站之星五站合一营销型网站搭建攻略,流量入口全覆盖优化指南  建站主机如何安装配置?新手必看操作指南  高端网站建设与定制开发一站式解决方案 中企动力  个人摄影网站制作流程,摄影爱好者都去什么网站?  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  如何快速生成凡客建站的专业级图册?  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  广东企业建站网站优化与SEO营销核心策略指南  详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)  兔展官网 在线制作,怎样制作微信请帖?  电脑免费海报制作网站推荐,招聘海报哪个网站多?  创业网站制作流程,创业网站可靠吗?  如何快速建站并高效导出源代码?  如何高效搭建专业期货交易平台网站?  c++ stringstream用法详解_c++字符串与数字转换利器  如何在景安云服务器上绑定域名并配置虚拟主机?  网站制作公司,橙子建站是合法的吗?  如何配置支付宝与微信支付功能?  如何在阿里云虚拟服务器快速搭建网站?  Python多线程使用规范_线程安全解析【教程】  如何通过VPS建站实现广告与增值服务盈利?  西安大型网站制作公司,西安招聘网站最好的是哪个?  深入理解Android中的xmlns:tools属性  如何通过wdcp面板快速创建网站?  自助网站制作软件,个人如何自助建网站?  导航网站建站方案与优化指南:一站式高效搭建技巧解析  如何快速搭建二级域名独立网站?  专业制作网站的公司哪家好,建立一个公司网站的费用.有哪些部分,分别要多少钱?  c# F# 的 MailboxProcessor 和 C# 的 Actor 模型  文字头像制作网站推荐软件,醒图能自动配文字吗? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。