攝影分享:
1.初識JavaScript
1.1JavaScript簡介
JavaScript (簡稱 JS)
-
是世界上最流行的編程語言之一
JS最初只是為了進(jìn)行前端頁面開發(fā).后來JS也被賦予了更多的功能.比如可以用來開發(fā)桌面程序,手機(jī)APP,服務(wù)器端的程序… -
是一個(gè)腳本語言, 通過解釋器運(yùn)行
JS是一種動(dòng)態(tài)類型, 弱類型的腳本語言, 通過解釋器運(yùn)行, 主要在客戶端和瀏覽器上運(yùn)行, 比如Chrome里面專門有一個(gè)模塊, 就是JS引擎, 就相當(dāng)于JVM一樣, 能夠解釋執(zhí)行js代碼, 后來這個(gè)部分的代碼就被大佬們單獨(dú)拎了出來, 封裝成了獨(dú)立的程序, 稱為V8引擎, 這就使JS的適用范圍更廣泛了, 可以使服務(wù)器也能解析JS代碼, 完成交互. -
主要在客戶端(瀏覽器)上運(yùn)行, 現(xiàn)在也可以基于 node.js 在服務(wù)器端運(yùn)行.
JavaScript 之父 布蘭登 * 艾奇 (Brendan Eich):
發(fā)明JS之前的布蘭登&&發(fā)明JS之后的布蘭登:
1995 年, 用 10 天時(shí)間完成 JS 的設(shè)計(jì) (由于設(shè)計(jì)時(shí)間太短,語言的一些細(xì)節(jié)考慮得不夠嚴(yán)謹(jǐn),導(dǎo)致后來很長一段時(shí)間,Javascript
寫出來的程序混亂不堪).最初在網(wǎng)景公司, 命名為 LiveScript,一般認(rèn)為,當(dāng)時(shí) Netscape 之所以將 LiveScript
命名為 JavaScript
,是因?yàn)?Java 是當(dāng)時(shí)最流行的編程語言,帶有 “Java” 的名字有助于這門新生語言的傳播。
其實(shí) Java 和 JavaScript 之間的語法風(fēng)格相去甚遠(yuǎn).
1.2JavaScript 和 HTML 和 CSS 之間的關(guān)系
JS主要在前端中可以完成用戶在網(wǎng)頁和Web服務(wù)器的交互, HTML
描述了網(wǎng)頁的結(jié)構(gòu)(骨), CSS
描述了網(wǎng)頁的樣式(皮), JavaScript
則描述了網(wǎng)頁的行為(魂).
- HTML: 網(wǎng)頁的結(jié)構(gòu)(骨)
- CSS: 網(wǎng)頁的表現(xiàn)(皮)
- JavaScript: 網(wǎng)頁的行為(魂)
1.3JavaScript 運(yùn)行過程
- 編寫的代碼是保存在文件中的, 也就是存儲在硬盤(外存上).
- 雙擊 .html 文件瀏覽器(應(yīng)用程序)就會讀取文件, 把文件內(nèi)容加載到內(nèi)存中(數(shù)據(jù)流向: 硬盤 => 內(nèi)存)
- 瀏覽器會解析用戶編寫的代碼, 把代碼翻譯成二進(jìn)制的, 能讓計(jì)算機(jī)識別的指令(解釋器的工作)
- 得到的二進(jìn)制指令會被 CPU 加載并執(zhí)行(數(shù)據(jù)流向: 內(nèi)存 => CPU)
瀏覽器分成渲染引擎
+ JS 引擎
.
渲染引擎: 解析 html + CSS, 俗稱 “內(nèi)核”
JS 引擎: 也就是 JS 解釋器. 典型的就是 Chrome 中內(nèi)置的 V8
1.4JavaScript 的組成
- ECMAScript(簡稱 ES): JavaScript 語法
- DOM: 頁面文檔對象模型, 對頁面中的元素進(jìn)行操作
- BOM: 瀏覽器對象模型, 對瀏覽器窗口進(jìn)行操作
2.JS基礎(chǔ)語法
2.1在HTML中引入JS
在html中引入JS代碼主要有行內(nèi)式,內(nèi)嵌式和外部式三種.行內(nèi)式直接將JS代碼嵌入到了html勻速內(nèi)部,內(nèi)嵌式將代碼寫入到了script
標(biāo)簽中,外部式將代碼寫到了單獨(dú)的.js
文件中.
在js中有兩種注釋風(fēng)格,單行注釋使用//
來表示,多行注釋使用/**/
來表示.
注意:外部式的script標(biāo)簽中間不能寫代碼,必須空著.(即使寫了也不會被執(zhí)行)
2.2第一個(gè)JS程序
在JS中可以使用alert()這個(gè)函數(shù)來彈出一個(gè)對話警示框, 我們搭配使用html中的button標(biāo)簽使用作為JS的第一個(gè)程序, 順便演示一下上面的三種引入JS的方式.
首先采用行內(nèi)式來寫這個(gè)代碼, 要注意JS中字符串常量可以使用單引號表示, 也可以使用雙引號表示, 但更推薦的寫法是在html中使用雙引號, JS中使用單引號.
<!--行內(nèi)式-->
<button onclick="alert('hello js')">一個(gè)按鈕</button>
<!-- 內(nèi)嵌式 -->
<script>
alert("hello js!");
</script>
<!-- 外部式 -->
<script src="./hello.js"></script>
//hello.js
alert('helloJS');
上面使用alert顯示彈窗提示可以讓用戶看到程序的輸出, 是一種很常見的交互方式, 但彈框操作不方便的地方在于, 有些對話框一彈出來用戶就不能在操作頁面的其他部分了, 必須把彈窗點(diǎn)掉才能繼續(xù)其他操作.
在JS中可以使用console.log來進(jìn)行調(diào)試輸出, 在瀏覽器開發(fā)者工具中, 有一個(gè)控制臺, 在這個(gè)控制臺上就能看到console.log輸出的內(nèi)容, 如果出現(xiàn)了一些異常在控制臺上也會有提示.
2.3變量
語法:
//第一種:
var 變量名 = 值;
//第二種:
let 變量名 = 值;
與java/c/c++不同的是, 關(guān)鍵字var/let
定義的變量可以接收多種類型的變量值, 可以是整數(shù), 浮點(diǎn)數(shù), 字符串, 數(shù)組等, 甚至還可以是函數(shù)變量(有點(diǎn)像C語言中的函數(shù)指針), JS代碼中每個(gè)語句最后帶有一個(gè);結(jié)尾, 可以省略, 但是建議還是加上.
var a = 10;
console.log(a);
let b = 'hello';
console.log(b);
JS中定義變量不用聲明類型并不意味著變量沒有類型, 而是變量的類型是通過初始化操作的值來確定的, 比如值為10變量的類型就是number
類型, 值為字符串常量變量的類型就是string
類型.
雖然JS中var和let關(guān)鍵字都可以定義變量, 但更推薦的寫法是無腦使用let, 這是因?yàn)関ar是老式的寫法, 是有很多坑在里面的, 比如這樣一個(gè)代碼:
使用var
關(guān)鍵字定義兩個(gè)相同的變量是可行的, 而在Java/c/c++中是定義兩個(gè)相同的變量是會報(bào)錯(cuò)的, 而如果使用let
關(guān)鍵字這樣定義也是會報(bào)錯(cuò)的:let
這種寫法是新式寫法, 語法上更接近Java/C++等主流語言, 更符合我們的直覺, 直接使用即可, 具體細(xì)節(jié)不用區(qū)分.
JS是一種動(dòng)態(tài)類型的語言, 一個(gè)變量在運(yùn)行過程種類型可以發(fā)生改變, 就是動(dòng)態(tài)類型(JS, Pychon, PHP, Lua…,); 反之, 類型不能發(fā)生改變就是靜態(tài)類型了(c, c++, java, go…).
動(dòng)態(tài)類型相比于靜態(tài)類型更加的靈活, 但靜態(tài)類型的語言在編譯檢查方面可以做的更好, 寫出來的代碼可維護(hù)性就比較高; 而動(dòng)態(tài)變量當(dāng)下到底是什么類型, 里面是什么樣的值這都是不確定的, 這就使其的類型檢查不是很嚴(yán)格, 代碼維護(hù)起來相較于靜態(tài)類型就比較麻煩.
2.4JS的內(nèi)置類型
-
number
: 數(shù)字, 不區(qū)分整數(shù)和小數(shù). -
boolean
: true 真, false 假. -
string
: 字符串類型. -
undefined
: 只有唯一的值 undefined, 表示未定義的值. -
null
: 只有唯一的值 null, 表示空值.
2.4.1數(shù)字
JS中的數(shù)字不區(qū)分整形和浮點(diǎn)型, 統(tǒng)一都是number類型, 與Java一樣, 支持用二進(jìn)制, 八進(jìn)制, 十六進(jìn)制的表示.
let a = 0o11; //八進(jìn)制整數(shù),以0o開頭
let b = 0x22; //十六進(jìn)制整數(shù),以0x開頭
let c = 0b01; //二進(jìn)制整數(shù),以0b開頭
JS中的有關(guān)數(shù)字運(yùn)算結(jié)果可能出現(xiàn)一些特殊的數(shù)字值, 有如下幾種:
-
Infinity
: 無窮大, 大于任何數(shù)字, 表示數(shù)字已經(jīng)超過了 JS 能表示的范圍. -
Infinity
: 負(fù)無窮大, 小于任何數(shù)字. 表示數(shù)字已經(jīng)超過了 JS 能表示的范圍. -
NaN
: 表示當(dāng)前的結(jié)果不是一個(gè)數(shù)字.
2.4.2字符串
字符串字面值需要使用引號引起來, 單引號雙引號均可, JS中的字符串和Java一樣, 可以使用+運(yùn)算符進(jìn)行不同類型的字符串拼接, 可以使用變量名.lenght求得字符串的長度.
2.4.3布爾類型
JS中布爾類型和C語言類似, true和非0表示可以表示真, false和0可以表示假, JS的布爾類型支持與數(shù)字運(yùn)算, 運(yùn)算時(shí), true表示1, false表示0, 本質(zhì)上也是隱式類型轉(zhuǎn)換, 這在Java中是不行的.
2.4.4undefined類型和null類型
如果一個(gè)變量沒有被初始化過, 那這個(gè)變量就具有唯一的值undefined
, 是undefined類型, 這個(gè)操作其實(shí)就是將其它語言中非法的行為合法化了, 我們知道在Java中未經(jīng)初始化的變量直接訪問是會報(bào)空指針異常的, 但在JS中不會報(bào)錯(cuò), 它會給你返回一個(gè)undefined.
null
與undefined
不同, 它表示變量初始化了, 但值為null
, null
和undefined
都表示取值非法的情況, 但是側(cè)重點(diǎn)不同, null
表示當(dāng)前的值為空(相當(dāng)于有一個(gè)空的盒子), undefined
表示當(dāng)前的變量未定義(相當(dāng)于連盒子都沒有).
2.5運(yùn)算符
JavaScript 中的運(yùn)算符和 Java 用法基本相同. 此處不做詳細(xì)介紹.
算術(shù)運(yùn)算符:+ - * / %
賦值運(yùn)算符 & 復(fù)合賦值運(yùn)算符: = += -= *= /= %=
自增自減運(yùn)算符:++
: 自增1--
: 自減1
比較運(yùn)算符: < > <= >=
== 比較相等(會進(jìn)行隱式類型轉(zhuǎn)換)
!=
=== 比較相等(不會進(jìn)行隱式類型轉(zhuǎn)換)
!==
JS中a==b這個(gè)判斷其實(shí)觸發(fā)了隱式類型轉(zhuǎn)換, 也就是說, JS中針對不相同的類型進(jìn)行比較(==
)運(yùn)算, 會嘗試盡可能的轉(zhuǎn)成相同類型, 而使用===
不會觸發(fā)隱式類型轉(zhuǎn)換了, 所以有了上面的結(jié)果.
像JS這種, 比較能支持隱式類型轉(zhuǎn)換的語言, 稱為 “弱類型” 語言; 反過來像Java這種, 不太支持隱式類型轉(zhuǎn)換的語言就被稱為 “強(qiáng)類型” 語言, 常見語言的強(qiáng)/弱, 動(dòng)態(tài)/靜態(tài)類型就如下圖:
其中C++處在一個(gè)比較特殊的位置了, 這是因?yàn)镃++即要保證和C語言兼容(C語言支持的隱式類型轉(zhuǎn)換C++也得支持), 而同時(shí)C++又在努力的加強(qiáng)自身的類型系統(tǒng), 設(shè)定一些新規(guī)則盡量規(guī)避舊的問題…
邏輯運(yùn)算符:
用于計(jì)算多個(gè) boolean 表達(dá)式的值.&& 與
: 一假則假|| 或
: 一真則真! 非
位運(yùn)算&
按位與|
按位或~
按位取反^
按位異或
移位運(yùn)算<<
左移>>
有符號右移(算術(shù)右移)>>>
無符號右移(邏輯右移)
2.6數(shù)組
2.6.1數(shù)組的基本操作
首先來看數(shù)組的創(chuàng)建:
let arr1 = new Array(); //很少這樣寫
let arr2 = [];
let arr3 = [1,2,3,4,5,6,7,8,9,0];
let arr4 = [1, 'hello', this, [1,'hhh'], null, undefined];
JS中使用[]
來表示數(shù)組, 同時(shí)JS中數(shù)組的元素類型不要求是統(tǒng)一的, 可以是任意的類型, 動(dòng)態(tài)類型的語言基本上都如此.
接下來看數(shù)組的遍歷, 可以直接使用console.log
(數(shù)組名);輸出整個(gè)數(shù)組, 如下:
JS中的數(shù)組也是通過下標(biāo)的方式來訪問的, 所以還可以使用下面幾種for
循環(huán)來進(jìn)行遍歷.
方式一:
方式二:
方式三:
2.6.2數(shù)組的越界訪問
在JS中數(shù)組的越界訪問是合法的, 不會像Java一樣報(bào)空指針異常, 得到的結(jié)果是undefined
.
除了越界訪問, 越界修改數(shù)組的值也是合法的, 此時(shí)數(shù)組的長度也會隨之發(fā)生改變.
觀察結(jié)果可以發(fā)現(xiàn), 當(dāng)數(shù)組越界訪問將下標(biāo)為100的位置的值修改為66時(shí), 數(shù)組的長度就變成了101, 那么中間未初始化的元素值就都為undefined了.
如果說初次接觸看到上面的內(nèi)容還比較合理, 可以接受, 那么下面的內(nèi)容對于第一次接觸JS的來說就可能覺的有些打破認(rèn)知了.
JS在數(shù)組中可以將任意類型作為數(shù)組的下標(biāo)向其中添加元素, 比如負(fù)數(shù), 字符串等作為下標(biāo), 如下代碼.
觀察結(jié)果可以看到, 此時(shí)雖然將兩個(gè)值成功添加到了數(shù)組中, 但數(shù)組的長度并沒有發(fā)生改變, 實(shí)際上, JS中的數(shù)組不僅僅只是一個(gè)傳統(tǒng)意義的數(shù)組(只能按下標(biāo)來訪問元素), 當(dāng)使用負(fù)數(shù), 字符串這些去訪問數(shù)組時(shí), 會生成一個(gè)鍵值對添加到數(shù)組中, 它更像是數(shù)組+Map的結(jié)合體, 這就得數(shù)組也能夠按照Map鍵值對的方式來組織數(shù)據(jù).
2.6.3插入/刪除/修改元素
可以使用push
方法給數(shù)組進(jìn)行尾插式的添加元素.
此處介紹一個(gè)進(jìn)行數(shù)組操作的萬能方法splice
, 它可以完成對數(shù)組的插入, 修改, 刪除等操作.
array.splice(index, howmany, item1, ....., itemX);
它有三個(gè)部分的參數(shù), inded
是必須要有的, 表示在什么位置添加/刪除元素, howmany
是可選參數(shù), 表示要?jiǎng)h除的元素的個(gè)數(shù), item1, …, itemX
是可選的變長參數(shù), 表示要添加到數(shù)組中的新元素.
這三個(gè)部分的參數(shù),如果沒有變長參數(shù)就表示這個(gè)函數(shù)起到的作用是刪除元素
; 如果變長參數(shù)和前面指定的區(qū)間個(gè)數(shù)一樣就表示, 此時(shí)就表示這個(gè)函數(shù)起到的作用是修改/替換元素
; 如果后面變長參數(shù)比前面指定的區(qū)間個(gè)數(shù)要大就表示這個(gè)函數(shù)起到的作用是新增/添加元素
.
刪除元素:
修改元素:
新增元素:
2.7函數(shù)
JS中需要使用function關(guān)鍵字來聲明一個(gè)函數(shù), 結(jié)構(gòu)包括函數(shù)名, 形參列表(不必寫參數(shù)類型), 函數(shù)體; 不必寫返回值類型, 但是可以返回值的.
函數(shù)的定義, 函數(shù)聲明, 函數(shù)調(diào)用的格式如下:
// 創(chuàng)建函數(shù)/函數(shù)聲明/函數(shù)定義
function 函數(shù)名(形參列表) {
函數(shù)體
return 返回值;
}
// 函數(shù)調(diào)用
函數(shù)名(實(shí)參列表) // 不考慮返回值
返回值 = 函數(shù)名(實(shí)參列表) // 考慮返回值
函數(shù)的調(diào)用可以出現(xiàn)在函數(shù)聲明之前, 也可以出現(xiàn)在函數(shù)聲明之后.
hello();
function hello() {
console.log("hello");
}
hello();
在JS中調(diào)用函數(shù)傳入的實(shí)參個(gè)數(shù)比形參多或者是少都是沒關(guān)系的, 只不過如果是少的話沒有收到傳入?yún)?shù)值的變量默認(rèn)值就為undefined了, 此時(shí)進(jìn)行數(shù)值運(yùn)算結(jié)果就為NaN了; 而如果是多的話形參中只能拿到形參個(gè)數(shù)的值, 后面的就拿不到不會參與運(yùn)算了.
但上面的代碼中傳入的實(shí)參個(gè)數(shù)比形參少運(yùn)算后得到的結(jié)果是NaN, 這個(gè)設(shè)定是JS一個(gè)比較坑的地方, 這個(gè)結(jié)果明顯是不符合用戶期望的, 但它也不報(bào)錯(cuò)…
其實(shí)還有一種寫法可以避免上面的問題, 其實(shí)在每個(gè)函數(shù)里面都會自動(dòng)定義一個(gè)arguments變量, 它是個(gè)數(shù)組, 其中包含了所有的實(shí)參, 可以從arguments變量中拿到元素判斷其的值是不是undefined, 然后再進(jìn)行運(yùn)算.
JS中函數(shù)和普通變量一樣, 可以賦值給變量, 此時(shí)變量的類型就是function, 然后該變量可以調(diào)用該函數(shù)或者作為一個(gè)返回值, 就像C語言當(dāng)中的函數(shù)指針一樣, 這點(diǎn)在Java中無法做到, 因?yàn)樵贘S中函數(shù)擁有這種特性, 所以JS函數(shù)也被叫做 “一等公民”.
JS中還支持函數(shù)表達(dá)式的寫法, 即定義一個(gè)匿名函數(shù), 形如: function() { }, 然后將這個(gè)匿名函數(shù)賦值給一個(gè)變, 后面就可以通過這個(gè)變量來調(diào)用函數(shù)了.
將上面的例子改寫成函數(shù)表達(dá)式如下:
在JS中函數(shù)里面是可以繼續(xù)聲明函數(shù)函數(shù)的, 可以無限的進(jìn)行嵌套, 這點(diǎn)在Java當(dāng)中也是不行的.
還有就是在JS中變量的作用域也是有一些特殊的, 當(dāng)代碼中訪問某個(gè)變量的時(shí)候, 會先在當(dāng)前作用域去尋找, 如果當(dāng)前的沒有, 就繼續(xù)往上層作用域一級一級的找, 直到找至全局作用域, 如果還是找不到, 變量的值就為undefined了, 這個(gè)語法設(shè)定和Java中的變量捕獲是類似的.
2.8對象
JS不是面向?qū)ο蟮恼Z言但是存在對象的概念, JS中的對象設(shè)定和Java中的差異較大, JS中沒有繼承, 封裝, 多態(tài), 甚至沒有類, JS中所有的對象的類型都是object, js的對象有屬性也有方法, 不過JS中的方法本質(zhì)上也是屬性(一等公民), 下面介紹JS中對象的創(chuàng)建方式, JS里面的對象是通過鍵值對的方式來組織的.
第一種創(chuàng)建方式是可以直接使用{ }
來創(chuàng)建對象, { }
里面可以寫對象的屬性, 鍵值對之間使用,分割, 鍵和值之間使用:
分割, 方法的值是一個(gè)匿名函數(shù).
let 變量名 = {
//屬性
鍵:值,
...,
//函數(shù)
鍵:function (){
//函數(shù)語句塊
},
...,
//最后一個(gè)屬性逗號可以省略
}
舉例:
訪問屬性可以使用.或[ ]
, 使用[ ]
訪問屬性, 此時(shí)屬性需要加上引號, 調(diào)用方法要記的加上()
.
第二種方式是可以使用new Object
先創(chuàng)建對象, 然后再添加屬性, 上面使用{ }
創(chuàng)建的對象也可以隨時(shí)可以在聲明的對象外新增屬性.
第三種方式是使用構(gòu)造函數(shù)來創(chuàng)建對象, 使用構(gòu)造函數(shù)可以把相同的屬性創(chuàng)建提取出來, 簡化開發(fā)過程.文章來源:http://www.zghlxwxcb.cn/news/detail-548190.html
function 構(gòu)造函數(shù)名(形參列表) {
this.屬性 = 值;
this.函數(shù) = function...;
}
//創(chuàng)建
let obj = new 構(gòu)造方法名(實(shí)參);
在JS的ES6版本中, 引入了class關(guān)鍵字, JS中就可以定義 “類” 了, 然后可以通過類去創(chuàng)建實(shí)例對象, 這種規(guī)則就更接近Java了.文章來源地址http://www.zghlxwxcb.cn/news/detail-548190.html
到了這里,關(guān)于【JavaEE初階】JavaScript基礎(chǔ)語法的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!