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