前言
其實我個人認為JavaScript
是一種非常隨便的語言,也是一門很神奇很強大的語言。
因為之前使用過一段時間的JavaScript
並做了些學習筆記都是放在word
上的顯得十分雜亂,所以這次也是打算認認真真的重新填一下坑並且認真整理一下JavaScript
筆記到博客園。
以前在群里聊JavaScript
的時候會經常出現一張圖,我認為這個很有意思,所以就放在這里做一個填坑目標吧。
https://www.w3cschool.cn/javascript/javascript-skillmap.html 這里放上一個學習路線圖,非常詳細非常精彩。當然我的筆記不可能做的十分的全面,所以可以配合看這張學習路線圖與筆記,這個路線圖好像有很多新版特性都沒介紹到,不過在我的筆記中會有相應的介紹。
我還是希望將整個的筆記好好整理一下,並且以一種文檔格式進行書寫,也方便后期查閱。
理論知識
語言介紹
JavaScript
官方名稱是 ECMAScript
是一種屬於網絡的腳本語言,已經被廣泛用於Web應用開發,常用來為網頁添加各式各樣的動態功能,為用戶提供更流暢美觀的瀏覽效果。
1995年2月Netscape的布蘭登.艾奇
開發了針對網景公司的 Netscape Navigator
瀏覽器的腳本語言LiveScript
。之后Netscape與Sun公司聯盟后LiveScript
更名為JavaScript
。
微軟在JavaScript
發布后為了搶占市場推出了JavaScript
。為了讓腳本語言規范不在混亂,根據JavaScript 1.1
版本推出了ECMA-262
的腳本語言標准。
ECMA是歐洲計算機制造商協會由Sum、微軟、NetScape公司的程序員組成。
文檔中會經常使用
JS
簡寫來代替JavaScript
Ps:其實整個JavaScript
最早的開發周期只用了兩周,所以在未來很長一段時間里JavaScript
的語法非常混亂,但是隨着時間的更迭慢慢的越來越完善起來。
適用場景
-
瀏覽器網頁端開發
-
做為服務器后台語言使用
-
移動端手機APP開發,如Facebook的
-
跨平台的桌面應用程序,如使用
所以
JS
是一專多能的語言,非常適合學習使用。
發展歷史
-
1994年Netscape(網景)公司發布了
Navigator
瀏覽器1.0版本,市場占用率超過90% -
1995年發布了
JavaScript
語言 -
1996年 JS在
Navigator
瀏覽器中使用 -
1996年微軟發布
JScript
在IE3.0中使用 -
1996年11月網景公司將JS提交給ECMA(國際標准化組織)成為國際標准,用於對抗微軟。
由ECMA的第39號技術專家委員會(Technical Committee 39,簡稱TC39)負責制訂ECMAScript標准,成員包括Microsoft、Mozilla、Google等大公司。
-
1997年 ECMA發布ECMA-262標准,推出瀏覽器標准語言
ECMAScript 1.0
ECMAScript 是標准而Javascript是實現
-
...
-
2009年ECMAScript 5.0發布
-
2011年ECMAScript5.1發布,成為ISO國際標准,從而推動所有瀏覽器都支持
-
...
-
2015年ECMAScript6發布,更名為ECMAScript 2015。
-
2016年ECMAScript7發布,ECMAScript2016
-
2017年ECMAScript8發布,ECMAScript2017
-
2018年ECMAScript9發布,ECMAScript2018
-
2019年ECMAScript10,ECMAScript2019
-
2020年ECMAScript11,ECMAScript2020
-
....
從2015年開始 tc39
委員會決定每年發布新的ECMAScript版本
chrome使用
在學習Js
的過程中,推薦使用chrome
瀏覽器作為你的開發工具。
引入方式
嵌入式
在HTML
文檔中使用<script>
標簽,在<script>
標簽中嵌入Js
代碼即可,關於type
什么的文檔類型聲明可寫可不寫。
使用這種在方式最好是將Js
代碼寫在尾部。也就是寫在HTML
與CSS
代碼之后。
這種做法是因為如果我們的Js
代碼需要去查找某一標簽而將其放在頭部的話HTML
的代碼可能還沒有加載出來,會出現一些不穩定的特殊情況。
我個人是非常喜歡夾在<body>
標簽后的...
<!DOCTYPE html> <html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head><body></body> <script> console.log("hello,world"); // hello,world </script> </html>
引入式
同樣的,也是使用<script>
標簽,並為其src
屬性指定好Js
文件路徑即可,關於type
什么的文檔類型聲明可寫可不寫。
還是推薦將它放在尾部,但是也有很多是放在<head>
標簽中的。
<script src="./first_js.js" type="application/x-javascript"></script>
代碼注釋
在Js
中的注釋有兩種,一種單行注釋,一種多行注釋。
單行注釋
使用//
放在語句前,即可完成單行注釋。
<script> // 下面是個自執行函數 (function (){ console.log("hello,world"); })() </script>
多行注釋
使用/*
開頭,*/
結束,可包含多行。
<script> /* 下面是個自執行函數 它沒有參數 */ (function (){ console.log("hello,world"); })() </script>
自動分號
自動分號
在一段語句結束后,應當加上;
號,但是這並不是強制性的而是一種規范。
<script> (function (){ console.log("hello,world"); alert("hello,world"); document.write("hello,world"); })(); </script>
意義作用
盡管你可以不加,但是請注意前端的代碼一般來說在上線部署后都會進行壓縮。
在使用構建工具時,不使用分號結束可能會造成異常!
我們可以看一下一個非常常見的Js
庫jQuery
的生產版源碼。
變量聲明
變量就是存儲着一個允許變的值。
如年齡,愛好,居住地等都可以定義為變量。
變量的使用都是先聲明后使用,這個應該是非常基礎的,在每個語言中都是這樣。
那么在JavaScript
中關於變量聲明有很多有意思的點,可以慢慢往下看。
命名規則
Js
中的變量是弱類型可以保存所有類型的數據,即變量沒有類型而值有類型。變量名以字母
、$
、_
開始,后跟字母
、數字
、_
。
Js
中的語言關鍵字不能用來做變量名,比如 true、if、while、class
等。
請不要輕易使用用
$
來作為變量名的起始,因為它被jQuery
給霸占了,目前請謹記這一點。
正確的命名規范
<script> var username = "Yunya"; var _age = 18; var $select = "Please do not use $ to start variable names lightly, although it is not wrong"; </script>
錯誤的命名規范
<script> var 9username = "ERROR"; var (age = "ERROR"; var --select = "ERROR"; </script>
聲明賦值
早期的Js
使用者都同一用var
來聲明變量,但是es6
后推出了let
,具體的作用我們這里先不管。先看一下最基本的使用,由於Js
是一門弱類型語言,所以不用強調變量聲明的類型。
先聲明並賦值,后使用。
<script> // 先聲明並且賦值 var username = "YunYa"; let age = 18; // 后使用 console.log(username); // YunYa console.log(age); // 18 </script>
上面是最常用的方式,其實也可以先聲明,再賦值,后使用。
<script> // 先聲明 var username; let age; // 再賦值 username = "YunYa"; age = 18; // 后使用 console.log(username); // YunYa console.log(age); // 18 </script>
我們還可以一次性聲明賦值多個變量。
<script> var username = "YunYa", age = 18, gender = "male"; console.log(username); // YunYa console.log(age); // 18 console.log(gender); // male </script>
也可以進行鏈式賦值。
<script> var a=b=c=1; console.log(a); // 1 console.log(b); // 1 console.log(c); // 1 </script>
弱類型
弱類型其實就是說存的是什么類型的值,就是什么類型的變量。
不用提前聲明變量變量再進行存儲。
<script> var username = "YunYa"; var age = 18; var other = {"hobby":"basketball","marriage":false,"height":192,"weight":126,}; // typeof 是查看變量的類型方法 console.log(typeof username); // string console.log(typeof age); // number console.log(typeof other); // object </script>
常量聲明
常量存儲一些不允許被改變的值。
如PI
,性別,籍貫等等都可以定義為常量。
命名規則
常量的命名規則和變量基本一致,但是一定要注意!常量的命名規則是全部大寫形式,這是一種規范。
常量名建議全部大寫
只能聲明一次變量
聲明時必須同時賦值
不允許再次全新賦值
可以修改引用類型變量的值
擁有塊、函數、全局作用域
<script> // 常量聲明全用大寫 const PI = 3.1415926535897; console.log(PI); // 3.1415926535897 </script>
聲明賦值
常量我們一般都會使用const
來進行聲明並賦值,它有一個特點,即聲明之后不允許改變。
<script> // 常量聲明全用大寫 const PI = 3.1415926535897; PI = 100; console.log(PI); // Uncaught TypeError: Assignment to constant variable. // 類型錯誤: 將值分配給了一個不變的變量(常量) </script>
var let const 區別
意義作用
不使用他們會全部亂套,因為有不同的作用域存在,如果不使用他們則代表將所有的變量全部放進全局作用域中。
代碼及易出現問題!
<script> username = "YunYa"; function test(params) { console.log(username); // YunYa username = "Jack"; console.log(username); // Jack }; test(); // 可以看到,被污染了.. console.log(username); // Jack </script>
<script> var username = "YunYa"; function test(params) { console.log(username); // undefined 這是因為自身局部作用域有一個 username,但是此時還未定義。所以不去找全局的name了,只好顯示undefined。 var username = "Jack"; console.log(username); // Jack }; test(); // 可以看到,未污染了.. console.log(username); // YunYa </script>
變量提升
變量提升其實你可以將它當做是預加載,它會預先來檢查所有聲明的變量名字是否合法。
<script> console.log("執行我了..."); // 沒執行 let for = "YunYa"; // Uncaught SyntaxError: Unexpected token 'for' console.log("執行我了..."); // 沒執行 </script>
很明顯的看到,代碼都沒執行,但是卻拋出異常。這是預加載做的第一步事情,檢查名稱是否合法。
當預加載第一步執行完畢后,開始做第二步事情,對var
聲明的變量進行開辟內存空間(注意:是開辟內存空間,並未賦值,並且let
與const
聲明的變量都不會開辟內存空間)。
也就是說,當Js
代碼開始運行時,檢查完變量名是否合法后,它會預先拿到所有var
聲明的變量名的名字(函數名也會),但並不會進行賦值。
只有當真正開始執行代碼並且走到賦值代碼時才會進行賦值操作,所以你可以看到下面的這種情況。
<script> // 為什么沒拋出異常? console.log(username) // undefined var username = "YunYa"; </script>
如果使用一個未被定義的名字,那么才是真正的會拋出異常。
<script> console.log(age) // Uncaught ReferenceError: age is not defined var username = "YunYa"; </script>
TDZ暫時性死區
TDZ
又稱暫時性死區,指變量在作用域內已經存在,但必須在let/const
聲明后才可以使用。
TDZ
可以讓程序保持先聲明后使用的習慣,讓程序更穩定。
變量要先聲明后使用
建議使用
let
/const
而少使用var
使用let/const
聲明的變量在聲明前存在臨時性死區(TDZ
)使用會發生錯誤。
其實說白了就是let
和const
來聲明的變量必須遵守先聲明后使用的原則。
<script> // 意思就說,不能在完成之前訪問name這個變量 console.log(username) // Uncaught ReferenceError: Cannot access 'name' before initialization let username = "YunYa"; </script>
<script> // 意思就說,不能在完成之前訪問name這個變量 console.log(username) // Uncaught ReferenceError: Cannot access 'username' before initialization const username = "YunYa"; </script>
塊作用域
作用域你可以簡單的理解為,只要有{}
括起來的地方全是作用域,它的作用就是讓相同名字的變量名之間互不沖突。
作用域 | |
---|---|
全局作用域 | 變量名全局有效。 |
局部作用域 | 變量名在函數,類中有效,可訪問全局作用域中的變量。 |
塊作用域 | 對於var 來說不存在,對於let 來說則存在,常見for 循環,通俗講只要有不是局部作用域和全局作用域而被{} 包裹的代碼塊全部稱為塊作用域。 |
注意:let
與const
都具有塊作用域,而var
則不具有。
下面例子使用var
則會造成污染(會當成全局作用域來看待,不具有塊作用域),而使用let
則不會(const
不可多次賦值應用)。
<script> var i = 100; for(var i = 0;i < 5;i++){ console.log(i); // 0 1 2 3 4 } // 此時我們在想用 100 的那個 i 抱歉,被替換了。 console.log(i); // 5 </script>
<script> let i = 100; for(let i = 0;i < 5;i++){ console.log(i); // 0 1 2 3 4 } // 未替換。 console.log(i); // 100 </script>
重復定義
在同一作用域下,使用var
定義的變量名可重復定義,而let
與const
則不可重復定義。
var
<script> var num = 100; var num = 1000; // 明顯不太好 console.log(num); // 1000 </script>
let
<script> // Uncaught SyntaxError: Identifier 'num' has already been declared // 語法錯誤 num 已經被定義 let num = 100; let num = 1000; console.log(num); </script>
const
<script> // Uncaught SyntaxError: Identifier 'num' has already been declared // 語法錯誤 num 已經被定義 const num = 100; const num = 1000; console.log(num); // 1000 </script>
windows對象
使用var
定義的變量會被存入windows
對象,而let
與const
卻不會。
var
<script> var username = "YunYa"; console.log(window["username"]); // YunYa </script>
let
<script> let username = "YunYa"; console.log(window["username"]); // undefined </script>
const
<script> const username = "YunYa"; console.log(window["username"]); // undefined </script>
差異總結
var let const區別 | |||
---|---|---|---|
var | let | const | |
變量提升 | 有 | 無 | 無 |
TDZ暫時性死區 | 無 | 有 | 有 |
塊作用域 | 無 | 有 | 有 |
同一作用域下重復定義 | 允許 | 不允許 | 不允許 |
windows對象 | 添加 | 不添加 | 不添加 |
總結:盡量少使用var 多使用let 。 |
嚴格模式
嚴格模式可以讓我們及早發現錯誤,使代碼更安全規范,推薦在代碼中一直保持嚴格模式運行。
只需要在書寫代碼前加上"use strict";
即可。
主流框架都采用嚴格模式,嚴格模式也是未來JS標准,所以建議代碼使用嚴格模式開發
基本差異
變量必須使用關鍵詞聲明,未聲明的變量不允許賦值。
<script> // Uncaught ReferenceError: username is not defined "use strict"; username = "YunYa"; console.log(username); </script>
關鍵詞不允許做變量使用
<script> // Uncaught SyntaxError: Unexpected token 'try' "use strict"; var try = "YunYa"; console.log(username); </script>
變量參數不允許重復定義
<script> // Uncaught SyntaxError: Duplicate parameter name not allowed in this context "use strict"; function test(x,x){ console.log("執行了..."); }; test(); </script>
單獨為函數設置嚴格模式
<script> function test(){ "use strict"; console.log("執行了..."); // 執行了... }; test(); </script>
為了在多文件合並時,防止全局設置嚴格模式對其他沒使用嚴格模式文件的影響,將腳本放在一個執行函數中。
<script> (function (param) { "use strict"; let url = "www.google.com"; console.log(url); })(); </script>
解構差異
非嚴格模式可以不使用聲明指令,嚴格模式下必須使用聲明。所以建議使用 let
等聲明。
<script> // "use strict"; // 在嚴格模式下不允許這樣使用 ({ name, other } = { "name":"YunYa-cnblogs","other":"good" }); console.log(name, other); // YunYa-cnblogs good </script>