Javascript学习之常量定义

相信大部分人在看见这个标题的时候就一脸懵逼了,什么?javascript能常量定义?别逗我好吗?确切的说,JS当中确实没有常量(ES6中好像有了常量定义的关键字),但是深入一下我们可以发现JS很多不为人知的性质,好好利用这些性质,就会发现一个不一样的JS世界。一起来看看吧,希望对大家学习javascript有所帮助。

首先,在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)ChromeInternet ExplorerOperaSafari

基本支持4.0 (2)59 [1]11.605.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); //1CONST.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); //2CONST.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); //1CONST.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); //1CONST.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); //2CONST.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()

Object.seal()

Object.freeze()

到底还是万恶的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确实是没有常量的,但是我们可以通过对知识的深入和创造力来构建我们自己的常量,知识是死的,人是活的,只要我们不停的探索,满怀着创造力,就会发现其中不一样的世界。

来源:码农网

时间: 2024-10-29 10:45:36

Javascript学习之常量定义的相关文章

初级篇第十一期:学习使用常量定义和宏定义

学习建议:自己动手,丰衣足食 学习周期:1周 学习目的:熟练使用常量定义和宏定义 学习答疑:欢迎来技术群里提问并做分享 学习工具:Xcode开发环境 学习内容:熟悉项目开发中常用的两个定义 我们一般定义常量数字和字符串的时候一般会考虑用常量来定义   static CGFloat const kDefaultColorLayerOpacity = 0.4f; 一般定义宏的时候,都是用来定义方法,用宏的时候一定要多注意使用哦,会关系到括号的问题   #define SWH_RGBA(r, g, b

javascript学习

javascript 学习 title: Javascripttags: javascript,学习grammar_cjkRuby: true--- 定义变量 三种形式 var name; var name = "zhang san"; var name; name = "zhang san"; Javascript 的数据类型 6种数据类型 字符串单引号或双引号 var name = "zhang san"; var name = 'zhang

javascript学习3-自定义函数

javascript自定义函数,很简单的小例子. 实现效果:输入两个数和运算符号,根据不同运算符对数据进行计算,返回值 代码: 1 <html> 2 <head> 3 <script type="text/javascript"> 4 var num1=window.prompt('请输入第一个num'); 5 var num2=window.prompt('请输入第二个num'); 6 var operator=window.prompt('请输入

JavaScript 常量定义

相信同学们在看见这个标题的时候就一脸懵逼了,什么?JS能常量定义?别逗我好吗?确切的说,JS当中确实没有常量(ES6中好像有了常量定义的关键字),但是深入一下我们可以发现JS很多不为人知的性质,好好利用这些性质,就会发现一个不一样的JS世界. 首先,在JS当中,对象的属性其实还含有自己的隐含性质,比如下面对象: 1 var obj = {}; 2 obj.a = 1; 3 obj.b = 2; 在这里我们定义了一个对象 obj ,并且定义了这个对象的两个属性 a . b ,我们可以修改这两个属性

javascript学习笔记---ECMAScriptECMAScript 对象----定义类或对象

使用预定义对象只是面向对象语言的能力的一部分,它真正强大之处在于能够创建自己专用的类和对象. ECMAScript 拥有很多创建对象或类的方法. 原始的方式 因为对象的属性可以在对象创建后动态定义(后绑定),类似下面的代码: var oCar = new Object; oCar.color = "blue"; oCar.doors = 4; oCar.mpg = 25; oCar.showColor = function() { alert(this.color); };不过这里有一

C#与Java对比学习:类型判断、类与接口继承、代码规范与编码习惯、常量定义(转载)

C#与Java对比学习:类型判断.类与接口继承.代码规范与编码习惯.常量定义 类型判断符号: C#:object a;  if(a is int) { }  用 is 符号判断 Java:object a; if(a instanceof Integer) { } 用 instanceof 符号判断 类与接口的继承: C#:public class MDataRow : List<MDataCell>, IDataRecord, ICustomTypeDescriptor Java:publi

JavaScript学习12 JS中定义对象的几种方式

JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工厂方式 3.构造函数方式 4.原型("prototype")方式 5.动态原型方式 一.基于已有对象扩充其属性和方法 <script type="text/javascript"> var object = new Object(); object.name

JavaScript学习记录day5-函数的定义和调用

JavaScript学习记录day5-函数的定义和调用 [TOC] 1. 定义函数 在JavaScript中,定义函数的方式如下: function abs(x) { if (x >= 0) { return x; } else { return -x; } } 上述abs()函数的定义如下: function指出这是一个函数定义:abs是函数的名称:(x)括号内列出函数的参数,多个参数以,分隔:{ ... }之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句.请注意,函数体内部的语句在

【Struts2学习笔记(4)】指定需要Struts 2处理的请求后缀和细说常量定义

一.指定需要Struts 2处理的请求后缀 前面我们都是默认使用.action后缀访问Action.其实默认后缀是可以通过常量"struts.action.extension"进行修改的,例如:我们可以配置Struts 2只处理以.do为后缀的请求路径: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software