文章目錄
1 什麼是JavaScript
JavaScript 是一種腳本,一門編程語言,它可以在網頁上實現複雜的功能,網頁展現給你的不再是簡單的靜態信息,而是實時的內容更新,交互式的地圖,2D/3D 動畫,滾動播放的視頻等等。
1.1 瀏覽器 API
內建於 web 瀏覽器中,它們可以使周邊計算環境的數據暴露出來,還可以做實用的複雜工作。例如:
- 文檔對象模型 API(DOM(Document Object Model)API) 能通過創建、移除和修改 HTML,爲頁面動態應用新樣式等手段來操作 HTML 和 CSS。比如當某個頁面出現了一個彈窗,或者顯示了一些新內容(像上文小 demo 中看到那樣),這就是 DOM 在運行。
- 地理位置 API(Geolocation API) 獲取地理信息。這就是爲什麼 谷歌地圖 可以找到你的位置,而且標示在地圖上。
- 畫布(Canvas) 和 WebGL API 可以創建生動的 2D 和 3D 圖像。人們正運用這些 web 技術製作令人驚歎的作品。參見 Chrome Experiments 以及 webglsamples。
- 諸如 HTMLMediaElement 和 WebRTC 等 影音類 API 讓你可以利用多媒體做一些非常有趣的事,比如在網頁中直接播放音樂和影片,或用自己的網絡攝像頭獲取錄像,然後在其他人的電腦上展示(試用簡易版 截圖 demo 以理解這個概念)。
1.2 第三方 API
並沒有默認嵌入瀏覽器中,一般要從網上取得它們的代碼和信息。比如:
- Twitter API 和 新浪微博 API 可以在網站上展示最新推文之類。
- 谷歌地圖 API 和 高德地圖 API 可以在網站嵌入定製的地圖等等。
1.3 註釋
JavaScript 的註釋和C++ 一樣: //單行註釋
和 /*多行註釋 */
1.4 解釋代碼 vs 編譯代碼
解釋(interpret)和 編譯(compile)。在解釋型語言中,代碼自上而下運行,且實時返回運行結果。代碼在執行前,無需由瀏覽器將其轉化爲其他形式。
與此同時,編譯型語言代碼能夠運行之前需要先轉化(編譯)成另一種形式。比如 C/C++ 先被編譯成彙編語言,然後才能由計算機運行。JavaScript 是輕量級解釋型語言。兩種方式各有優勢。
1.5 服務器端代碼 vs 客戶端代碼
客戶端(client-side)代碼是在用戶的電腦上運行的代碼,在瀏覽一個網頁時,它的客戶端代碼就會被下載,然後由瀏覽器來運行並展示。這就是客戶端 JavaScript。
而服務器端(server-side)代碼在服務器上運行,瀏覽器將結果下載並展示出來。流行的服務器端 web 語言包括:PHP、Python、Ruby、ASP.NET 以及 JavaScript。JavaScript 也可用作服務器端語言,比如現在流行的 Node.js 環境。
1.6 動態代碼 vs 靜態代碼
“動態”一詞既能描述客戶端 JavaScript,又能描述服務器端語言。是指通過按需生成新內容來更新 web 頁面 / 應用,使得不同環境下顯示不同內容。服務器端代碼會在服務器上動態生成新內容,例如從數據庫中提取信息。而客戶端 JavaScript 則在用戶端瀏覽器中動態生成新內容,比如說創建一個新的 HTML 表格,用從服務器請求到的數據填充,然後在網頁中向用戶展示這個表格。兩種情況的意義略有不同,但又有所關聯。
沒有動態更新內容的網頁叫做“靜態”頁面,所顯示的內容不會改變。
1.7 怎樣向頁面添加 JavaScript
使用<script>
元素添加各種JavaScript:無論內部還是外部。
1.7.1 內部 JavaScript
code 直接加到html中,放在</head>
標籤之前。
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<title>Apply JavaScript example</title>
<script>
// JavaScript goes here
document.addEventListener("DOMContentLoaded", function() {
function createParagraph() {
let para = document.createElement('p');
para.textContent = 'You clicked the button!';
document.body.appendChild(para);
}
const buttons = document.querySelectorAll('button');
for(let i = 0; i < buttons.length ; i++) {
buttons[i].addEventListener('click', createParagraph);
}
});
</script>
</head>
<body>
<button>Click me</button>
</body>
</html>
1.7.2 外部 JavaScript
外部JavaScript是指,將JavaScript腳本放到.js
文件中,這是最佳的寫法,HTML和JS分開,易於維護,可重用。
function createParagraph() {
let para = document.createElement('p');
para.textContent = 'You clicked the button!';
document.body.appendChild(para);
}
const buttons = document.querySelectorAll('button');
for(let i = 0; i < buttons.length ; i++) {
buttons[i].addEventListener('click', createParagraph);
}
然後將<script> ...</script>
替換成:<script src="script.js" defer></script>
1.7.3 內聯 JavaScript 處理器
有時候會看到下面這樣的代碼,即在button元素里加一個onclick
處理器,但是這是不好的寫法,且每加一個button都要這樣寫,不好維護。
// !!!!!!!!!!!! bad practice! 不好的寫法,HTML和JS混合在一起
function createParagraph() {
let para = document.createElement('p');
para.textContent = 'You clicked the button!';
document.body.appendChild(para);
}
<button onclick="createParagraph()">Click me!</button>
1.8 腳本加載策略
如果要用JS操作DOM,那麼DOM一定要先於javascript被加載。
老的解決方法是將JS腳本放在</body>
標籤之前,這種方法使HTML DOM在加載之前,javascript的加載/解析完全被阻止,效率低。
1.8.1 async
和 defer
1.7.1 內部 javascript 的例子:
document.addEventListener("DOMContentLoaded", function() {
...
});
事件監聽器監聽 DOMContentLoaded
事件,代表HTML body已經完全加載並解析。此事件被觸發之後,javascript 纔會運行。
async
和 defer
僅對外部 javascript 起作用,它們之間的區別示意圖:
<script src="myscript.js"></script>
<script async src="myscript.js"></script>
<script defer src="myscript.js"></script>
- Without async or defer, browser will run your script immediately, before rendering the elements that’s below your script tag.
- With async (asynchronous), browser will continue to load the HTML page and render it while the browser load and execute the script at the same time.
- With defer, browser will run your script when the page finished parsing. (not necessary finishing downloading all image files. This is good.)
<script defer src="js/vendor/jquery.js"></script>
<script defer src="js/script2.js"></script>
<script defer src="js/script3.js"></script>
使用defer能保證腳本按順序加載,jquery.js, script2.js, script3.js ,使用 async 則不然。
如果多個腳本不需要等待解析(???),能獨立執行,用async
, 反之用defer
。
2 初次接觸 JavaScript
JavaScript 的很多代碼特性和其他編程語言是一樣的,比如函數啊,循環之類的,代碼語法看起來不同,但概念基本是一樣的。
用關鍵字let
(或 var
創建變量),用 const
創建常量(這點和C++一樣)。
定義函數有很多方式,其中一種是用關鍵字function
定義,舉例如下:
function checkGuess() {
alert('I am a placeholder');
}
如果在瀏覽器的JavaScript Console調用這個函數,會彈出對話框。
操作符 +
-
*
/
可以進行算術運算,還可以進行字符串連接。
還允許快捷操作符:
name += ' says hello!';
++
操作符也可以用: guessCount++;
比較操作符,這裏比較相等和不等與其他語言不同,多一個等號。
但是 ==
和!=
在JavaScript裏也是合法的操作符,但和嚴格相等符號===
相比,==
只看值是否相等,不管數據類型是否相同,因此應該使用===
符號,可以減少錯誤發生的可能性。
條件,if
, else if
, else
和C++ 語法是一樣的。
對於JavaScript語言,一切都是對象,用戶可以自己創建對象。
3 出現了什麼問題?JavaScript 疑難解答
JavaScript 大小寫敏感。
console.log()
是非常有用的調試函數,可以將值輸出到控制檯。
類選擇器以點號 .
開始。
如果是Firefox, 用 Ctrl + Shift + K, 打開console,可以看到可能的錯誤提示。
4 儲存你所需的信息 — 變量
4.1 用let
或var
聲明變量
聲明變量時不需要指定類型:
let myName;
let myAge;
在JavaScript中,所有代碼指令以分號結束。
同時聲明並初始化變量:
let myDog = 'Rover';
var
和let
的區別:
var
是老的,let
是新的,可以在變量初始化之後,再次用var
關鍵字聲明。例如:
myName = 'Chris';
function logName() {
console.log(myName);
}
logName();
var myName;
此外,下面的代碼是合法的,如果var
改成let
就不合法:
var myName = 'Chris';
var myName = 'Bob';
要儘量使用let
而非 var
,除非是要支持舊版的IE,一些舊版的IE只支持var
,不支持let
。
4.2 變量命名規則:
- 1 變量名由(0-9, a-z, A-Z) 以及下劃線組成
- 2 不要以下劃線開頭
- 3 不要以數字開頭
- 4 不能用保留字當變量名
4.3 變量類型:
- 數字:有整型,也有浮點型,
let myAge = 17;
- 字符串 :可用單引號或雙引號,
let dolphinGoodbye = 'So long and thanks for all the fish';
- 布爾:值爲
true
或false
,let iAmAlive = true;
- 數組:
let myNameArray = ['Chris', 'Bob', 'Jim'];
第一個元素的index是0 - 對象:
let dog = { name : 'Spot', breed : 'Dalmatian' };
然後dog.name
爲Spot
動態類型:不需要指定變量的數據類型
let myNumber = '500'; // oops, this is still a string
typeof myNumber; // return "string"
myNumber = 500; // much better — now this is a number
typeof myNumber; // return "number"
4.4 常量
常量聲明之後,值不可再次改變,和其他語言一樣。
使用const
關鍵字:
const daysInWeek = 7;
const hoursInDay = 24;
daysInWeek = 8; // 拋出錯誤:TypeError: invalid assignment to const `daysInWeek'
5 JavaScript 基礎概念 — 數字與運算符
5.1 JavaScript 只有一種數字的數據類型: Number
.
let myInt = 5;
let myFloat = 6.667;
myInt; // 5
myFloat; // 6.667
typedef myInt; // “number”
typedef myFloat; // "number"
5.2 操作符
操作符和其他語言類似, 有 +
-
*
/
%
**
, 最後一個是指數運算符:
10 ** 3
= Math.pow(10, 3)
= 10 * 10 * 10
= 1000
除法運算和python類似,會給出浮點值:
10 / 9;
1.1111111111111112
表達式求和的順序總是從左到右。
++
和 --
操作符和C++的一樣。
let num1 = 4;
num1++; //4
num1; //5
let num2 = 6;
num2--; //6
num2; //5
let num3 = 6;
++num3; //7
num3; //7
6 處理文字 — JavaScript 中的字符串
6.1 字符串
字符串可用單引號或雙引號,但是不能混用:
let badQuotes = 'What on earth?"; // ERROR!!!!!
6.2 轉義
轉義字符串中的字符,在字符前加反斜槓轉義字符:
let bigmouth = 'I\'ve got no right to take my place...';
bigmouth; // "I've got no right to take my place..."
6.3 連接字符串:
用+
號,字符串字面值還可以和變量相加:
let name = prompt('What is your name?');
alert('Hello ' + name + ', nice to see you!');
數字可與字符串相加:
'Front ' + 242; // OK, "Front 242"
6.4 數字與字符串相互轉換
使用Number函數與toString() 方法:
let myString = '123';
let myNum = Number(myString);
typeof myNum; // "number"
let myNum = 123;
let myString = myNum.toString();
typeof myString; // "string"
7 字符串常用操作
字符串是對象。
7.1 字符串長度
使用 length
屬性
let browserType = 'mozilla';
browserType.length; // 7
7.2 檢索
同數組:
browserType[0]; // 使用索引,從0開始
browserType.indexOf('zilla'); // 如果未查找到,返回 -1, 判斷時,可使用 !== -1
indexOf()
方法僅返回首次出現時的索引:The index of the first occurrence of searchValue, or -1 if not found.
7.3 字串
用 slice(a, b)
方法,a
爲起始位置,b
爲結束位置,實際取a ~ b-1
。 如果 b
省略,取a
起始的全部字符,直到結束。
let browserType = "Mozilla";
browserType.slice(2); // 'zilla';
7.4 大小寫轉換
分別使用 toLowerCase()
和 toUpperCase()
兩個方法。
7.4 字符串替換
let browserType = "Mozilla";
browserType.replace('moz','van'); // 僅對第一個匹配項進行替換
8 數組
8.1 創建數組
數組元素的數據類型可以不統一:
let random = ['tree', 795, [0, 1, 2]];
8.2 訪問和修改數組元素
同C++數組,沒有特別之處。
8.3 數組長度
使用 .length
屬性。
8.4 數組和字符串相互轉換
8.4.1 字符串轉換爲數組
let myData = 'Manchester,London,Liverpool,Birmingham,Leeds,Carlisle';
let myArray = myData.split(',');
myArray; //
8.4.2 數組轉換爲字符串
使用 join()
或 toString()
方法, toString()
更簡單,但不能帶參數。
let dogNames = ['Rocket','Flash','Bella','Slugger'];
let myNewString = dogNames.join(';;');
myNewString; //"Rocket;;Flash;;Bella;;Slugger"
let myNewString2 = dogNames.toString();
myNewString2; // "Rocket,Flash,Bella,Slugger"
8.5 添加和刪除數組元素
從數組末尾添加刪除元素: push()
, pop()
push()
可以帶多個參數,如果成功,返回新數組長度,pop()
不帶參數,如果成功,返回被刪除的元素。
從數組開頭添加刪除元素:unshift()
, shift()
兩組方法沒有差別,只不過是一個對數組末尾的元素操作,一個對數組開頭的元素操作。
let myArray = ['Manchester', 'London', 'Birmingham', 'Leeds', 'Carlisle'];
let newLength = myArray.push('Bradford', 'Brighton');
myArray; // Array(7) [ "Manchester", "London", "Birmingham", "Leeds", "Carlisle", "Bradford", "Brighton" ]
newLength; // 7
let removedItem = myArray.pop();
myArray; // Array(6) [ "Manchester", "London", "Birmingham", "Leeds", "Carlisle", "Bradford" ]
removedItem; // "Brighton"
https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/What_is_JavaScript
https://stackoverflow.com/questions/10808109/script-tag-async-defer/24183280#24183280