JavaScript 第一章和第二章
一、詞法結構
1.1字符集
JavaScript程式是用Unicode字符集編寫的。Unicode是ASCII和Latin-1的超集,並支援地球上幾乎所有在用的語言。
1.1.1區分大小寫 JavaScript是區分大小寫的語言,也就是說,關鍵字,變數,函式名和所有的識別符號都必須採取一致的大小寫形式。比如,關鍵字"while"必須寫成"while",不可以寫成"While"或者"WHILE"。同樣,"online",'Online","OnLine"和"ONLINE"是四個不同的變數名。 1.1.2 空格、換行符和格式控制符 JavaScript會忽略程式中標識之間的空格
1.2 註釋
JavaScript支援兩種格式的註釋。在行尾"//"之後的文字都會被JavaScript當作註釋忽略掉的。此外,"/*" 和 "*/"之間的文字也會當作註釋。這種註釋可以跨行書寫,但是不可以有巢狀的註釋。下面都是合法的JavaScript註釋:
//這是單行註釋
/* 這裡是一段註釋*/
/*
* 這又是一段註釋
* 這裡的註釋可以連寫很多行
*/
1 .3 直接量
所謂直接量,是程式中直接使用的資料值,這些數都是直接量
12 // 數字
1.2 // 小數
"hello world" // 字串文字
true/false // 布林值
/javasript/gi // 正則表示式直接量(用做模式匹配)
null // 空
1.4 識別符號和保留字
識別符號 在JavaScript中,識別符號用來對變數和函式進行命名,或者用做JavaScript程式碼中某些迴圈語句中的跳轉位置的標記。JavaSrcipt識別符號必須以字母、下劃線 ( _ ) 或 美元符 ( $ )開始。後續的字元可以是字母、數字、下劃線或美元符(數字是不允許作為首字元出現的,以便JavaScript可以輕易區分開識別符號和數字)。下面是合法的識別符號:
i
my_variable_name
v12
_dumy
$str
出於可移植性和易於書寫的考慮,通常我們只使用ASCII字母和數字來書寫識別符號。然而需要注意的是,JavaScript允許識別符號中出現Unicode字元全集中的字母和數字。因此,程式設計師也可以使用一些非英語語言或者數學符號來書寫識別符號。
var si=true;
var Π=3.14;
保留字 JavaSceipt把一些識別符號拿出來用作直接的關鍵字。因此,就不能在程式中把這些關鍵字用作識別符號了:
break delete function return typeof
case do if switch var
catch else in this void
continue false instanceof throw while
debugger finally new true with
default for null try
1.5 可選的分號
和其他許多程式語言一樣,JavaScript使用分號(;)將語句分隔開。這對增強程式碼的可讀性和整潔性是非常重要的;缺少分隔符,一條語句的結束就成為了下一條語句的開始,反之亦然。在JavaScript中,如果語句各自獨佔一行,通常可以省略語句之間的分號。另外一種風格就是,在任何可以省略分號的地方都將其省略,只有在不得不使用的時候才使用分號。不掛採用哪種程式設計風格,關於JavaScript中可選分行好的問題有幾個細節需要注意:
//考慮如下程式碼,因為兩句語句用兩行書寫,第一個分號是可以省略掉的
a=3;
b=3
//如果按照如下格式書寫,第一個分號則不能省略掉
a=3;b=4;
1、在涉及return、break和continue語句的場景中。如果這三個關鍵字後緊跟著換行,JavaScript則會在換行處填補分號。例如:
return
true;
// JavaScript會解析成:
return;true;
// 而程式碼的本意是這樣:
return True;
//也就是說,在retur、break和continue和隨後的表示式之間不能有換行,如果添加了換行,程式只能在極特殊的情況下才會報錯,而且程式的除錯非常不方便吧。
2、在涉及 "++" 和 "--" 運算子的時候,這些運算子可以作為表示式的字首,也可以當作表示式的字尾。如果將其用作字尾表示式,他和表示式應當在同一行。否則,行尾將填補分號,同時 "++" 或 "--" 將作為下一行程式碼的字首操作符並與之一起解析。
x
++
y
//這段程式碼將解析為"x;++y",而不是"x++;y"
二、型別、值和變數
計算機程式的進行需要對值(value)進行操作。在程式語言中,能夠表示並操作的值的型別乘坐資料型別(type),程式語言最基本的特性就是能夠支援多種資料型別。JavaScript的資料型別分為兩類;原始型別(primitive type)和物件型別(object type)。 JavaScript的原始資料型別包括數字、字串和布林值。另外,JavaScript具有兩個特殊的原始值:null(空)和undefined(未定義),他們不是數字、字串和布林值,他們們通常分別代表了各自特殊型別的唯一的成員。 JavaScript中除了數字、字串、布林值、null和undefined之後的就是物件了。物件(object)是屬性(property)的集合。每個屬性都由"名/值對"(值可以是原始值、不如數字、字串、也可以是物件構成)。其中,有一個比較特殊的物件--- 全域性物件(global object)。
2.1數字
和其他程式語言不同,JavaScript不區分整數值和浮點數值。JavaScript中的所有數字均用浮點數值表示。JavaScript次啊用IEEE 754標準定義的64為浮點格式表示數字,這意味著他能表示的最大值是±1.7978931348623157 x 10308,最小值是±5 x 10-324。按照JavaScript中的數字格式,能夠表示的整數範圍是從-253~253,包含邊界值。如果超過此範圍的整數,則無法報這個低位數字的精度。然而需要注意的是,JavaScript中實際的操作則是基於32位整數。 2.1.1 整數直接量 在JavaScript程式中,用一個數字序列表示一個十進位制整數。例如:
0
3
10000000
除了十進位制的整形直接量,JavaScript同樣可以識別十六進位制(以16為基數)值。所謂十六進位制的直接量是指以"0x"或"0X"為字首,其後跟隨十六進位制數串的直接量。十六進位制值是0-9之間的數字和a(A)-f(F)之間的字母構成,a-f的字母對應的是表示數字10-15。下列是十六進位制整型直接量的例子:
0xff //15*16+15=255(十進位制)
0xCAFE911
儘管ECMAScript(是JavaScript的規格,是JavaScript基本語法)標準不支援八進位制直接量,但JavaScript的某些實現可以允許採用八進位制(基數為8)形式表示整數。八進位制直接量以數字0開始,氣候跟隨一個由0-7(包括0和7)之間的數字組成的序列。例如:
0377 //3*64+7*8+7=255(十進位制)
由於某些JavaScript的實現支援八進位制直接量,而有的不支援,因此最好不要使用以0為字首的整型直接量,畢竟我們也無法得知當前JavaScript的實現是否支援八進位制的解析。 在ECMAScript6的嚴格模式下,八進位制直接量是明令禁止的。 2.1.2浮點型直接量 浮點型直接量可以含有小數點,他們採用的是傳統的實數寫法。一個實數由整數部分、小數點和小數部分組成。此外,可以使用科學計數法的形式進行記數,是由前面的實數乘以10的指數次冪。
可以使用更加簡潔的語法表示:
[digits][.digits][(E|e)[(+|-)]digits]
例如:
3.14
2345.789
.3333333
6.02e23 //6.02x10的23次冪
2.1.3 JavaScript中的算術運算 JavaScript程式是使用語言本身提供的算術運算子來進行數字運算的。這些運算子包括加法運算子(+)、減法運算子(-)、乘法運算子(*)、除法運算子(/)和求餘(求整除後的餘數)運算子(%)。 除了基本的運算外,JavaScript還支援更加複雜的算術運算,這些複雜運算通過作為Math物件的屬性定義的函式和常量來實現:
Math.pow(2,53) // => 9007199254740992:2的53次冪
Math.round(.6) // => 1.0:四捨五入
Math.ceil(.6) // => 1.0:向上取整
Math.floor(.6) // => 0.0:向下取整
JavaScript中的算術運算在溢位(overflow)、下溢(underflow)或被零整除時不好報錯。當數字運算結果超過了JavaScript所能表示的數字上限(溢位),結果為一個特殊的無窮大(infinity)值,在JavaScript中以Infinity表示。同時地,當負數的值超過了JavaScript所能表示的負數範圍,結果以無窮大,在JavaScript中以-Infinity表示。無窮大值的行為特性和我們所期望的是一致的:基於他們的加減乘除運算結果還是無窮大值(當然還保留他們的正負號)。 下溢(underflow)是當於是運算結果無線接近於零並比JavaScript能表示的最小值還小的時候出現的一種情形。這種情況下,JavaScript將會返回0.當一個附屬發生下溢時,JavaScript返回一個特殊的值"負零"。這個值(負零)幾乎和正常的零完全一樣,JavaScript程式設計師很少用到負零。 2.1.4二進位制浮點數和四捨五入錯誤 實數有無數個,但JavaScript通過浮點數的形式只能表示其中有限的個數(確定地來說是 18 437 736 874 454 810 627個)。也就是說,當在JavaScript中使用實數的時候,常常只是真實值的一個近似表示。 JavaScript採用了IEEE-754浮點數表示法(幾乎所有現代程式語言所採用),這是一種二進位制表示法,可以精確的表示帶分數,比如1/2,1/8和1/1024.遺憾的是,我們常用的分數(特別是在金融計算方面)都是十進位制分數1/10、1/100等。二進位制浮點數表示法並不能精確的表示精確0.1這樣簡單的數字。 JavaScript中的數字具有足夠的精度,並可以極其近似於0.1。但事實上,數字不能精確表述帶來的問題。例如:
var x= .3-.2; // 30美分減去20美分
var y= .2-.1; // 20美分減去10美分
x==y // =>false:兩值不相等
x==.1 // => false:.3-.2不等於.1
y==.1 // =>true: .2-.1等於.1
由於舍入誤差,0.3和0.2之間的近似差值實際上並不等於0.2和0.1之間的近似插值。這個問題並不是只在JavaScript中才出現。理解這一點非常重要,在任何二進位制浮點數的程式語言中都會有這個問題。同時需要注意的是,上述程式碼中的x和y值非常接近彼此和最終的正確值。這種計算結果可以勝任大多數的計算任務。這問題也只有在比較兩個值是否相等的時候出現。 2.1.5 日期和時間 JavaScript語言核心包括Date()建構函式,用來建立表示時間和日期的物件。這些日期物件的方法為日期計算提供了簡單的API。日期物件不想數字那樣是基本資料型別。本節給出了使用物件的一個簡單教程。
VaTthen = new Date(2011,0,1);//11 2011年1月1日
var later = new Date(2011,0,1,17,10,30);//同一天,當地時間5:10:30pm,var now= new Date();12當前日期和時間
vaI elapsed = now-then;// 71日期減法:計算時間間隔的毫秒數
later. getFullYear( );// => 2011
later. getMonth();// => 0:從0開始計數的月份
later。getDate() ;// => 1:從1開始計數的天數
later.getDay(); // => 5:得到星期幾,0代表星期日,5代表星期一
later. gethours(); // =>當地時間17:5pm
later. getUTCHours(); // 使用UTC表示小時的時間,基於時區
2.2 文字
字串(String)是一組由16位值組成的不可變的有序序列,每個字元通常來自於Unicode字符集。JavaSrcipt通過字串型別來表示文字。字串的長度(length)是其所含16位值的個數。JavaScript字串(和其陣列)的索引從零開始,第一個字元的位置是0,第二個字元的位置是1,以此類推。空字串(empty string)長度為0,JavaScript中並沒有表示單個字元的“字元型。要寶石一個16位值,只需將其複製給字串變數即可,這個字串長度位1。 2.2.1字串直接量 在JavaScript程式中的字串直接量,是由單引號或者雙引號括起來的字元序列。由單引號定界的字串中可以包含雙引號,由雙引號定界的字串中也可以包含單引號。例如:
'teseting'
"3,14"
"name=myform"
"This string\nhas two lines"
在ECMAScript5中,字串直接量可以拆分為數行,每行必須以反斜線(\)結束,反斜線和行結束符都不算是字串直接量的內容。如果希望在字串直接兩中另起一行看,可以使用轉義字元\n:
"two\nlines" //這裡定義了一個顯示位兩行的字串
"one\ //用三行程式碼定義了顯示位單行的字串,只有在EMCAScript 5中使用
long\
line" //
在客戶端JavaScript程式設計中,JavaScript程式碼會夾雜HTML程式碼的字串,HTML程式碼也會夾雜JavaScript程式碼。和JavaScript一樣,HTML也使用單引號或者雙引號來定界字串。因此,當JavaScript程式碼和HTML程式碼混在一起的額時候,最好在JavaScript和HTML程式碼中各自使用獨立的引號風格。例如,在JavaScript表示式中使用單引號表示字串"Thank you",而在HTML事件處理程式屬性中則使用雙引號表示字串。例如:
<button onclick="alert('Thank you ')">click me </button>
2.2.2轉移字元 在JavaScript字串中,反斜線()有著特殊的紅提,反斜線符號後加一個字元,將不在表示他們的字面含義。例如,\n即使一個轉義字元,她表示的是一個換行符。 另外,上節中提到的轉義字元‘\n',表示單引號(撇號)。當需要在一個單引號定界的字串內使用撇號的時候,他就顯得非常有用,一維反斜線可以是我們避免使用常規方式解釋單引號,當單引號不是用是做標記字串結尾時,他只是是一個撇號:
You\'re right,it can not be a quote'
JavaScript轉義字元
\o // NULL字元(\u0000)
\b // 退格符(\u0008)
\t // 水平製表符(\u0009)
\n // 換行符(\u000A)
\v // 垂直製表符(\y000B)
\f // 換頁符(\u000C)
\r // 回車符(\u000D)
\" // 雙引號(\u0022)
\' // 撇號或單引號(\u0027)
\\ // 反斜線(\u005C)
\xXX // 由兩位十六進位制xx指定的Latin-1字元
\uXXX // 由思維十六進位制數xxxx指定的Unicode字元
2.2.3 字串的使用 JavaScript的內建功能之一就是字串連線。如果將加號(+)運算子用於數字,表示兩數相加。但將它作用於字串,則表示字串連線,將第二個字串拼接在第一個之後,例如:
msg="hello",+"world"; // 生成字串"hello,world"
要確定一個字串的長度-其所包含的十六位值的格式——可以使用字串的length屬性。例如,向得到字串s的長度:s.length 除了length屬性,字串還提供許多可以呼叫的方法:
var s="hello world" // 定義一個字串
s.charAt(0) // =>'h':第一個字元
s.charAt(s.length-1) // =>'d':最後一個字元
s.substring(1,4) // =>'ell':第2-4個字元
s.slice(1,4) // =>'ell'同上
s.slice(-3) // =>'rld':最後三個字元
s.indexOf("l") // =>'2':字元l首次出現的位置
s.lastIndexOf('1') // =>10:字串1最後一次出現的位置
s.indexOf("l",3) // =>3:在位置3及之後首次出現字元l的位置
s.split(",") // =>['hello',’world‘]分割成字串
s.replace('h','H') // =>"Hello,world"全文字元替換
s.toUpperCase() // =>"HELLO,WORLD"
2.2.4 模式匹配 JavaScript定義了RegExp()建構函式,用來建立文字匹配模式的物件。這些模式成為"正則表示式",JavaScript採用Perl中的正則表示式語法。String和RegExp物件均定義了利用正則表示式進行模式匹配和查詢與替換的函式。 在兩條斜線之間的文字構成了一個正則表示式直接量。第二條斜線之後也可以跟隨一個或者多個字母,用來修飾匹配模式的含義。例如:
/^html/ // 匹配以HTML開始的字串
/[1-9][0-9]*/ // 匹配一個非零數字,後面是任意個數字
/\bjavascript\b/i // 匹配單詞"javascript",忽略大小寫
RegExp物件定義了很多有用的方法,字元串同時具有可以接收RegExp引數的方法,例如:
var text="testing:1,2,3"; // 文字示例
var pattern=/d+/g // 匹配所有包含一個或者多個數字的例項
pattern.test(test) // =>true:匹配成功
text.search(pattern) // =>9:首次匹配成功的位置
text.match(pattern) // =>["1","2","3"]:所有匹配組成的陣列
2.3布林值
布林值代真或假、開或關、是或否。這個型別只有兩個值,保留字true和false。JavaScript程式中的比較難語句的結果通常都是布林值,例如:
a==4 //這段程式碼用來檢測變數a的值是否等於4.如果等於,比較結果的布林值是true,如果不等,比較結果則為false。
undefined、null、0、-0、NaN、""這些值會被轉換成false。其他值,包括物件(陣列)都會轉換成true。布林值包含tostring()方法,因此可以使用這個方法將字串轉換為"true"或"false",但它並不包含其他有用的方法。除了這個不重要的API,還是三個重要的布林運算子。 "&&"運算子執行了邏輯與(AND)操作,當且僅當兩個運算元都是真值時它才返回true,否則返回false;"||"運算子是布林或(OR)操作,如果兩個運算元其中之一為真值他就返回true,如果兩個運算元都是假值則返回false。最後,一元操作符"!"執行了布林非(NOT)操作;如果運算元是真值則返回false;如果是假值,則返回true。
if ((x==0 &&y==0)//!(z==0)){
//x和y都是零或者z是非零
}
2.4 null和undefined
null是JavaScript語言的關鍵字,它表示一個特殊值,常用來描述"空值"。對null執行typeof預算,結果返回字串"object",也就是說,可以將null認為是一個特殊的物件值,含義是"非物件"。但實際上,通常認為null是它自由型別的唯一一個成員,它可以表示數字,字串和物件是"無值"的。 undefined是JavaScript第二個表示值的空缺。用未定義的值表示更深陳詞的"空值"。他是比那輛的一個取值,表明變數沒有初始化,如果要查詢物件屬性或陣列元素的值時返回undefined,則說明這屬性或元素不存在。如果函式沒有返回任何值,則返回undefined。 儘管null和undefined時不同的,但他們都表示"值的空缺",兩者往往可以呼喚。判斷相等於運算子"=="認為兩者時相等的。underfined是表示系統級的,出乎意料的或類似錯誤的值的空缺,而null是表示程式級的,正常的或在醫療之中的值的空缺。
2.5全域性物件
全域性物件(global object)在JavaScript中有著重要的用途。當JavaScript直譯器啟動時(或者任何web瀏覽器載入新頁面的時候),他將建立一個新的全域性物件,並給它一組定義的初始屬性。
-
全域性屬性:例如:undefined、Infinity和NaN
-
全域性函式:比如IsNaN()、parseInt()和eval()
-
建構函式,比如Date()、string()、Array()、object()
-
全域性物件:比如Math和Json 全域性物件初始屬性並不是保留字,但他們應該當做保留字來對待,或者通過別名"Global"來找到這些全域性變數。在程式碼的最頂級——不在任何函式內的JavaScript程式碼——可以使用JavaScript關鍵字this來引用全域性物件
var global=this; //定義一個引用全域性物件的全域性變數
在客戶端JavaScript中,在其表示的瀏覽器視窗中的所有JavaScript程式碼中,Window物件充當了全域性物件。這個全域性Window物件有一個屬性window引用其自身,它可以替代this來引用全域性物件。Window物件定義了全域性屬性,但他也針對Web瀏覽器和客戶端JavaScript定義了一小部分其他全域性屬性。
2.6包裝物件
JavaScript物件時一種複合值,它是屬性或已命名值的集合。通過"."符號來引用屬性值。當屬性值是一個函式的時候,稱其為方法。通過o.m()來呼叫物件o中的方法。例如:
var s="hello,world" //一個字串
var word=s.substring(s.indexOf("")+1,s.length) // 使用字串的屬性
只要引用了字串s的屬性,JavaScript就會將字串通過呼叫new Sting(s)的方式轉換成物件,這個物件繼承了字串的方法,並被用來處理屬性的引用。一旦屬性引用結束,這個新建立的物件就會銷燬。 同字串一樣,數字和布林值也具有各自的方法,通過Number()和Boolean()建構函式建立一個臨時物件,這些方法的呼叫均來自於這個臨時物件。null和undefined沒有包裝物件,訪問他們的屬性會造成一個型別錯誤。注意的是String()、Number()或Boolean()建構函式來建立包裝物件。JavaScript會在必要時將包裝物件轉換成原始值。“==”等於運算子將原始值和其包裝物件視為相同,但是“===”全等運算子將他們視為不等,通過typeof於是暖夫可以看到原始值和其包裝物件的不同。
var s="test",n=1,b=true; // 一個字串、數字和布林值
var S=new String(s); // 一個字串物件
var N=new Number(n); // 一個數值物件
var B=new Boolean(b); // 一個布林物件
2.7 不可變的原始值和可變的物件引用
JavaScript中的原始值(undefined、null、布林值、數字和字串)與物件(包括陣列和函式)有著根本的區別。原始值時不可更改的;任何方法都無法更改一個原始值。對數字和布林值來說顯然如此——改變數字的值本身就說不通,但是對字串來說並不明顯,因為字串可以看作由字元組成的陣列。字串中所有的方法看上去返回了一個修改後的字串,實際上返回的時一個欣的字串值。
var s="hello"; // 定義一個由小寫字母組成的文字
s.toUpperCase(); // 返回"HELLO",但並沒有改變s的值
s // =>"hello":原始字串的值並沒改變
原始值的比較是值的比較:只有在他們的值相同時他們在相同。對於字串來說則並不明顯,如果比較兩個單獨的字串,當且僅當他們的長度相同且每個索引的字元都想相同,JavaScript才認為他們相同。 物件和初始值不同,首先,物件是可變的——他們的值是可以修改的。物件的比較並非值的比較,即使兩個物件包含相同的屬性以相同的值,他們也是不相等的。各個索引元素完全相同的陣列也不相同。
var s={x:1} // 定義一個物件
s.x=2; // 通過修改物件屬性值來更改物件
s.y=3; // 再次更改這個物件,給他增加一個新的屬性
如果想要比較兩個單獨的物件或者陣列,則必須比較他們的屬性或者元素。例如:
function equalArray(a,b){
if (a.length==b.length) return false;
for (var i=0;i<a.length;i++)
if(a[i]!==b[i]) return false;
return true;
}
2.8型別轉換
JavaScript中的取值型別非常靈活,我餓們已經從布林值看到了這一點:當JavaScript期望使用一個布林值的時候,你可以提供任意型別值,JavaSrcipt將根據需要自行轉換型別。一些真值轉換為true,其他值轉換為false。同時在其他型別中同樣使用。例如:
10+"object"; // =>"10 object",將數字10 轉換為字串
"7"*4; // =>28:兩個字串均轉換為數字
var n=1-"x"; // =>NaN:字串“x”無法轉換為數字
2.8.1 轉換和相等性 由於JavaScript可以做靈活的型別轉換,因此“==”等於運算子也隨相等的含義靈活多變。例如:
null == undefined //這兩值被認為相等
"0" == 0 //在比較之前字串轉換成數字
注意的是,一個值轉換為另外一個值並不意味著兩個值相等。比如,如果在期望使用布林值的地方使用了undefined,它將轉換為false,但是並不表明undefined==false。 2.8.2 顯式型別轉換 為了使得程式碼更加清晰易讀而做的顯式轉換。做顯式型別轉最簡單的方法是使用Boolean()、Number()、String()和object()。當不通過new運算子呼叫這些型別的時候,他們將作為型別轉換函式進行型別轉換。
Number("3") // =>3
String(false) // =>"false"或者false.toString()
需要注意的是,除了null或underfined之外的任何值都具有toString()方法,這個方法的執行結果通常和String()方法返回的結果是一致的。 parseInt()函式和parseFloat()函式,他們是全域性函式,不從屬於任何一個一個的方法。parseInt()直接解析整數,而parseFloat()則可以解析整數和浮點數。如果字串字首是“0X”或者是”0x“,parseInt()將其解釋為十六進位制數,parseInt()和parseFloat()都會跳過任意數量的前導空格,儘可能解析更多數值字元,並忽略後面的內容。如果第一個非空格字元是非法的數字直接兩,將最終返回NaN 。
parseInt(" 3 blind mice") // => 3
parseFloat("3.14 meters") // =>3.14
parseInt("0.1") // =>0
parseInt()可以接收第二個可選引數,這個引數指定數字轉換的基數,合理的取值範圍是2-36。例如:
parseInt("11",2) // =>3 (1*2+1)
parseInt("ff",16) // =>255:(15*16+15)
parseInt("077",8) // =>63:(7*8+7)
2.9 變數宣告
在JavaScript程式中,使用一個變數之前應當先宣告。變數是使用關鍵字var來宣告的。
var i; // 宣告一個變數
var i,sum; // 宣告多個變數
var i=0,j=0,k=0; // 可以將變數的初始賦值和變數宣告何在一起
for (var i=0;i<10;i++) consloe.log(i); //在for和in迴圈中同樣也可以使用var語句
2.10 變數作用域
一個變數的作用域是程式原始碼中定義這個變數的區域。全域性變數擁有全域性作用域。在JavaScript程式碼中的任何地方都是有定義的。然而在函式內宣告的比那輛只能在函式體內有定義。他麼是區域性變數,作用域是區域性性的。函式引數也是區域性變數,他們只能在函式體內有定義。 在函式體內,區域性變數優先順序高於同名的全域性變數,如果在函式內宣告的一個區域性變數或者函式引數中帶有的變數和全域性變數重名,那麼全域性變數就會被區域性變數所覆蓋。
var s='global'; //宣告一個全域性變數
function checkscope(){
var s='local'; // 宣告一個同名的區域性變數
return s; // 返回區域性變數的值,而不是全域性變數的值
}
checkscope() // =>'local'
2.10.1 函式作用域和宣告提前
在一些類似c語言的程式語言中,花括號內的每一段程式碼都具有給咱的作用域,而且變數在宣告他們的程式碼段之外是不可見的,我們稱為塊級作用域。而在JavaScript中沒有塊級作用域。JavaScript取而代之的是使用函式作用域。變數在宣告他們的函式體以及這個函式體巢狀的任意函式體內都有定義的。
function test(w){
var i=0; // i在整個函式體內均是有定義的
if (typeof w=='object'){
var j=0; // j在函式體內是有定義的 ,不僅僅實在這個程式碼段內
for (var k=0;k<10;k++){ // k在函式體內是有定義的,不僅僅在迴圈內
console.log(k); // 輸出數字0-9
}
console.log(k); // k已經定義完了,輸出k=10
}
console.log(j); //j定義完了,但可能沒有初始化
}
JavaSript的函式作用域是指在函式內宣告的所有變數在函式題內始終是可見的,這意味著變數在宣告之前甚至已經可用。JavaSript的這個特性被非正式的稱為宣告提前
var s='global';
function f(){
console,log(s); // 輸出“undefined” ,而不是"global"
var s='local'; // 變數在這裡賦初始值,但變數本身在函式體內任何地方的都是有定義的
console.log(s); //輸出‘local'
}
在具有塊級作用域的程式語言中,在狹小的作用域裡讓變數宣告和使用變數的程式碼儘可能靠近彼此,通常來講,這是一個非常不錯的習慣。由於JavaScript沒有塊級作用域,因此一些程式設計師特意將變數宣告放在函式體頂部,而不是將宣告靠近在使用變數指出。這種做法使得他們的原始碼費差個青協的反映了真實的變數作用域。
2.10.2 作為屬性的變數 當申明一個JavaScript全域性變數的時候,實際上定義了全域性物件的一個屬性。當使用var宣告一個變數的時候,建立的這個屬性是不可配置的,也就是說這個變數無法通過delete運算子刪除。如果你沒有嚴格模式並給一個沒有宣告的變數複製的話,JavaScript會自動建立一個全域性變數,以這方式建立的變數是全域性物件的正常的可配置屬性,並可以刪除他們。
var s=1; // 宣告一個不可刪除的全域性變數
sd=2; // 建立全域性物件的一個可刪除的屬性
this.qw=3; // 同上
delete s // => false:變數並沒有被刪除
delete sd // => true :變數被刪除
delete this.qw // => true:變數被刪除