相信同學們在看見這個標題的時候就一臉懵逼了,什麼? 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确实是没有常量的,但是我们可以通过对知识的深入和创造力来构建我们自己的常量,知识是死的,人是活的,只要我们不停的探索,满怀着创造力,就会发现其中不一样的世界
以上就是JavaScript 常量定义详解的内容,更多相关内容请关注PHP中文网(www.php.cn)!

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

禪工作室 13.0.1
強大的PHP整合開發環境

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

記事本++7.3.1
好用且免費的程式碼編輯器