目錄
前言
javascript的語法非常簡單,本章介紹它的注意事項!
簡單
1 語句和表達式
本節介紹語句和表達式的區別,但不是全部。
語句
粗略的說,一條語句執行一個動作;常見的語句比如for語句和if語句;程序是一系列語句組成的。(javascript按行執行。因此,爲使你的代碼更加規範,一般一行就是一個語句)
//這是一個賦值語句
var a = 1 + 2;
表達式
表達式產生值;它們是函數參數,賦值的右側等;任何javascript預計爲值的地方,都可以使用表達式。
//這是一個表達式
3 * 7
2 區塊和分號
區塊
區塊是由大括號包圍的語句序列;你可能會驚訝javascript擁有獨立的代碼塊,但這並不能構成單獨的作用域;區塊往往用來構成其他更復雜的語法結構,包括:
- 循環:for,while(但不是do-while)
- 分支:if,switch,try
- 函數聲明(但不是函數表達式)
//一個簡單的代碼塊
{
var a = 13;
}
//if語句
var b =1;
if(b===1){
b =2;
}
else{
b=3;
}
//while和do-while
var a = 2;
while (a > 0) {
a--;
} // 不帶分號
do {
a--;
} while (a > 0);//帶分號
//for語句,塊內部的參數
for(var i=1;i>3;i++){
var b = 2;
}
console.log(b);//2 區塊不構成單獨的作用域
console.log(i);//1
//函數聲明和表達式
function test(){
} var a = 1; //不帶分號
var f = function () { }; var a = 1; // 加分號
分號
分號的基本使用規則是:
- 通常,語句以分號結尾。
- 例外是以塊結尾的語句。
分號在JavaScript中是可選的。通過所謂的自動分號插入(ASI;其他篇幅講介紹^)添加缺少的分號。但是,該功能並不總是按預期工作,這就是爲什麼你應該總是包含分號。
如果在塊之後添加分號,則不會出現語法錯誤,因爲它被視爲空語句。
//空語句
;;;
分號終止語句,但不終止塊。在一種情況下,您將在塊之後看到分號:函數表達式是以塊結尾的表達式。如果這樣的表達式在語句中排在最後,則後面跟一個分號
//函數表達式
var f = function () { }; var a = 1; // 加分號
//報錯舉例
var f = function () { } var a = 1;//代碼寫在同一行防止觸發分號自動插入機制
3 標識符
標識符規則
標識符是用於命名事物並在JavaScript中以各種話音未落角色出現。例如,變量和未加引用號的屬性鍵的名稱必須是有效的標識符。標識符區分大小寫。
標識符的第一個字符是以下之一:
- 任何Unicode字母,包括拉丁字母(如D),希臘字母(如λ)和西裏爾字母(如Ä),當然,中文同樣可以作爲標識符。
- 美元符號(
$
) - 下劃線(
_
)
後續字符是:
- 任何合法的第一個角色
- Unicode類別中的任何Unicode數字“十進制數(Nd)”; 這包括歐洲數字,如7和印度數字,如3
- 各種其他Unicode標記和標點符號
合法標識符的示例:
var ε = 0.0001;
var строка = '';
var _tmp;
var $foo2;
儘管這使您能夠在JavaScript代碼中使用各種人類語言,但我建議您使用英語,同時使用標識符和註釋。這確保了最大可能的人羣可以理解您的代碼,這一點很重要。
以下標識符是保留字 - 它們是語法的一部分,不能用作變量名(包括函數名和參數名):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
以下三個標識符不是保留字,但你應該這麼認爲:
|
|
|
4 註釋
JavaScript有兩種註釋:單行註釋和多行註釋。單行註釋以行尾開頭//並在行尾結束:
x++; // 單行註釋
多行註釋被分隔/*和*/:
/* 這是
一個
多行註釋
*/
5 標籤(lable)
JavaScript 語言允許,語句的前面有標籤(label),相當於定位符,用於跳轉到程序的任意位置,標籤的格式如下。
label:
語句
標籤可以是任意的標識符,但不能是保留字,語句部分可以是任意語句。標籤可與break語句和continue語句配合使用,跳出特定的循環。
top:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) break top;
console.log('i=' + i + ', j=' + j);
}
}
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
標籤也可用於跳出代碼塊:
foo: {
console.log(1);
break foo;
console.log('本行不會輸出');
}
console.log(2);
// 1
// 2
6 JavaScript的五個基本值和八類值
本節保留Exploring ES5五個基本值說法。
五個基本值
以下是五個基本的值:
- Booleans(布爾值):
true
false
- Numbers(數值):
1023
7.851
- Strings(字符串):
"hello"
'wrold'
- Objects(對象):
{
firstName:'Shrry',
lastName:'Join'
}
- Arrays(數組):
['join','shrry','LiMing']
JavaScript的八類值
除了以上五種值,javascript還包括其他三種值。
以下包括另外三類值:
null(空),undefined(未定義),boolean(布爾值),number(數值),string(字符串)
Object(對象),Array(數組),Function(函數)
源自Scheme,javascript參考其語法(函數編程),函數被視爲值且可作爲參數傳遞。
7 變量
定義
變量是對“值”的具名引用。變量就是爲“值”起名,然後引用這個名字,就等同於引用這個值。變量的名字就是變量名。
變量的聲明和賦值
以下爲兩個變量賦值:
//聲明變量a,b併爲其賦值
var a = 1;var b = 2;
//等同於
var a,b;
a = 1;
b = 2;
如果變量只聲明而未賦值,則該變量爲undefined(未定義):
var b;// undefined
如果變量賦值的時候,忘記寫var命令,該條語句也是有效的:
var a = 1;
// 基本等同,但是嚴格模式'use strict'下會報錯
a = 1;
如果一個變量沒有聲明就直接使用,JavaScript 會報錯,告訴你變量未定義:
x
// ReferenceError: x is not defined
值得一提的是,js並沒有採用java的靜態類型,而是設計爲動態類型語言,因此變量的類型沒有限值:
var a = 1;
a = 'hello';
變量提升
JavaScript 引擎的工作方式是,先解析代碼,獲取所有被聲明的變量,然後再一行一行地運行。這造成的結果,就是所有的變量的聲明語句,都會被提升到代碼的頭部,這就叫做變量提升(hoisting)。
console.log(a);
var a = 1;// undefined 而不是 ReferenceError: x is not defined
//執行時爲
var a;
console.log(a);
a = 1;
額外的
數據類型(可以理解爲變量類型也可以理解爲值類型)被分爲兩類:
- 值類型:null(空),undefined(未定義),boolean(布爾值),number(數值),string(字符串)
- 引用類型:Object(對象),Array(數組),Function(函數)
區別:
- 值類型:
- 佔用空間固定,保存在棧中(當一個方法執行時,每個方法都會建立自己的內存棧,在這個方法內定義的變量將會逐個放入這塊棧內存裏,隨着方法的執行結束,這個方法的內存棧也將自然銷燬了因此,所有在方法中定義的變量都是放在棧內存中的。棧中存儲的是基礎變量以及一些對象的引用變量基礎變量的值是存儲在棧中,而引引變量存儲在棧中的是指向堆中的數組或者對象的地址,這就是爲何修改引用類型總會影響到其他指向這個地址的引用變量。)
- 保存與複製的是值本身
- 使用的typeof運算檢測數據的類型
- 基本類型數據是值類型
- 引用類型:
- 佔用空間不固定,保存在堆中(當我們在程序中創建一個對象時,這個對象將被保存到運行時數據區中,以便反覆利用(因爲對象的創建成本通常較大),這個運行時數據區就是堆內存。堆內存中的對象不會隨方法的結束而銷燬,即使方法結束後,這個對象還可能被另一個引用變量所引用(方法的參數傳遞時很常見),則這個對象依然不會被銷燬,只有當一個對象沒有任何引用變量引用它時,系統的垃圾回收機制纔會在覈實的時候回收它。)
- 保存與複製的是指向對象的一個指針
- 使用的的instanceof檢測數據類型
- 使用new()方法構造出的對象是引用型
熟悉的Java的程序猿一定會覺得很熟悉,是的,JS變量類型機制和Java的的基本一致,這也就能理解爲什麼說的的JavaScript是一門很像的的Java的腳本語言。
高級
表達式語句
只要javascript需要語句,你也可以編寫表達式。這樣的語句被稱爲表達式語句。反過來則不成立,例如if語句不能作爲函數的參數。
類似
如果我們查看兩個相似的語法類別成員,語句和表達式之間的區別會變得更加清晰。
以下是if語句示例:
var x;
if(y> = 0){
x = y;
} else {
x = -y;
}
表達式有一個模擬條件運算符。以上陳述等同於以下陳述。
var x =(y> = 0?y:-y);
等號和分號之間的代碼是一個表達式。括號不是必需的,但如果把它放在parens中,我發現條件運算符更容易閱讀。
看起來像語句的表達式
有些表達式看起來像語句。我們將在本節結尾處研究爲什麼這是一個問題。
對象字面量
下面是一個對象字面量,也就是一個可以生成一個對象值的表達式。
{
foo: bar(3, 5)
}
但是,它也是一個完全合法的語句,其組成部分有:
- 一個代碼塊:一個由大括號包圍的語句序列。
- 一個標籤:你可以在任何語句前面放置一個標籤.這裏的foo就是一個標籤。
- 一條語句:表達式語句bar(3, 5)。
{ //區塊
foo: //標籤
bar(3, 5) //表達式語句
}
函數表達式與函數聲明
下面的代碼是一個函數表達式:
function(){}
//表達式是一個函數,不像函數聲明,函數名不是必須的
您還可以爲函數表達式指定名稱並將其轉換爲命名函數表達式:
function foo() { }
如此一來,一個命名的函數表達式從表面上看起來,和一個函數聲明並沒有什麼區別。但它們的效果是不同的:一個函數表達式產生一個值(一個函數).一個函數聲明執行一個動作:將一個函數賦值給一個變量. 此外,只有函數表達式可以被立即調用,函數聲明不可以.
javascript如何判定看起來像語句的表達式
我們已經看到一些表達式與語句無法區分。這意味着相同的代碼工作方式可能不同,具體取決於它是出現在表達式上下文還是語句上下文中。通常情況下,這兩種情境明顯是分開的。但是,對於表達式語句,存在重疊:在那裏,您有表達式出現在語句上下文中。爲了防止歧義,JavaScript語法禁止表達式語句以大括號或關鍵字function開頭:
ExpressionStatement : [lookahead ∉ {"{", "function"}] Expression ;
那麼如果你想編寫一個以上面兩個標記中的任何一個開頭的表達式語句,你該怎麼做?您可以將其放在括號“()”中,這樣能確保它僅出現在表達式上下文中。(括號在javascript當中是分組符,裏面只能包含表達式,所以解釋器會認爲這是一個表達式而不是語句)讓我們看兩個例子:eval和立即調用的函數表達式。
eval
eval在語句上下文中解析其參數。如果希望eval返回一個對象,則必須在對象文字周圍加上括號。
eval("{foo:123}")//123
eval("({foo:123})")//{foo:123}
立即調用函數表達式(IIFE)
以下代碼是立即調用的函數表達式。
(function(){return "abc"}())// abc
如果省略括號,則會出現語法錯誤(函數聲明不能是匿名的):
function(){return "abc"}()// SyntaxError: function statement requires a name
如果添加名稱,則還會出現語法錯誤(無法立即調用函數聲明):
function foo(){return "abc"}()// SyntaxError: syntax error