摘要:沒有模塊化的支持,使用開發大型應用將舉步維艱,所以經過大量的實踐,社區制定了一些模塊加載方案,最主要的有運行于瀏覽器的方案和運行于以為代表的服務端的方案。該方法返回被凍結的對象。
背景
ES Module是JavaScript在ES2015版本開始提供的語言標準級別的模塊化方案,在此之前JavaScript一直沒有語言級別的模塊化體系。沒有模塊化的支持,使用JavaScript開發大型應用將舉步維艱,所以經過大量的實踐,社區制定了一些模塊加載方案,最主要的有運行于瀏覽器的AMD方案和運行于以Nodejs為代表的服務端的CommonJS方案。
由于Webpack和Babel等打包、轉義工具的出現,開發者已經可以在開發中使用ES Module,AMD已是明日黃花,使用的人越來越少,不太值得去關注。但CommonJS方案由于Nodejs在前端構建工具和服務端中的普及度,在Nodejs全面支持ES Module、老版本Nodejs消亡之前,我們還是要關注CommonJS方案以及它與ES Module之間的區別,以免搞混、記憶混淆,釀成bug。為了為后面的禁止點做鋪墊,先讓我們來了解或回顧兩個API:Object.preventExtensions和Object.freeze。
Object.preventExtensionsObject.preventExtensions()將對象標記為不再可擴展,因此它將永遠不會具有超出它被標記為不可擴展的屬性。注意,一般來說,不可擴展對象的屬性可能仍然可被刪除。嘗試將新屬性添加到不可擴展對象將靜默失敗或拋出TypeError(在strict mode下)
當我們在嚴格模式下,嘗試對不可拓展的對象進行屬性添加時,就會拋出異常,具體代碼如下:
"use strict" var obj = { age: 23, name: "rioli", city: ["sz", "jy"] }; Object.preventExtensions(obj); obj.province = "GD";
運行結果:
Uncaught TypeError: Cannot add property "province", object is not extensibleObject.freeze
Object.freeze() 方法可以凍結一個對象,凍結指的是不能向這個對象添加新的屬性,不能修改其已有屬性的值,不能刪除已有屬性,以及不能修改該對象已有屬性的可枚舉性、可配置性、可寫性。該方法返回被凍結的對象。
當我們在嚴格模式下,嘗試對已凍結的對象進行屬性修改時,就會拋出異常,具體代碼如下:
"use strict" var obj = { age: 23, name: "rioli", city: ["sz", "jy"] }; Object.freeze(obj); obj.age = 26;
運行結果:
Uncaught TypeError: Cannot assign to read only property "age" of object "#構建不可拓展的凍結對象
我們可以利用Object.preventExtensions和Object.freeze這兩個API來組合構建一個不可拓展的凍結對象,即:不能對對象的頂級屬性對象增、刪、改等操作。
"use strict" var obj = { age: 23, name: "rioli", city: ["sz", "jy"] }; Object.freeze(obj); Object.preventExtensions(obj); // obj.age = 26; 修改頂級屬性將引發報錯 // obj.province = "GD"; 新增頂級屬性將引發報錯 // delete obj.name; 刪除頂級屬性將引發報錯 // 但仍然可以修改對象的子對象的屬性,因為修改對象的子對象的屬性并不會修改子對象的引用,對于引用類型來說等于沒有發生值的改變 obj.city[0] = "zq"; obj.city.push("st");ES Module禁忌之不可以修改整體導入模塊對象的直接屬性
為什么會列出這個禁忌,這是因為在CommonJS方案中,你是可以修改整體導入模塊對象的直接屬性的,長期在CommonJS在ES Module中交叉使用,難免會造成不必要的記憶混淆。但是在 ES Module中,整體導入的模塊對象是一個不可拓展的凍結的常量對象,對其直接屬性的修改和新增將引發報錯。
假定我們正處于CommonJs環境下,例如NodeJS中,我們導入等個模塊,然后嘗試對模塊對象的屬性進行修改和新增,具體代碼如下:
lib.js
exports.time = Date.now(); exports.getCurrrentYear = function () { return new Date().getFullYear(); } exports.people = { age: 26, name: "rioli", cities: ["jieyang", "shenzhen"] };
main.js
const lib = require("./lib"); const people = lib.people; const print = (data) => { console.log("==================================="); console.log(data); }; print(people); print(lib); people.age = 999; print(people); people.father = "baba"; print(people); lib.people = 23; print(lib); lib.people.age = 666; print(lib); lib.provices = ["GD", "FJ"]; print(lib);
運行結果通過,控制臺輸出結果如下:
=================================== { age: 26, name: "rioli", cities: [ "jieyang", "shenzhen" ] } =================================== { time: 1545274516494, getCurrrentYear: [Function], people: { age: 26, name: "rioli", cities: [ "jieyang", "shenzhen" ] } } =================================== { age: 999, name: "rioli", cities: [ "jieyang", "shenzhen" ] } =================================== { age: 999, name: "rioli", cities: [ "jieyang", "shenzhen" ], father: "baba" } =================================== { time: 1545274516494, getCurrrentYear: [Function], people: 23 } =================================== { time: 1545274516494, getCurrrentYear: [Function], people: 23 } =================================== { time: 1545274516494, getCurrrentYear: [Function], people: 23, provices: [ "GD", "FJ" ] }
在ES Module環境下,整體導入的模塊對象,但我們對其進行修改和新增屬性的時候,其表現和上述利用Object.preventExtensions和Object.freeze這兩個API來組合構建一個不可拓展的凍結對象的表現一樣,即:這個模塊對象是一個不可拓展的凍結的常量對象。演示代碼如下:
lib.mjs
export const time = Date.now(); export function getCurrrentYear() { return new Date().getFullYear(); } export const people = { age: 26, name: "rioli", cities: ["jieyang", "shenzhen"] };
main.mjs
import { people } from "./lib.mjs"; import * as lib from "./lib.mjs"; // 首先定一個基調,其實但我們用 import * as xx from "yy" 將一個模塊做整體導入時,此時xx會作為作為模塊命名空間 const print = (data) => { console.log("==================================="); console.log(data); }; print(people); print(lib); // 允許修改 people.age = 999; print(people); // 允許修改 people.father = "baba"; print(people); // 不允許修改,因為作為整體導入時,模塊對象的直接一級屬性是只讀屬性,修改將引發報錯 try { lib.people = 23; print(lib); } catch (e) { print(e); print("不允許修改lib.people,因為作為整體導入時,模塊對象的直接一級屬性是只讀屬性,修改將引發報錯"); } // 允許修改,因為作為整體導入時,模塊對象的直接一級屬性是只讀屬性,但一級 // 屬性引用的對象不是只讀對象,可以修改其屬性(只要沒有被設置為不可寫) lib.people.age = 666; print(lib); // 整體導入時,不允許給模塊對象新增屬性,因為整體導入時的模塊對象是一個不可拓展的對象,不可以給模塊對象新增任何屬性 try { lib.provices = ["GD", "FJ"]; print(lib); } catch (e) { print(e); print("不允許對lib對象新增屬性,整體導入時,不允許給模塊對象新增屬性,因為整體導入時的模塊對象是一個不可拓展的對象,不可以給模塊對象新增任何屬性"); }
具體運行結果:
=================================== { age: 26, name: "rioli", cities: [ "jieyang", "shenzhen" ] } =================================== { getCurrrentYear: [Function: getCurrrentYear], people: { age: 26, name: "rioli", cities: [ "jieyang", "shenzhen" ] }, time: 1545275257126 } =================================== { age: 999, name: "rioli", cities: [ "jieyang", "shenzhen" ] } =================================== { age: 999, name: "rioli", cities: [ "jieyang", "shenzhen" ], father: "baba" } =================================== TypeError: Cannot assign to read only property "people" of object "[object Module]" at ModuleJob.run (internal/modules/esm/ModuleJob.js:106:14) at=================================== 不允許修改lib.people,因為作為整體導入時,模塊對象的直接一級屬性是只讀屬性,修改將引發報錯 =================================== { getCurrrentYear: [Function: getCurrrentYear], people: { age: 666, name: "rioli", cities: [ "jieyang", "shenzhen" ], father: "baba" }, time: 1545275257126 } =================================== TypeError: Cannot add property provices, object is not extensible at ModuleJob.run (internal/modules/esm/ModuleJob.js:106:14) at =================================== 不允許對lib對象新增屬性,整體導入時,不允許給模塊對象新增屬性,因為整體導入時的模塊對象是一個不可拓展的對象,不可以給模塊對象新增任何屬性
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100214.html
摘要:如果你還沒讀過上篇上篇和中篇并無依賴關系,您可以讀過本文之后再閱讀上篇,可戳面試篇寒冬求職季之你必須要懂的原生上小姐姐花了近百個小時才完成這篇文章,篇幅較長,希望大家閱讀時多花點耐心,力求真正的掌握相關知識點。 互聯網寒冬之際,各大公司都縮減了HC,甚至是采取了裁員措施,在這樣的大環境之下,想要獲得一份更好的工作,必然需要付出更多的努力。 一年前,也許你搞清楚閉包,this,原型鏈,就...
摘要:循環可以使用的范圍包括數組和結構某些類似數組的對象對象,以及字符串。只能遍歷數組,不能中斷,返回值是修改后的數組。除了之外,等,也有同樣的問題。聲明一個只讀的常量。這在語法上,稱為暫時性死區。暫時性死區也意味著不再是一個百分百安全的操作。 互聯網寒冬之際,各大公司都縮減了HC,甚至是采取了裁員措施,在這樣的大環境之下,想要獲得一份更好的工作,必然需要付出更多的努力。 一年前,也許你搞清楚閉包...
摘要:只能遍歷數組,不能中斷,返回值是修改后的數組。這在語法上,稱為暫時性死區。作用域鏈無論是還是查詢,都會在當前的作用域開始查找,如果沒有找到,就會向上級作用域繼續查找目標標識符,每次上升一個作用域,一直到全局作用域為止。 互聯網寒冬之際,各大公司都縮減了HC,甚至是采取了裁員措施,在這樣的大環境之下,想要獲得一份更好的工作,必然需要付出更多的努力。 一年前,也許你搞清楚閉包,this,原...
摘要:半路出家的前端程序員應該不在少數,我也是其中之一。年,馮馮同事兼師兄看我寫太費勁,跟我說對面樓在找,問我要不要學,說出來可能有點丟人,但是在那之前,我真得不知道什么是,什么是。 半路出家的前端程序員應該不在少數,我也是其中之一。 為何會走向前端 非計算機專業的我,畢業之后,就職于一家電力行業公司,做過設備調試、部門助理、測試,也寫過一段時間的QT,那三年的時間,最難過的不是工作忙不忙,...
閱讀 5739·2021-11-24 10:25
閱讀 2689·2021-11-16 11:44
閱讀 3843·2021-10-11 11:09
閱讀 3172·2021-09-02 15:41
閱讀 3256·2019-08-30 14:14
閱讀 2271·2019-08-29 14:10
閱讀 2345·2019-08-29 11:03
閱讀 1125·2019-08-26 13:47