JavaScript鞏固與加強一 第一天:JavaScript回顧+函數(shù)+作用域鏈+script代碼執(zhí)行+數(shù)組 兩鏈:作用域鏈+原型鏈 一包:閉包 第二天:事件編程 第三天和第四天:面向?qū)ο?/span>+貪吃蛇游戲開發(fā) 第五天:正則表達(dá)式 一、簡介1、為什么需要JavaScript?2、什么是JavaScriptJavaScript 是網(wǎng)景(Netscape)公司開發(fā)的一種基于客戶端瀏覽器、面向(基于)對象、事件驅(qū)動式的網(wǎng)頁腳本語言。 客戶端瀏覽器: HTML、CSS、JavaScript客戶端語言 PHP/Java/.NET服務(wù)器語言 判斷一種語言是客戶端還是服務(wù)器端,主要看“它”在哪里運行 JavaScript是一種面向?qū)ο蟮哪_本語言 事件驅(qū)動式 3、JavaScript應(yīng)用場景1)網(wǎng)頁特效 2)表單驗證 3)網(wǎng)頁小游戲(超級瑪麗、五子棋、坦克大戰(zhàn)) 4)服務(wù)器端編程(Ajax、Node.js) 4、快速入門例1:通過JavaScript輸出hello world script標(biāo)簽:JavaScript標(biāo)識符 language:告訴瀏覽器在解析時采用哪種語言解析 在現(xiàn)在的瀏覽中,可以不需要指定script中的language屬性,因為瀏覽器默認(rèn)識別到script標(biāo)簽會自動采用JavaScript引擎進行解析 例2:通過script標(biāo)簽的src屬性引入外部js文件 建議:在js中,如何確定js代碼所放置的位置 1)對于函數(shù)聲明、類的定義、外部文件的導(dǎo)入,建議放在head標(biāo)簽中 2)對應(yīng)函數(shù)調(diào)用,代碼執(zhí)行建議放在body標(biāo)簽中 二、JavaScript基本語法1、JavaScript基本格式1)JavaScript區(qū)分大小寫 var i與var I 是不同的 2)JavaScript腳本程序須嵌入在HTML文件中 3)JavaScript腳本程序中不能包含HTML標(biāo)記代碼 如果想在javascript中使用html代碼,可以采用document.write(“<h1>hello world</h1>”); 4)每行寫一條腳本語句 document.write('hello’);alert('world’); 5)語句末尾可以加分號(建議都加分號) document.write('hello world’) alert('hello javascript’); 6)JavaScript腳本程序可以獨立保存為一個外部文件 public.js文件中,并通過script中的src屬性直接引入 2、變量變量是用來臨時存儲數(shù)值的容器,變量存儲的數(shù)值是可以變化的 變量必須要先聲明才能使用,使用var聲明變量 錯誤的: alert(i); 正確的: var i=10; alert(i); 正確的:(只限全局,不推薦使用) i=10; alert(i) 變量的命名規(guī)則:第一個字符必須是英文字母,或者是下劃線(_),還可以是$美元符號,其后的字符,可以是英文字母,數(shù)字,下劃線;變量名不能是JavaScript的保留字 變量的作用域:全局變量、局部變量 3、變量的數(shù)據(jù)類型JavaScript弱類型 1)String 字符類型 在PHP中,單引與雙引是有區(qū)別的,但是在JavaScript中單引號與雙引號都是一樣的 var str = “hello world”; var str = 'hello world’; 2)Number 整型、浮點型、雙精度浮點型 var i=10; var i=10.00 3)Boolean true、false 4)Undefined(變量聲明,但未賦值) 5)Null 空類型 6)Object 對象類型(數(shù)組) 4、運算符1)算術(shù)運算符+ - * / % ++ :自加 -- :自減 var i=10; alert(i++); //先執(zhí)行在加加 var i=10; alert(++i); //先加加在執(zhí)行 2)比較運算符> < == === >= <= != !== ==:值相等,類型可以不同 ===:全等于,要求值相等且類型要一致 3)邏輯運算符&& || ! 4)賦值運算符= += -= *= /= %= 5)字符串運算符+ 5、流程過程1)順序結(jié)構(gòu)例1:獲取dom對象內(nèi)容并更改其值 2)分支結(jié)構(gòu)if else if else switch 例2:判斷當(dāng)前是星期幾 說明: 在if結(jié)構(gòu)中,既可以對固定值的判斷也可以實現(xiàn)對范圍的判斷 在switch,只能實現(xiàn)對固定值的判斷 3)循環(huán)結(jié)構(gòu)for循環(huán) while循環(huán) do…while…循環(huán) for…in…循環(huán) 例1: 什么時候用for循環(huán),什么時候用while循環(huán)? 對于已知循環(huán)次數(shù),我們通常采用for循環(huán)結(jié)構(gòu) 對于未知循環(huán)次數(shù),我們通常采用while循環(huán)結(jié)構(gòu) do…while…與while的區(qū)別 do…while…:先執(zhí)行后判斷 while:先判斷后執(zhí)行 從循環(huán)次數(shù)角度: do…while…始終要比while多執(zhí)行一次 練習(xí):1、編寫九九乘法表 2、有一物,不知其數(shù),三三數(shù)之余二,五五數(shù)之余三,七七數(shù)之余二,問物幾何?(100以內(nèi)) 三、JavaScript中的函數(shù)1、函數(shù)分類1)系統(tǒng)函數(shù) 2)自定義函數(shù) 2、自定義函數(shù)使用函數(shù)前要先定義才能調(diào)用 l 函數(shù)定義有三個部分:函數(shù)名,參數(shù)列表,函數(shù)體 l 定義函數(shù)的格式 function函數(shù)名([參數(shù)1,參數(shù)2...]){ 函數(shù)執(zhí)行部分; return表達(dá)式; } 3、函數(shù)的功能:1)代碼重用 2)模塊化編程 4、快速入門例1:在js中實現(xiàn)打招呼的程序 例2:由于以上代碼有很多重復(fù)性代碼,可以采用函數(shù)進行封裝 例3:改進上題,實現(xiàn)對不同的人打不同的招呼 5、函數(shù)參數(shù)實參:在函數(shù)調(diào)用時,所傳遞的參數(shù),我們稱之為實參 形參:函數(shù)定義時,所指定的參數(shù),我們稱之為形參 例4:函數(shù)形參值的改變并不會影響實參(對象除外) 例5:改進例4 從軟件設(shè)計思想來看例4中的案例,發(fā)現(xiàn)其不滿足“高內(nèi)聚,低耦合”的軟件設(shè)計思想 高內(nèi)聚低耦合:盡量不依賴外在因素運行且功能專一 6、函數(shù)在內(nèi)存中的表現(xiàn)形式說明: 函數(shù)在內(nèi)存中是一段連續(xù)的內(nèi)存地址,放在代碼段中,當(dāng)我們在程序中定義函數(shù)時,系統(tǒng)會自動返回其在內(nèi)存中的首地址,而調(diào)用或執(zhí)行函數(shù)時,系統(tǒng)會自動尋找該地址并執(zhí)行 注:定義函數(shù)時,系統(tǒng)會自動返回該函數(shù)的首地址 例6:其實我們函數(shù)也是一種特殊的量 通過測試我們發(fā)現(xiàn),變量可以存儲任何數(shù)據(jù)的量,那么既然函數(shù)也是一種量,那么我就是說我們的變量也可以存儲函數(shù)的首地址 通過執(zhí)行i(),可以實現(xiàn)對函數(shù)的調(diào)用,代碼如下: 例7:由于以上案例,在賦值過程,函數(shù)名稱并無任何意思,所以可以去除 我們把沒有名字的函數(shù)就稱之為匿名函數(shù) 說明:即使是匿名函數(shù),只要其進行了定義,那么系統(tǒng)就會自動返回其函數(shù)的首地址 7、自調(diào)用匿名函數(shù) 自調(diào)用匿名函數(shù)作用: 在以后項目開發(fā)中,經(jīng)常會引入各種各樣的js代碼庫,如jQuery、Extjs、Dojo,可能在使用過程,就會產(chǎn)生函數(shù)沖突,為了解決函數(shù)沖突問題,我們通常采用自調(diào)用匿名函數(shù)解決此問題。 四、JavaScript中的作用域鏈例1:全局作用域與局部作用域 說明:我們所說的全局變量與和局部變量其實只是相對的 例2:全局作用域中可以不可以直接訪問局部變量 答:以上情況是不允許的,原因: 1)由于作用域鏈不允許 2)由于JavaScript的垃圾回收機制 例3:探討函數(shù)與函數(shù)的關(guān)系 通過觀察,發(fā)現(xiàn)以上代碼可以正常執(zhí)行 例2:函數(shù)如果在函數(shù)中,那么也存在作用域關(guān)系,如下圖所示 通過運行以上代碼,系統(tǒng)會提示fn1()缺少對象,主要是由于當(dāng)執(zhí)行第15行后,系統(tǒng)會自動回收display函數(shù)所占用的內(nèi)存空間,會導(dǎo)致調(diào)用fn1函數(shù)無法找到,所以會產(chǎn)生缺少對象錯誤。 回顧php代碼,在函數(shù)內(nèi)部定義函數(shù),那么在函數(shù)外部是否可以訪問呢? 例3: 通過運行以上代碼,返回結(jié)果displayfn1 也就是說明我們在PHP中可以調(diào)用函數(shù)中的函數(shù) 1、深入探討JavaScript與PHP中的作用域問題PHP中的作用域問題: 在PHP代碼運行過程中,系統(tǒng)首先會加載display函數(shù),并在運行棧區(qū)中開辟一段連續(xù)的內(nèi)存空間,當(dāng)display函數(shù)被調(diào)用時,系統(tǒng)會自動在運行棧區(qū)中,開辟一段獨立且平行的內(nèi)存空間用于fn1的存儲,由于兩者處于平行獨立關(guān)系,所以我可以在display調(diào)用完成后,直接調(diào)用fn1函數(shù)。 JS作用域 在JavaScript代碼運行過程中,系統(tǒng)首先會加載display函數(shù),并在運行棧區(qū)中開辟一段連續(xù)的內(nèi)存空間,當(dāng)display函數(shù)執(zhí)行時,系統(tǒng)會自動在display函數(shù)作用域范圍內(nèi)繼續(xù)開辟一段連續(xù)的內(nèi)存空間用于保存fn1函數(shù),由于兩者處于包含關(guān)系,我們我們沒辦法直接在函數(shù)外直接調(diào)用fn1函數(shù) 例4: 通過觀察以上代碼,我們會發(fā)現(xiàn),系統(tǒng)彈出100,原因: 2、作用域鏈當(dāng)我們在函數(shù)內(nèi)部調(diào)用某一變量時,系統(tǒng)首先在當(dāng)前函數(shù)中尋找var聲明語句(var i),如找到則直接使用,否則繼續(xù)向上一級作用域?qū)ふ?,如找到,則直接使用,否則繼續(xù)向上尋找,直到全局作用域,如找到,則使用,否則會在全局作用域中聲明該變量,我們把這個過程就稱之為作用域鏈 作用域鏈和原理圖: 例5: 以上代碼彈出結(jié)果為1000,原理同上。 例6: 運行結(jié)果:1000,1000 五、script代碼段1、JavaScript中script代碼段執(zhí)行流程:1、讀入第一個代碼段 2、編譯 聲明變量,聲明函數(shù),語法檢查,語義檢查,代碼優(yōu)化,分析并得到代碼樹 3、執(zhí)行 代碼調(diào)用,代碼執(zhí)行 var i = 100; 編譯過程:var i = undefined; 執(zhí)行過程:i=100; 4、讀入下一個代碼段 5、編譯 6、執(zhí)行 7、…… 8、結(jié)束 2、探討代碼段錯誤(編譯錯誤、執(zhí)行錯誤)的影響例1:編譯錯誤對當(dāng)前代碼段所產(chǎn)生的影響 通過運行發(fā)現(xiàn),代碼無法執(zhí)行。原因: 我們知道代碼執(zhí)行分為兩個階段: 編譯階段與執(zhí)行階段,我們沒有寫圓括號,那么系統(tǒng)在編譯過程就會產(chǎn)生錯誤,所以后面的代碼與前面的代碼都無法正常執(zhí)行。 說明:編譯錯誤會導(dǎo)致當(dāng)前代碼段無法執(zhí)行 例2:執(zhí)行錯誤對當(dāng)前代碼段的影響 運行結(jié)果:hello,報錯 說明:當(dāng)前代碼在編譯階段沒有任何異常,在運行時,首先運行第9行代碼,運行到第10行時,系統(tǒng)找不到display函數(shù),所以會報錯(執(zhí)行錯誤),會導(dǎo)致后面的word無法輸出,所以可以說明: script代碼段執(zhí)行錯誤只對當(dāng)前代碼后面的代碼有影響,而不會影響前面代碼的執(zhí)行 例3:編譯錯誤對后面代碼段的影響 例4:執(zhí)行錯誤對后面代碼段的影響 通過例3與例4案例,我們可以得出以下結(jié)論,無論編譯錯誤還是執(zhí)行錯誤,都只對當(dāng)前代碼段有影響,而不會對后面的代碼產(chǎn)生影響。 3、script代碼段執(zhí)行原理圖:面試題:判斷當(dāng)前程序的執(zhí)行結(jié)果? 執(zhí)行結(jié)果: undefined,1000 說明:當(dāng)函數(shù)執(zhí)行到第9-10行時,系統(tǒng)定義全局變量i=100與聲明函數(shù),當(dāng)執(zhí)行到第15行,系統(tǒng)調(diào)用display函數(shù),由于第11行代碼執(zhí)行alert(i),由于作用域鏈原則,系統(tǒng)首先會在當(dāng)前作用域中尋找var聲明,在第12行找到了var聲明,又由于代碼執(zhí)行分為兩個階段編譯與執(zhí)行:由于函數(shù)display內(nèi)在編譯時會定義var i=undefined所以當(dāng)執(zhí)行第11行代碼時,系統(tǒng)首先輸出undefined,當(dāng)執(zhí)行到12行時,系統(tǒng)自動為變量賦值i=1000,當(dāng)執(zhí)行到13行時,系統(tǒng)自動彈出剛才已賦值的變量i=1000,所以兩次結(jié)果為undefined與1000。 六、JavaScript中的數(shù)組1、什么是數(shù)組?答:一組數(shù)據(jù)的集合 一維數(shù)組 二維數(shù)組 多維數(shù)組 2、數(shù)組的定義l var arr=[值1,值2,值3]; //隱式創(chuàng)建 l var arr=new Array(值1,值2,值3); //顯示創(chuàng)建或直接實例化 l var array=new Array(size); //顯示創(chuàng)建并指定數(shù)組長度 例1:通過以上三種方式創(chuàng)建數(shù)組 例2:如何對已定義數(shù)組進行引用 基本語法: 數(shù)組名稱[索引] 例3:如何遍歷輸出數(shù)組數(shù)據(jù) 1)通過for循環(huán)進行遍歷輸出 數(shù)組擁有一個屬性length,標(biāo)識數(shù)組長度 運行結(jié)果: 2)通過for…in…進行遍歷輸出 輸出結(jié)果: 例4:二維數(shù)組定義 運行結(jié)果: 例5:二維數(shù)組遍歷 運行結(jié)果: 3、定義文本下標(biāo)數(shù)組例6:文本下標(biāo)數(shù)組 運行結(jié)果: 彈出小美 例7:文本下標(biāo)數(shù)組元素是不計入數(shù)組長度的 輸出結(jié)果:當(dāng)前數(shù)組中共有3個元素 IE調(diào)試工具,F12彈出,如下圖 調(diào)試結(jié)果如下: 在數(shù)組中,我們的文本下標(biāo)都是通過屬性的形式追加到數(shù)組中,所以其不計入數(shù)組長度。 例8:遍歷輸出帶文本下標(biāo)型數(shù)組 示例代碼: 運行結(jié)果: 七:作業(yè)作業(yè)一:JavaScript中與Array數(shù)組相關(guān)的系統(tǒng)函數(shù)添加數(shù)組元素: l arrayObject.push(newelement1,newelement2,....,newelementX) l arrayObject.unshift(newelement1,newelement2,....,newelementX) l arrayObject.splice(index,howmany,element1,.....,elementX) 刪除數(shù)組元素: l arrayObject.pop() l arrayObject.shift() l arrayObject.splice(index,howmany) 數(shù)組的截取與合并: l arrayObject.slice(start[,end]) l arrayObject.concat(arrayX,arrayX,......,arrayX) l 返回新數(shù)組 數(shù)組的連接: l arrayObject.join(separator) 數(shù)組的切割: l stringObject.split(separator, howmany) 作業(yè)二:省市級聯(lián)(二級聯(lián)動)北京 (海淀區(qū),朝陽區(qū)) 廣州 (天河,海珠區(qū)) |
|