JavaScript基礎知識
前言
其實我個人認為JavaScript
是一種非常隨便的語言,也是一門很神奇很強大的語言。
因為之前使用過一段時間的JavaScript
並做了些學習筆記都是放在word
上的顯得十分雜亂,所以這次也是打算認認真真的重新填一下坑並且認真整理一下JavaScript
筆記到部落格園。
以前在群裡聊JavaScript
的時候會經常出現一張圖,我認為這個很有意思,所以就放在這裡做一個填坑目標吧。
我還是希望將整個的筆記好好整理一下,並且以一種文件格式進行書寫,也方便後期查閱。
理論知識
語言介紹
JavaScript
官方名稱是 ECMAScript
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
-
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>