JavaScript
- JavaScript 是世界上最流行的語(yǔ)言之一,是一種運(yùn)行在客戶(hù)端的腳本語(yǔ)言 (Script 是腳本的意思)
- 腳本語(yǔ)言:不需要編譯,運(yùn)行過(guò)程中由 js 解釋器( js 引擎)逐行來(lái)進(jìn)行解釋并執(zhí)行
- 現(xiàn)在也可以基于 Node.js 技術(shù)進(jìn)行服務(wù)器端編程
JavaScript的作用
- 表單動(dòng)態(tài)校驗(yàn)(密碼強(qiáng)度檢測(cè)) ( JS 產(chǎn)生最初的目的 )
- 網(wǎng)頁(yè)特效
- 服務(wù)端開(kāi)發(fā)(Node.js)
- 桌面程序(Electron)
- App(Cordova)
- 控制硬件-物聯(lián)網(wǎng)(Ruff)
- 游戲開(kāi)發(fā)(cocos2d-js)
HTML/CSS/JS 的關(guān)系
HTML/CSS 標(biāo)記語(yǔ)言--描述類(lèi)語(yǔ)言
- HTML 決定網(wǎng)頁(yè)結(jié)構(gòu)和內(nèi)容( 決定看到什么 ),相當(dāng)
于人的身體
- CSS 決定網(wǎng)頁(yè)呈現(xiàn)給用戶(hù)的模樣( 決定好不好看 ),
相當(dāng)于給人穿衣服、化妝
- JS 腳本語(yǔ)言--編程類(lèi)語(yǔ)言
實(shí)現(xiàn)業(yè)務(wù)邏輯和頁(yè)面控制( 決定功能 ),相當(dāng)
于人的各種動(dòng)作
瀏覽器執(zhí)行 JS 簡(jiǎn)介
瀏覽器分成兩部分:渲染引擎和 JS 引擎
- 渲染引擎:用來(lái)解析HTML與CSS,俗稱(chēng)內(nèi)核,比如 chrome 瀏覽器的 blink ,老版本的 webkit
- JS 引擎:也稱(chēng)為 JS 解釋器。 用來(lái)讀取網(wǎng)頁(yè)中的JavaScript代碼,對(duì)其處理后運(yùn)行,比如 chrome 瀏覽器的 V8
瀏覽器本身并不會(huì)執(zhí)行JS代碼,而是通過(guò)內(nèi)置 JavaScript 引擎(解釋器) 來(lái)執(zhí)行 JS 代碼 。JS 引擎執(zhí)行代碼時(shí)逐行解釋
每一句源碼(轉(zhuǎn)換為機(jī)器語(yǔ)言),然后由計(jì)算機(jī)去執(zhí)行,所以 JavaScript 語(yǔ)言歸為腳本語(yǔ)言,會(huì)逐行解釋執(zhí)行。
JS 的組成
- ECMAScript:ECMAScript 規(guī)定了JS的編程語(yǔ)法和基礎(chǔ)核心知識(shí),是所有瀏覽器廠(chǎng)商共同遵守的一套JS語(yǔ)法工業(yè)標(biāo)準(zhǔn)。
- 文檔對(duì)象模型(Document Object Model,簡(jiǎn)稱(chēng)DOM),是W3C組織推薦的處理可擴(kuò)展標(biāo)記語(yǔ)言的標(biāo)準(zhǔn)編程接口。
通過(guò) DOM 提供的接口可以對(duì)頁(yè)面上的各種元素進(jìn)行操作(大小、位置、顏色等)。
- BOM (Browser Object Model,簡(jiǎn)稱(chēng)BOM) 是指瀏覽器對(duì)象模型,它提供了獨(dú)立于內(nèi)容的、可以與瀏覽器窗口進(jìn)行
互動(dòng)的對(duì)象結(jié)構(gòu)。通過(guò)BOM可以操作瀏覽器窗口,比如彈出框、控制瀏覽器跳轉(zhuǎn)、獲取分辨率等。
JS的使用
JS 有3種書(shū)寫(xiě)位置,分別為行內(nèi)、內(nèi)嵌和外部。
- 行內(nèi)式 JS
<input type='button' value='點(diǎn)我試試' onclick='alert('Hello World')' />
2.內(nèi)嵌 JS
<script>
alert('Hello World~!');
</script>
3.外部 JS文件
<script src='my.js'></script>
利于HTML頁(yè)面代碼結(jié)構(gòu)化,把大段 JS代碼獨(dú)立到 HTML 頁(yè)面之外,既美觀(guān),也方便文件級(jí)別的復(fù)用
- 引用外部 JS文件的 script 標(biāo)簽中間不可以寫(xiě)代碼
- 適合于JS 代碼量比較大的情況
JS注釋
- 單行注釋
為了提高代碼的可讀性,JS與CSS一樣,也提供了注釋功能。JS中的注釋主要有兩種,分別是單行注釋和多行注釋。
單行注釋的注釋方式如下:
// 用來(lái)注釋單行文字( 快捷鍵 ctrl + / )
/* 用來(lái)注釋多行文字( 默認(rèn)快捷鍵 alt + shift + a )*/
快捷鍵修改為: ctrl + shift + /
vscode - 首選項(xiàng)按鈕 -鍵盤(pán)快捷方式 -查找 原來(lái)的快捷鍵 - 修改為新的快捷鍵 - 回車(chē)確認(rèn)
JavaScript 輸入輸出語(yǔ)句
為了方便信息的輸入輸出,JS中提供了一些輸入輸出語(yǔ)句,其常用的語(yǔ)句如下:
方法 |
說(shuō)明 |
歸屬 |
alert() |
瀏覽器彈出警示框 |
瀏覽器 |
console.log() |
瀏覽器控制臺(tái)打印輸出信息 |
瀏覽器 |
prompt() |
瀏覽器彈出輸入框,用戶(hù)可以輸入 |
瀏覽器 |
注意:alert() 主要用來(lái)顯示消息給用戶(hù),console.log() 用來(lái)給程序員自己看運(yùn)行時(shí)的消息。
什么是變量
- 通俗:變量是用于存放數(shù)據(jù)的容器。 我們通過(guò) 變量名 獲取數(shù)據(jù),甚至數(shù)據(jù)可以修改。
- 變量在內(nèi)存中的存儲(chǔ)
本質(zhì):變量是程序在內(nèi)存中申請(qǐng)的一塊用來(lái)存放數(shù)據(jù)的空間。
類(lèi)似我們酒店的房間,一個(gè)房間就可以看做是一個(gè)變量。
變量的使用
變量在使用時(shí)分為兩步: 1. 聲明變量 2. 賦值
- 聲明變量
// 聲明變量
var age; // 聲明一個(gè) 名稱(chēng)為age 的變量
- var 是一個(gè) JS關(guān)鍵字,用來(lái)聲明變量( variable 變量的意思 )。使用該關(guān)鍵字聲明變量后,計(jì)算機(jī)會(huì)自動(dòng)為變量分配內(nèi)存空間。
- age 是程序員定義的變量名,我們要通過(guò)變量名來(lái)訪(fǎng)問(wèn)內(nèi)存中分配的空間
- 賦值
age = 10; // 給 age 這個(gè)變量賦值為 10
- = 用來(lái)把右邊的值賦給左邊的變量空間中 此處代表賦值的意思
- 變量值是程序員保存到變量空間里的值
- 變量的初始化
var age = 18; // 聲明變量同時(shí)賦值為 18
聲明一個(gè)變量并賦值, 我們稱(chēng)之為變量的初始化。
注意:一個(gè)變量被重新復(fù)賦值后,它原有的值就會(huì)被覆蓋,變量值將以最后一次賦的值為準(zhǔn)。
4.同時(shí)聲明多個(gè)變量
同時(shí)聲明多個(gè)變量時(shí),只需要寫(xiě)一個(gè) var, 多個(gè)變量名之間使用英文逗號(hào)隔開(kāi)。
var age = 10, name = 'zs', sex = 2;
5.變量命名規(guī)范
- 由字母(A-Za-z)、數(shù)字(0-9)、下劃線(xiàn)(_)、美元符號(hào)( $ )組成,如:usrAge, num01, _name
- 嚴(yán)格區(qū)分大小寫(xiě)。var app; 和 var App; 是兩個(gè)變量
- 不能 以數(shù)字開(kāi)頭。 18age 是錯(cuò)誤的
- 不能 是關(guān)鍵字、保留字。例如:var、for、while
- 變量名必須有意義。
- 遵守駝峰命名法。首字母小寫(xiě),后面單詞的首字母需要大寫(xiě)。 myFirstName
數(shù)據(jù)類(lèi)型
1.為什么需要數(shù)據(jù)類(lèi)型
在計(jì)算機(jī)中,不同的數(shù)據(jù)所需占用的存儲(chǔ)空間是不同的,為了便于把數(shù)據(jù)分成所需內(nèi)存大小不同的數(shù)據(jù),充分利用存儲(chǔ)空間,于是定義了不同的數(shù)據(jù)類(lèi)型。
2.變量的數(shù)據(jù)類(lèi)型
變量是用來(lái)存儲(chǔ)值的所在處,它們有名字和數(shù)據(jù)類(lèi)型。變量的數(shù)據(jù)類(lèi)型決定了如何將代表這些值的位存儲(chǔ)到計(jì)算機(jī)的內(nèi)存中。
JavaScript 是一種弱類(lèi)型或者說(shuō)動(dòng)態(tài)語(yǔ)言。這意味著不用提前聲明變量的類(lèi)型,在程序運(yùn)行過(guò)程中,類(lèi)型會(huì)被自動(dòng)確定。
var age = 10; // 這是一個(gè)數(shù)字型
var areYouOk = '是的'; // 這是一個(gè)字符串
var x = 6; // x 為數(shù)字
var x = 'Bill'; // x 為字符串
在代碼運(yùn)行時(shí),變量的數(shù)據(jù)類(lèi)型是由 JS引擎 根據(jù) = 右邊變量值的數(shù)據(jù)類(lèi)型來(lái)判斷 的,運(yùn)行完畢之后, 變量就確定了數(shù)據(jù)類(lèi)型。
JavaScript 擁有動(dòng)態(tài)類(lèi)型,同時(shí)也意味著相同的變量可用作不同的類(lèi)型:
var x = 6; // x 為數(shù)字
var x = 'Bill'; // x 為字符串
數(shù)據(jù)類(lèi)型的分類(lèi)
- JS 把數(shù)據(jù)類(lèi)型分為兩類(lèi):
- 簡(jiǎn)單數(shù)據(jù)類(lèi)型 (Number,String,Boolean,Undefined,Null)
- 復(fù)雜數(shù)據(jù)類(lèi)型 (object)
- 簡(jiǎn)單數(shù)據(jù)類(lèi)型(基本數(shù)據(jù)類(lèi)型)
JavaScript 中的簡(jiǎn)單數(shù)據(jù)類(lèi)型及其說(shuō)明如下:
簡(jiǎn)單數(shù)據(jù)類(lèi)型 |
說(shuō)明 |
默認(rèn)值 |
Number |
數(shù)字型,包含整型值和浮點(diǎn)型值,如21. 0.21 |
0 |
Boolean |
布爾值類(lèi)型,如true、 false, 等價(jià)于1和0 |
false |
String |
字符串類(lèi)型,如'張三'注意咱們js里面,字符串都帶引號(hào) |
'' |
Undefined |
var a;聲明了變量a但是沒(méi)有給值,此時(shí)a = undefined |
undefined |
Null |
vara=null;聲明了變量a為空值 |
null |
- 數(shù)字型范圍
JavaScript中數(shù)值的最大和最小值
alert(Number.MAX_VALUE); // 1.7976931348623157e+308
alert(Number.MIN_VALUE); // 5e-324
- 最大值:Number.MAX_VALUE,這個(gè)值為: 1.7976931348623157e+308
- 最小值:Number.MIN_VALUE,這個(gè)值為:5e-32
- 數(shù)字型三個(gè)特殊值
alert(Infinity); // Infinity
alert(-Infinity); // -Infinity
alert(NaN); // NaN
- Infinity ,代表無(wú)窮大,大于任何數(shù)值
- -Infinity ,代表無(wú)窮小,小于任何數(shù)值
- NaN ,Not a number,代表一個(gè)非數(shù)值
5.isNaN()
用來(lái)判斷一個(gè)變量是否為非數(shù)字的類(lèi)型,返回 true 或者 false
var usrAge = 21;
var isOk = isNaN(userAge);
console.log(isNum); // false ,21 不是一個(gè)非數(shù)字
var usrName = 'andy';
console.log(isNaN(userName)); // true ,'andy'是一個(gè)非數(shù)字
6.字符串型 String
字符串型可以是引號(hào)中的任意文本,其語(yǔ)法為 雙引號(hào) '' 和 單引號(hào)''
var strMsg = '我愛(ài)北京~'; // 使用雙引號(hào)表示字符串
var strMsg2 = '我愛(ài)北京~'; // 使用單引號(hào)表示字符串
注意:因?yàn)?HTML 標(biāo)簽里面的屬性使用的是雙引號(hào),JS 這里我們更推薦使用單引號(hào)。
7.字符串引號(hào)嵌套
JS 可以用單引號(hào)嵌套雙引號(hào) ,或者用雙引號(hào)嵌套單引號(hào) (外雙內(nèi)單,外單內(nèi)雙)
var strMsg = '我要'親親'寶寶'; // 可以用''包含''
var strMsg2 = '我要'親親'寶寶'; // 也可以用'' 包含''
8.字符串轉(zhuǎn)義符
類(lèi)似HTML里面的特殊字符,字符串中也有特殊字符,我們稱(chēng)之為轉(zhuǎn)義符。
轉(zhuǎn)義符都是 \ 開(kāi)頭的
轉(zhuǎn)義符都是 \ 開(kāi)頭的,常用的轉(zhuǎn)義符及其說(shuō)明如下:
轉(zhuǎn)義符 |
解釋說(shuō)明 |
\n |
換行符,n 是 newline 的意思 |
\ \ |
斜杠 \ |
' |
' 單引號(hào) |
' |
”雙引號(hào) |
\t |
tab 縮進(jìn) |
\b |
空格 ,b 是 blank 的意思 |
9.字符串是由若干字符組成的,這些字符的數(shù)量就是字符串的長(zhǎng)度。通過(guò)字符串的 length 屬性可以獲取整個(gè)字符串的長(zhǎng)度。
(注意空格也是一個(gè)字符串哦)
var strMsg = '我餓了!';
alert(strMsg.length); // 顯示 4
10.字符串拼接
- 多個(gè)字符串之間可以使用 + 進(jìn)行拼接,其拼接方式為 字符串 + 任何類(lèi)型 = 拼接之后的新字符串
- 拼接前會(huì)把與字符串相加的任何類(lèi)型轉(zhuǎn)成字符串,再拼接成一個(gè)新的字符串
//1 字符串 '相加'
alert('hello' + ' ' + 'world'); // hello world
//2 數(shù)值字符串 '相加'
alert('100' + '100'); // 100100
//3 數(shù)值字符串 + 數(shù)值
alert('11' + 12); // 1112
11.布爾型 Boolean
布爾類(lèi)型有兩個(gè)值:true 和 false ,其中 true 表示真(對(duì)),而 false 表示假(錯(cuò))。
布爾型和數(shù)字型相加的時(shí)候, true 的值為 1 ,false 的值為 0。
console.log(true + 1); // 2
console.log(false + 1); // 1
12.Undefined 和 Null
一個(gè)聲明后沒(méi)有被賦值的變量會(huì)有一個(gè)默認(rèn)值 undefined ( 如果進(jìn)行相連或者相加時(shí),注意結(jié)果)
var variable;
console.log(variable); // undefined
console.log('你好' + variable); // 你好undefined
console.log(11 + variable); // NaN
console.log(true + variable); // NaN
一個(gè)聲明變量給 null 值,里面存的值為空(學(xué)習(xí)對(duì)象時(shí),我們繼續(xù)研究null)
var vari = null;
console.log('你好' + vari); // 你好null
console.log(11 + vari); // 11
console.log(true + vari); // 1
獲取檢測(cè)變量的數(shù)據(jù)類(lèi)型
1.typeof 可用來(lái)獲取檢測(cè)變量的數(shù)據(jù)類(lèi)型
var num = 18;
console.log(typeof num) // 結(jié)果 number
注意:null的返回值不是null,是object
2.字面量
字面量是在源代碼中一個(gè)固定值的表示法,通俗來(lái)說(shuō),就是字面量表示如何表達(dá)這個(gè)值。
數(shù)據(jù)類(lèi)型轉(zhuǎn)換
使用表單、prompt 獲取過(guò)來(lái)的數(shù)據(jù)默認(rèn)是字符串類(lèi)型的,此時(shí)就不能直接簡(jiǎn)單的進(jìn)行加法運(yùn)算,而需要轉(zhuǎn)換變量的數(shù)據(jù)類(lèi)型。通俗來(lái)說(shuō),就是把一種數(shù)據(jù)類(lèi)型的變量轉(zhuǎn)換成另外一種數(shù)據(jù)類(lèi)型。
我們通常會(huì)實(shí)現(xiàn)3種方式的轉(zhuǎn)換:
- 轉(zhuǎn)換為字符串類(lèi)型
- 轉(zhuǎn)換為數(shù)字型
- 轉(zhuǎn)換為布爾型
1.轉(zhuǎn)換為字符串
方式 |
說(shuō)明 |
案例 |
toString( ) |
轉(zhuǎn)成字符串 |
var num= 1; alert(num.toString); |
String( )強(qiáng)制轉(zhuǎn)換 |
轉(zhuǎn)成字符串 |
var num = 1; alert(String(num); |
- toString() 和 String() 使用方式不一樣。
2.轉(zhuǎn)換為數(shù)字型(重點(diǎn))
方式 |
說(shuō)明 |
案例 |
parselInt(string)函數(shù) |
將string類(lèi)型轉(zhuǎn)成整數(shù)數(shù)值型 |
parselnt(78) |
parseFloat(string)函數(shù) |
將string類(lèi)型轉(zhuǎn)成浮點(diǎn)數(shù)數(shù)值型 |
parseFloat(78.21') |
Number()強(qiáng)制轉(zhuǎn)換函數(shù) |
將string類(lèi)型轉(zhuǎn)換為數(shù)值型 |
Number('12') |
js隱式轉(zhuǎn)換(- * /) |
利用算術(shù)運(yùn)算隱式轉(zhuǎn)換為數(shù)值型 |
'12'-0 |
- 注意 parseInt 和 parseFloat 單詞的大小寫(xiě),這2個(gè)是重點(diǎn)
- 隱式轉(zhuǎn)換是我們?cè)谶M(jìn)行算數(shù)運(yùn)算的時(shí)候,JS 自動(dòng)轉(zhuǎn)換了數(shù)據(jù)類(lèi)型
3.轉(zhuǎn)換為布爾型
- 代表空、否定的值會(huì)被轉(zhuǎn)換為 false ,如 ''、0、NaN、null、undefined
- 其余值都會(huì)被轉(zhuǎn)換為 true
方式 |
說(shuō)明 |
案例 |
Boolean( )函數(shù) |
其他類(lèi)型轉(zhuǎn)成布爾值 |
Boolean'true'; |
console.log(Boolean('')); // false
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean('小白')); // true
console.log(Boolean(12)); // true
運(yùn)算符(操作符)
運(yùn)算符的分類(lèi)
?運(yùn)算符(operator)也被稱(chēng)為操作符,是用于實(shí)現(xiàn)賦值、比較和執(zhí)行算數(shù)運(yùn)算等功能的符號(hào)。
JavaScript中常用的運(yùn)算符有:
- 算數(shù)運(yùn)算符
- 遞增和遞減運(yùn)算符
- 比較運(yùn)算符
- 邏輯運(yùn)算符
- 賦值運(yùn)算符
算數(shù)運(yùn)算符
運(yùn)算符 |
描述 |
實(shí)例 |
+ |
加 |
10+ 20= 30 |
- |
減 |
10- 20=-10 |
* |
乘 |
10* 20= 200 |
/ |
除 |
10/20= 0.5 |
% |
取余數(shù)(取模) |
返回除法的余數(shù)9%2= 1 |
-
浮點(diǎn)數(shù)的精度問(wèn)題
?浮點(diǎn)數(shù)值的最高精度是 17 位小數(shù),但在進(jìn)行算術(shù)計(jì)算時(shí)其精確度遠(yuǎn)遠(yuǎn)不如整數(shù)。
var result = 0.1 + 0.2;//結(jié)果是:0.30000000000000004
console.log(0.07 * 100);//結(jié)果是:7.000000000000001
?所以:不要直接判斷兩個(gè)浮點(diǎn)數(shù)是否相等 !
-
表達(dá)式和返回值
表達(dá)式:是由數(shù)字、運(yùn)算符、變量等以能求得數(shù)值的有意義排列方法所得的組合
?簡(jiǎn)單理解:是由數(shù)字、運(yùn)算符、變量等組成的式子
?表達(dá)式最終都會(huì)有一個(gè)結(jié)果,返回給開(kāi)發(fā)者,稱(chēng)為返回值
遞增和遞減運(yùn)算符
-
遞增和遞減運(yùn)算符概述
?如果需要反復(fù)給數(shù)字變量添加或減去1,可以使用遞增(++)和遞減( -- )運(yùn)算符來(lái)完成。
在 JavaScript 中,遞增(++)和遞減( -- )既可以放在變量前面,也可以放在變量后面。放在變量前面時(shí),我們可以稱(chēng)為前置遞增(遞減)運(yùn)算符,放在變量后面時(shí),我們可以稱(chēng)為后置遞增(遞減)運(yùn)算符。
注意:遞增和遞減運(yùn)算符必須和變量配合使用。
-
遞增運(yùn)算符
var num = 10;
alert(++num + 10); // 21
var num = 10;
alert(10 + num++); // 20
總結(jié):
1. 前置遞增和后置遞增運(yùn)算符可以簡(jiǎn)化代碼的編寫(xiě),讓變量的值 + 1 比以前寫(xiě)法更簡(jiǎn)單
2. 單獨(dú)使用時(shí),運(yùn)行結(jié)果相同
3. 與其他代碼聯(lián)用時(shí),執(zhí)行結(jié)果會(huì)不同
4. 后置:先原值運(yùn)算,后自加(先人后己)
5. 前置:先自加,后運(yùn)算(先已后人)
6. 大多使用后置遞增/減,并且代碼獨(dú)占一行,例如:num++; 或者 num--;
比較運(yùn)算符
運(yùn)算符名稱(chēng) |
說(shuō)明 |
案例 |
結(jié)果 |
< |
小于號(hào) |
1<2 |
true |
> |
大于號(hào) |
1>2 |
false |
>= |
大于等于號(hào)(大于或者等于) |
2>= 2 |
true |
<= |
小于等于號(hào)(小于或者等于) |
3<= 2 |
false |
== |
等號(hào) |
37 == 37 |
true |
!= |
不等號(hào) |
37 != 37 |
false |
=== |
全等要求值和數(shù)據(jù)類(lèi)型都一致 |
37 === '37' |
false |
符號(hào) |
作用 |
用法 |
= |
賦值 |
把右邊給左邊 |
== |
判斷 |
判斷兩邊值是否相等 |
=== |
全等 |
判斷兩邊的值和數(shù)據(jù)類(lèi)型是否完全相同 |
console.log(18 == '18'); // true
console.log(18 === '18'); // false
邏輯運(yùn)算符
邏輯運(yùn)算符 |
說(shuō)明 |
案例 |
&& |
“邏輯與',簡(jiǎn)稱(chēng)'與”and |
true && false |
|| |
'邏輯或',簡(jiǎn)稱(chēng)'或” or |
true || false |
! |
“邏輯非',簡(jiǎn)稱(chēng)“非' not |
! true |
-
邏輯與&&
?兩邊都是 true才返回 true,否則返回 false
-
邏輯或 ||
?兩邊都是 true才返回 true,否則返回 false
-
邏輯非 !
?邏輯非(!)也叫作取反符,用來(lái)取一個(gè)布爾值相反的值,如 true 的相反值是 false
var isOk = !true;
console.log(isOk); // false
賦值運(yùn)算符
?概念:用來(lái)把數(shù)據(jù)賦值給變量的運(yùn)算符。
賦值運(yùn)算符 |
說(shuō)明 |
案例 |
= |
直接賦值 |
var usrName ='我是值'; |
+= , - = |
加、減一個(gè)數(shù)后在賦值 |
varage= 10; age+=5; // 15 |
*=、/=、%= |
乘、除、取模后在賦值 |
varage= 2; age*=5;// 10. |
var age = 10;
age += 5; // 相當(dāng)于 age = age + 5;
age -= 5; // 相當(dāng)于 age = age - 5;
age *= 10; // 相當(dāng)于 age = age * 10;
運(yùn)算符優(yōu)先級(jí)
優(yōu)先級(jí) |
運(yùn)算符 |
順序 |
1 |
小括號(hào) |
( ) |
2 |
一元運(yùn)算符 |
++ -- ! |
3 |
算數(shù)運(yùn)算符 |
先* / % 后+ - |
4 |
關(guān)系運(yùn)算符 |
> >= < <= |
5 |
相等運(yùn)算符 |
== != === !== |
6 |
邏輯運(yùn)算符 |
先&&后|| |
7 |
賦值運(yùn)算符 |
= |
8 |
逗號(hào)運(yùn)算符 |
, |
- 一元運(yùn)算符里面的邏輯非優(yōu)先級(jí)很高
- 邏輯與比邏輯或優(yōu)先級(jí)高
流程控制
流程控制概念
?在一個(gè)程序執(zhí)行的過(guò)程中,各條代碼的執(zhí)行順序?qū)Τ绦虻慕Y(jié)果是有直接影響的。很多時(shí)候我們要通過(guò)控制代碼的執(zhí)行順序來(lái)實(shí)現(xiàn)我們要完成的功能。
?簡(jiǎn)單理解:流程控制就是來(lái)控制代碼按照一定結(jié)構(gòu)順序來(lái)執(zhí)行
?流程控制主要有三種結(jié)構(gòu):順序結(jié)構(gòu)、分支(選擇)結(jié)構(gòu)、循環(huán)結(jié)構(gòu)
順序流程控制
分支流程控制
?
?JS 語(yǔ)言提供了兩種分支結(jié)構(gòu)語(yǔ)句:if 語(yǔ)句、switch 語(yǔ)句
-
if 語(yǔ)句
// 條件成立執(zhí)行代碼,否則什么也不做
if (條件表達(dá)式) {
// 條件成立執(zhí)行的代碼語(yǔ)句
}
語(yǔ)句可以理解為一個(gè)行為,循環(huán)語(yǔ)句和分支語(yǔ)句就是典型的語(yǔ)句。一個(gè)程序由很多個(gè)語(yǔ)句組成,一般情況下,會(huì)分割成一個(gè)一個(gè)的語(yǔ)句。
-
if else語(yǔ)句(雙分支語(yǔ)句)
-
if else if 語(yǔ)句(多分支語(yǔ)句)
總結(jié):
if語(yǔ)句
語(yǔ)法結(jié)構(gòu)
if (/* 條件表達(dá)式 */) {
// 執(zhí)行語(yǔ)句
}
if (/* 條件表達(dá)式 */){
// 成立執(zhí)行語(yǔ)句
} else {
// 否則執(zhí)行語(yǔ)句
}
if (/* 條件1 */){
// 成立執(zhí)行語(yǔ)句
} else if (/* 條件2 */){
// 成立執(zhí)行語(yǔ)句
} else if (/* 條件3 */){
// 成立執(zhí)行語(yǔ)句
} else {
// 最后默認(rèn)執(zhí)行語(yǔ)句
}
三元表達(dá)式
switch分支流程控制
-
語(yǔ)法結(jié)構(gòu)
switch( 表達(dá)式 ){
case value1:
// 表達(dá)式 等于 value1 時(shí)要執(zhí)行的代碼
break;
case value2:
// 表達(dá)式 等于 value2 時(shí)要執(zhí)行的代碼
break;
default:
// 表達(dá)式 不等于任何一個(gè) value 時(shí)要執(zhí)行的代碼
}
-
關(guān)鍵字 switch 后面括號(hào)內(nèi)可以是表達(dá)式或值, 通常是一個(gè)變量
-
關(guān)鍵字 case , 后跟一個(gè)選項(xiàng)的表達(dá)式或值,后面跟一個(gè)冒號(hào)
-
switch 表達(dá)式的值會(huì)與結(jié)構(gòu)中的 case 的值做比較
-
如果存在匹配全等(===) ,則與該 case 關(guān)聯(lián)的代碼塊會(huì)被執(zhí)行,并在遇到 break 時(shí)停止,整個(gè) switch 語(yǔ)句代碼執(zhí)行結(jié)束
-
如果所有的 case 的值都和表達(dá)式的值不匹配,則執(zhí)行 default 里的代碼
注意: 執(zhí)行case 里面的語(yǔ)句時(shí),如果沒(méi)有break,則繼續(xù)執(zhí)行下一個(gè)case里面的語(yǔ)句。
-
switch 語(yǔ)句和 if else if 語(yǔ)句的區(qū)別
- 一般情況下,它們兩個(gè)語(yǔ)句可以相互替換
- switch...case 語(yǔ)句通常處理 case為比較確定值的情況, 而 if…else…語(yǔ)句更加靈活,常用于范圍判斷(大于、等于某個(gè)范圍)
- switch 語(yǔ)句進(jìn)行條件判斷后直接執(zhí)行到程序的條件語(yǔ)句,效率更高。而if…else 語(yǔ)句有幾種條件,就得判斷多少次。
- 當(dāng)分支比較少時(shí),if… else語(yǔ)句的執(zhí)行效率比 switch語(yǔ)句高。
- 當(dāng)分支比較多時(shí),switch語(yǔ)句的執(zhí)行效率比較高,而且結(jié)構(gòu)更清晰。
循環(huán)結(jié)構(gòu)
在javascript中,循環(huán)語(yǔ)句有三種,while、do..while、for循環(huán)。
for循環(huán)
小結(jié):
while和do...while一般用來(lái)解決無(wú)法確認(rèn)次數(shù)的循環(huán)。
for循環(huán)一般在循環(huán)次數(shù)確定的時(shí)候比較方便
- 執(zhí)行操作表達(dá)式,此時(shí)第一輪結(jié)束。
- 第二輪開(kāi)始,直接去執(zhí)行條件表達(dá)式(不再初始化變量),如果為 true ,則去執(zhí)行循環(huán)體語(yǔ)句,否則退出循環(huán)。
- 繼續(xù)執(zhí)行操作表達(dá)式,第二輪結(jié)束。
- 后續(xù)跟第二輪一致,直至條件表達(dá)式為假,結(jié)束整個(gè) for 循環(huán)。
雙重for循環(huán)
-
雙重 for 循環(huán)概述
循環(huán)嵌套是指在一個(gè)循環(huán)語(yǔ)句中再定義一個(gè)循環(huán)語(yǔ)句的語(yǔ)法結(jié)構(gòu),例如在for循環(huán)語(yǔ)句中,可以再嵌套一個(gè)for 循環(huán),這樣的 for 循環(huán)語(yǔ)句我們稱(chēng)之為雙重for循環(huán)。
-
雙重 for 循環(huán)語(yǔ)法
for (外循環(huán)的初始; 外循環(huán)的條件; 外循環(huán)的操作表達(dá)式) {
for (內(nèi)循環(huán)的初始; 內(nèi)循環(huán)的條件; 內(nèi)循環(huán)的操作表達(dá)式) {
需執(zhí)行的代碼;
}
}
- 內(nèi)層循環(huán)可以看做外層循環(huán)的循環(huán)體語(yǔ)句
- 內(nèi)層循環(huán)執(zhí)行的順序也要遵循 for 循環(huán)的執(zhí)行順序
- 外層循環(huán)執(zhí)行一次,內(nèi)層循環(huán)要執(zhí)行全部次數(shù)
-
打印五行五列星星
var star = '';
for (var j = 1; j <= 3; j++) {
for (var i = 1; i <= 3; i++) {
star += '☆'
}
// 每次滿(mǎn) 5個(gè)星星 就 加一次換行
star += '\n'
}
console.log(star);
核心邏輯:
1.內(nèi)層循環(huán)負(fù)責(zé)一行打印五個(gè)星星
2.外層循環(huán)負(fù)責(zé)打印五行
-
for 循環(huán)小結(jié)
- for 循環(huán)可以重復(fù)執(zhí)行某些相同代碼
- for 循環(huán)可以重復(fù)執(zhí)行些許不同的代碼,因?yàn)槲覀冇杏?jì)數(shù)器
- for 循環(huán)可以重復(fù)執(zhí)行某些操作,比如算術(shù)運(yùn)算符加法操作
- 隨著需求增加,雙重for循環(huán)可以做更多、更好看的效果
- 雙重 for 循環(huán),外層循環(huán)一次,內(nèi)層 for 循環(huán)全部執(zhí)行
- for 循環(huán)是循環(huán)條件和數(shù)字直接相關(guān)的循環(huán)
JS要理解掌握的代碼題型:
打印1-100之間所有數(shù)
求1-100之間所有數(shù)的和
求1-100之間所有數(shù)的平均值
求1-100之間所有偶數(shù)的和
同時(shí)求1-100之間所有偶數(shù)和奇數(shù)的和
打印正方形
// console.log 輸出重復(fù)內(nèi)容的問(wèn)題
// console.log 默認(rèn)輸出內(nèi)容介紹后有換行
var start = '';
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
start += '* ';
}
start += '\n';
}
console.log(start);
打印直角三角形
var start = '';
for (var i = 0; i < 10; i++) {
for (var j = i; j < 10; j++) {
start += '* ';
}
start += '\n';
}
console.log(start);
打印9*9乘法表
var str = '';
for (var i = 1; i <= 9; i++) {
for (var j = i; j <=9; j++) {
str += i + ' * ' + j + ' = ' + i * j + '\t';
}
str += '\n';
}
console.log(str);
while循環(huán)
while語(yǔ)句的語(yǔ)法結(jié)構(gòu)如下:
while (條件表達(dá)式) {
// 循環(huán)體代碼
}
執(zhí)行思路:
- 1 先執(zhí)行條件表達(dá)式,如果結(jié)果為 true,則執(zhí)行循環(huán)體代碼;如果為 false,則退出循環(huán),執(zhí)行后面代碼
- 2 執(zhí)行循環(huán)體代碼
- 3 循環(huán)體代碼執(zhí)行完畢后,程序會(huì)繼續(xù)判斷執(zhí)行條件表達(dá)式,如條件仍為true,則會(huì)繼續(xù)執(zhí)行循環(huán)體,直到循環(huán)條件為 false 時(shí),整個(gè)循環(huán)過(guò)程才會(huì)結(jié)束
注意:
- 使用 while 循環(huán)時(shí)一定要注意,它必須要有退出條件,否則會(huì)成為死循環(huán)
1.4 do-while循環(huán)
do... while 語(yǔ)句的語(yǔ)法結(jié)構(gòu)如下:
do {
// 循環(huán)體代碼 - 條件表達(dá)式為 true 時(shí)重復(fù)執(zhí)行循環(huán)體代碼
} while(條件表達(dá)式);
執(zhí)行思路
continue和break
break:立即跳出整個(gè)循環(huán),即循環(huán)結(jié)束,開(kāi)始執(zhí)行循環(huán)后面的內(nèi)容(直接跳到大括號(hào))
continue:立即跳出當(dāng)前循環(huán),繼續(xù)下一次循環(huán)(跳到i++的地方)
數(shù)組
1.1 數(shù)組的概念
- 數(shù)組可以把一組相關(guān)的數(shù)據(jù)一起存放,并提供方便的訪(fǎng)問(wèn)(獲?。┓绞?。
- 數(shù)組是指一組數(shù)據(jù)的集合,其中的每個(gè)數(shù)據(jù)被稱(chēng)作元素,在數(shù)組中可以存放任意類(lèi)型的元素。數(shù)組是一種將一組數(shù)據(jù)存儲(chǔ)在單個(gè)變量名下的優(yōu)雅方式。
1.2 創(chuàng)建數(shù)組
JS 中創(chuàng)建數(shù)組有兩種方式:
// 創(chuàng)建一個(gè)空數(shù)組
var arr1 = [];
// 創(chuàng)建一個(gè)包含3個(gè)數(shù)值的數(shù)組,多個(gè)數(shù)組項(xiàng)以逗號(hào)隔開(kāi)
var arr2 = [1, 3, 4];
// 創(chuàng)建一個(gè)包含2個(gè)字符串的數(shù)組
var arr3 = ['a', 'c'];
// 可以通過(guò)數(shù)組的length屬性獲取數(shù)組的長(zhǎng)度
console.log(arr3.length);
// 可以設(shè)置length屬性改變數(shù)組中元素的個(gè)數(shù)
arr3.length = 0;
- 數(shù)組的字面量是方括號(hào) [ ]
- 聲明數(shù)組并賦值稱(chēng)為數(shù)組的初始化
- 這種字面量方式也是我們以后最多使用的方式
-
數(shù)組元素的類(lèi)型
數(shù)組中可以存放任意類(lèi)型的數(shù)據(jù),例如字符串,數(shù)字,布爾值等。
var arrStus = ['小白',12,true,28.9];
1.3 獲取數(shù)組中的元素
?索引 (下標(biāo)) :用來(lái)訪(fǎng)問(wèn)數(shù)組元素的序號(hào)(數(shù)組下標(biāo)從 0 開(kāi)始)。
數(shù)組可以通過(guò)索引來(lái)訪(fǎng)問(wèn)、設(shè)置、修改對(duì)應(yīng)的數(shù)組元素,可以通過(guò)“數(shù)組名[索引]”的形式來(lái)獲取數(shù)組中的元素。
// 定義數(shù)組
var arrStus = [1,2,3];
// 獲取數(shù)組中的第2個(gè)元素
alert(arrStus[1]);
注意:如果訪(fǎng)問(wèn)時(shí)數(shù)組沒(méi)有和索引值對(duì)應(yīng)的元素,則得到的值是undefined
遍歷數(shù)組
遍歷:遍及所有,對(duì)數(shù)組的每一個(gè)元素都訪(fǎng)問(wèn)一次就叫遍歷。
數(shù)組遍歷的基本語(yǔ)法:
for(var i = 0; i < arr.length; i++) {
// 數(shù)組遍歷的固定結(jié)構(gòu)
}
-
數(shù)組的長(zhǎng)度
數(shù)組的長(zhǎng)度:默認(rèn)情況下表示數(shù)組中元素的個(gè)數(shù)
使用“數(shù)組名.length”可以訪(fǎng)問(wèn)數(shù)組元素的數(shù)量(數(shù)組長(zhǎng)度)。
var arrStus = [1,2,3];
alert(arrStus.length); // 3
注意:
- 此處數(shù)組的長(zhǎng)度是數(shù)組元素的個(gè)數(shù) ,不要和數(shù)組的索引號(hào)混淆。
-
當(dāng)我們數(shù)組里面的元素個(gè)數(shù)發(fā)生了變化,這個(gè) length 屬性跟著一起變化
-
如果設(shè)置的length屬性值大于數(shù)組的元素個(gè)數(shù),則會(huì)在數(shù)組末尾出現(xiàn)空白元素;
- 如果設(shè)置的length屬性值小于數(shù)組的元素個(gè)數(shù),則會(huì)把超過(guò)該值的數(shù)組元素刪除
數(shù)組中新增元素
數(shù)組的賦值
// 格式:數(shù)組名[下標(biāo)/索引] = 值;
// 如果下標(biāo)有對(duì)應(yīng)的值,會(huì)把原來(lái)的值覆蓋,如果下標(biāo)不存在,
//會(huì)給數(shù)組新增一個(gè)元素。
var arr = ['red', 'green', 'blue'];
// 把red替換成了yellow
arr[0] = 'yellow';
// 給數(shù)組新增加了一個(gè)pink的值
arr[3] = 'pink';
JS數(shù)組要會(huì)的題:
/* 求數(shù)組[2,6,1,77,52,25,7]中的最大值。
分析:冒泡排序法:是一種算法,把一系列的數(shù)據(jù)按照一定的順序進(jìn)行排列顯示
(從小到大或從大到?。?。
回顧:把2個(gè)變量交換數(shù)據(jù)
// 利用第三個(gè)變量
var num1 = 10;
var num2 = 20;
var temp = num1;
num1 = num2;
num2 = temp;
console.log(num1, num2);
① 聲明一個(gè)保存最大元素的變量 max。
② 默認(rèn)最大值可以取數(shù)組中的第一個(gè)元素。
③ 遍歷這個(gè)數(shù)組,把里面每個(gè)數(shù)組元素和 max 相比較。
④ 如果這個(gè)數(shù)組元素大于max 就把這個(gè)數(shù)組元素存到 max 里面,
否則繼續(xù)下一輪比較。
⑤ 最后輸出這個(gè) max。*/
var arrNum = [2,6,1,77,52,25,7];
var maxNum = arrNum[0]; // 用來(lái)保存最大元素,默認(rèn)最大值是數(shù)組中的第一個(gè)元素
// 從0 開(kāi)始循環(huán)數(shù)組里的每個(gè)元素
for(var i = 0;i< arrNum.length; i++){
// 如果數(shù)組里當(dāng)前循環(huán)的元素大于 maxNum,則保存這個(gè)元素和下標(biāo)
if(arrNum[i] > maxNum){
maxNum = arrNum[i]; // 保存數(shù)值到變量 maxNum
}
}
/* 刪除指定數(shù)組元素
要求:將數(shù)組[2, 0, 6, 1, 77, 0, 52, 0, 25, 7]中的 0 去掉后,形成一個(gè)不包含 0 的新數(shù)組。
分析
① 需要一個(gè)新數(shù)組用于存放篩選之后的數(shù)據(jù)。
② 遍歷原來(lái)的數(shù)組,把不是 0 的數(shù)據(jù)添加到新數(shù)組里面( 此時(shí)要注意采用數(shù)組名+索引的格式接收數(shù)據(jù))。
③ 新數(shù)組里面的個(gè)數(shù),用 length 不斷累加。*/
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newArr = []; // 空數(shù)組的默認(rèn)的長(zhǎng)度為 0
// 定義一個(gè)變量 i 用來(lái)計(jì)算新數(shù)組的索引號(hào)
for (var i = 0; i < arr.length; i++) {
// 找出大于 10 的數(shù)
if (arr[i] != 0) {
// 給新數(shù)組
// 每次存入一個(gè)值,newArr長(zhǎng)度都會(huì) +1
newArr[newArr.length] = arr[i];
}
}
console.log(newArr);
什么是函數(shù)
把一段相對(duì)獨(dú)立的具有特定功能的代碼塊封裝起來(lái),形成一個(gè)獨(dú)立實(shí)體,就是函數(shù),起個(gè)名字(函數(shù)名),在后續(xù)開(kāi)發(fā)中可以反復(fù)調(diào)用
函數(shù)的作用就是封裝一段代碼,將來(lái)可以重復(fù)使用
函數(shù)的定義
function 函數(shù)名(){
// 函數(shù)體
}
function 是聲明函數(shù)的關(guān)鍵字,必須小寫(xiě)
var fn = function() {
// 函數(shù)體
}
函數(shù)的調(diào)用
函數(shù)名();// 通過(guò)調(diào)用函數(shù)名來(lái)執(zhí)行函數(shù)體代碼
注意:聲明函數(shù)本身并不會(huì)執(zhí)行代碼,只有調(diào)用函數(shù)時(shí)才會(huì)執(zhí)行函數(shù)體代碼。
代碼示例:
// 聲明函數(shù)
function sayHi() {
console.log('吃了沒(méi)?');
}
// 調(diào)用函數(shù)
sayHi();
// 求1-100之間所有數(shù)的和
function getSum() {
var sum = 0;
for (var i = 0; i < 100; i++) {
sum += i;
}
console.log(sum);
}
// 調(diào)用
getSum();
函數(shù)的封裝
-
函數(shù)的封裝是把一個(gè)或者多個(gè)功能通過(guò)函數(shù)的方式封裝起來(lái),對(duì)外只提供一個(gè)簡(jiǎn)單的函數(shù)接口
-
簡(jiǎn)單理解:封裝類(lèi)似于將電腦配件整合組裝到機(jī)箱中 ( 類(lèi)似快遞打包)
例子:封裝計(jì)算1-100累加和
/*
計(jì)算1-100之間值的函數(shù)
*/
// 聲明函數(shù)
function getSum(){
var sumNum = 0;// 準(zhǔn)備一個(gè)變量,保存數(shù)字和
for (var i = 1; i <= 100; i++) {
sumNum += i;// 把每個(gè)數(shù)值 都累加 到變量中
}
alert(sumNum);
}
// 調(diào)用函數(shù)
getSum();
函數(shù)的參數(shù)
-
為什么要有參數(shù)
?參數(shù)的作用 : 在函數(shù)內(nèi)部某些值不能固定,我們可以通過(guò)參數(shù)在調(diào)用函數(shù)時(shí)傳遞不同的值進(jìn)去。
函數(shù)參數(shù)的運(yùn)用:
// 帶參數(shù)的函數(shù)聲明
function 函數(shù)名(形參1, 形參2 , 形參3...) { // 可以定義任意多的參數(shù),用逗號(hào)分隔
// 函數(shù)體
}
// 帶參數(shù)的函數(shù)調(diào)用
函數(shù)名(實(shí)參1, 實(shí)參2, 實(shí)參3...);
- 調(diào)用的時(shí)候?qū)崊⒅凳莻鬟f給形參的
- 形參簡(jiǎn)單理解為:不用聲明的變量
- 實(shí)參和形參的多個(gè)參數(shù)之間用逗號(hào)(,)分隔
function getSum() {
var sum = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
console.log();
}
// 雖然上面代碼可以重復(fù)調(diào)用,但是只能計(jì)算1-100之間的值
// 如果想要計(jì)算n-m之間所有數(shù)的和,應(yīng)該怎么辦呢?
// 函數(shù)內(nèi)部是一個(gè)封閉的環(huán)境,可以通過(guò)參數(shù)的方式,把外部的值傳遞給函數(shù)內(nèi)部
// 帶參數(shù)的函數(shù)聲明
function 函數(shù)名(形參1, 形參2, 形參...){
// 函數(shù)體
}
// 帶參數(shù)的函數(shù)調(diào)用
函數(shù)名(實(shí)參1, 實(shí)參2, 實(shí)參3);
-
形參和實(shí)參
- 形式參數(shù):在聲明一個(gè)函數(shù)的時(shí)候,為了函數(shù)的功能更加靈活,有些值是固定不了的,對(duì)于這些固定不了的值。我們可以給函數(shù)設(shè)置參數(shù)。這個(gè)參數(shù)沒(méi)有具體的值,僅僅起到一個(gè)占位置的作用,我們通常稱(chēng)之為形式參數(shù),也叫形參。
簡(jiǎn)單理解(函數(shù)定義時(shí)設(shè)置接收調(diào)用時(shí)傳入)
- 實(shí)際參數(shù):如果函數(shù)在聲明時(shí),設(shè)置了形參,那么在函數(shù)調(diào)用的時(shí)候就需要傳入對(duì)應(yīng)的參數(shù),我們把傳入的參數(shù)叫做實(shí)際參數(shù),也叫實(shí)參。
簡(jiǎn)單理解(函數(shù)調(diào)用時(shí)傳入小括號(hào)內(nèi)的真實(shí)數(shù)據(jù))
參數(shù) |
說(shuō)明 |
形參 |
形式_上的參數(shù)函數(shù)定義的時(shí)候傳遞的參數(shù)當(dāng)前并不知道是什么 |
實(shí)參 |
實(shí)際上的參數(shù)函數(shù)調(diào)用的時(shí)候傳遞的參數(shù)實(shí)參是傳遞給形參的 |
var x = 5, y = 6;
fn(x,y);
function fn(a, b) {
console.log(a + b);
}
//x,y實(shí)參,有具體的值。函數(shù)執(zhí)行的時(shí)候會(huì)把x,y復(fù)制一份給函數(shù)內(nèi)部的a和b,函數(shù)內(nèi)部的值是復(fù)制的新值,無(wú)法修改外部的x,y
注意:在JavaScript中,形參的默認(rèn)值是undefined。
小結(jié):
- 函數(shù)可以帶參數(shù)也可以不帶參數(shù)
- 聲明函數(shù)的時(shí)候,函數(shù)名括號(hào)里面的是形參,形參的默認(rèn)值為 undefined
- 調(diào)用函數(shù)的時(shí)候,函數(shù)名括號(hào)里面的是實(shí)參
- 多個(gè)參數(shù)中間用逗號(hào)分隔
函數(shù)的返回值
當(dāng)函數(shù)執(zhí)行完的時(shí)候,并不是所有時(shí)候都要把結(jié)果打印。我們期望函數(shù)給我一些反饋(比如計(jì)算的結(jié)果返回進(jìn)行后續(xù)的運(yùn)算),這個(gè)時(shí)候可以讓函數(shù)返回一些東西。也就是返回值。函數(shù)通過(guò)return返回一個(gè)返回值
返回值語(yǔ)法:
//聲明一個(gè)帶返回值的函數(shù)
function 函數(shù)名(形參1, 形參2, 形參...){
//函數(shù)體
return 返回值;
}
//可以通過(guò)變量來(lái)接收這個(gè)返回值
var 變量 = 函數(shù)名(實(shí)參1, 實(shí)參2, 實(shí)參3);
函數(shù)的調(diào)用結(jié)果就是返回值,因此我們可以直接對(duì)函數(shù)調(diào)用結(jié)果進(jìn)行操作。
返回值詳解:
- 在使用 return 語(yǔ)句時(shí),函數(shù)會(huì)停止執(zhí)行,并返回指定的值
-
如果函數(shù)沒(méi)有 return ,返回的值是 undefined
-
在使用 return 語(yǔ)句時(shí),函數(shù)會(huì)停止執(zhí)行,并返回指定的值
如果函數(shù)使用 return語(yǔ)句,那么跟再return后面的值,就成了函數(shù)的返回值
如果函數(shù)使用 return語(yǔ)句,但是return后面沒(méi)有任何值,那么函數(shù)的返回值也是:undefined
函數(shù)使用return語(yǔ)句后,這個(gè)函數(shù)會(huì)在執(zhí)行完 return 語(yǔ)句之后停止并立即退出,也就是說(shuō)return后面的所有其他代碼都不會(huì)再執(zhí)行。
推薦的做法是要么讓函數(shù)始終都返回一個(gè)值,要么永遠(yuǎn)都不要返回值。
break ,continue ,return 的區(qū)別
- break :結(jié)束當(dāng)前的循環(huán)體(如 for、while)
- continue :跳出本次循環(huán),繼續(xù)執(zhí)行下次循環(huán)(如 for、while)
- return :不僅可以退出循環(huán),還能夠返回 return 語(yǔ)句中的值,同時(shí)還可以結(jié)束當(dāng)前的函數(shù)體內(nèi)的代碼
arguments的使用
?當(dāng)不確定有多少個(gè)參數(shù)傳遞的時(shí)候,可以用 arguments 來(lái)獲取。JavaScript 中,arguments實(shí)際上它是當(dāng)前函數(shù)的一個(gè)內(nèi)置對(duì)象。所有函數(shù)都內(nèi)置了一個(gè) arguments 對(duì)象,arguments 對(duì)象中存儲(chǔ)了傳遞的所有實(shí)參。arguments展示形式是一個(gè)偽數(shù)組,因此可以進(jìn)行遍歷。偽數(shù)組具有以下特點(diǎn):
注意:在函數(shù)內(nèi)部使用該對(duì)象,用此對(duì)象獲取函數(shù)調(diào)用時(shí)傳的實(shí)參。
函數(shù)內(nèi)部可以調(diào)用另一個(gè)函數(shù),在同一作用域代碼中,函數(shù)名即代表封裝的操作,
使用函數(shù)名加括號(hào)即可以將封裝的操作執(zhí)行。
函數(shù)的兩種聲明方式
-
自定義函數(shù)方式(命名函數(shù))
利用函數(shù)關(guān)鍵字 function 自定義函數(shù)方式
// 聲明定義方式
function fn() {...}
// 調(diào)用
fn();
- 因?yàn)橛忻?,所以也被稱(chēng)為命名函數(shù)
- 調(diào)用函數(shù)的代碼既可以放到聲明函數(shù)的前面,也可以放在聲明函數(shù)的后面
-
函數(shù)表達(dá)式方式(匿名函數(shù))
利用函數(shù)表達(dá)式方式的寫(xiě)法如下:
// 這是函數(shù)表達(dá)式寫(xiě)法,匿名函數(shù)后面跟分號(hào)結(jié)束
var fn = function(){...};
// 調(diào)用的方式,函數(shù)調(diào)用必須寫(xiě)到函數(shù)體下面
fn();
匿名函數(shù)如何使用:
將匿名函數(shù)賦值給一個(gè)變量,這樣就可以通過(guò)變量進(jìn)行調(diào)用
匿名函數(shù)自調(diào)用
關(guān)于自執(zhí)行函數(shù)(匿名函數(shù)自調(diào)用)的作用:防止全局變量污染。
- 因?yàn)楹瘮?shù)沒(méi)有名字,所以也被稱(chēng)為匿名函數(shù)
- 這個(gè)fn 里面存儲(chǔ)的是一個(gè)函數(shù)
- 函數(shù)表達(dá)式方式原理跟聲明變量方式是一致的
- 函數(shù)調(diào)用的代碼必須寫(xiě)到函數(shù)體后面
自調(diào)用函數(shù)
匿名函數(shù)不能通過(guò)直接調(diào)用來(lái)執(zhí)行,因此可以通過(guò)匿名函數(shù)的自調(diào)用的方式來(lái)執(zhí)行
(function () {
alert(123);
})();
函數(shù)是一種數(shù)據(jù)類(lèi)型
function fn() {}
console.log(typeof fn);
因?yàn)楹瘮?shù)也是一種類(lèi)型,可以把函數(shù)作為兩一個(gè)函數(shù)的參數(shù),在兩一個(gè)函數(shù)中調(diào)用
因?yàn)楹瘮?shù)是一種類(lèi)型,所以可以把函數(shù)可以作為返回值從函數(shù)內(nèi)部返回,這種用法在后面很常見(jiàn)。
function fn(b) {
var a = 10;
return function () {
alert(a+b);
}
}
fn(15)();
調(diào)試
- 過(guò)去調(diào)試JavaScript的方式
- 斷點(diǎn)調(diào)試
斷點(diǎn)調(diào)試是指自己在程序的某一行設(shè)置一個(gè)斷點(diǎn),調(diào)試時(shí),程序運(yùn)行到這一行就會(huì)停住,然后你可以一步一步往下調(diào)試,調(diào)試過(guò)程中可以看各個(gè)變量當(dāng)前的值,出錯(cuò)的話(huà),調(diào)試到出錯(cuò)的代碼行即顯示錯(cuò)誤,停下。
瀏覽器中按F12-->sources-->找到需要調(diào)試的文件-->在程序的某一行設(shè)置斷點(diǎn)
Watch: 監(jiān)視,通過(guò)watch可以監(jiān)視變量的值的變化,非常的常用。
F10: 程序單步執(zhí)行,讓程序一行一行的執(zhí)行,
這個(gè)時(shí)候,觀(guān)察watch中變量的值的變化。
F8:跳到下一個(gè)斷點(diǎn)處,如果后面沒(méi)有斷點(diǎn)了,則程序執(zhí)行結(jié)束。
tips: 監(jiān)視變量,不要監(jiān)視表達(dá)式,因?yàn)楸O(jiān)視了表達(dá)式,那么這個(gè)表達(dá)式也會(huì)執(zhí)行。
代碼規(guī)范
標(biāo)識(shí)符命名規(guī)范
- 變量、函數(shù)的命名必須要有意義
- 變量的名稱(chēng)一般用名詞
- 函數(shù)的名稱(chēng)一般用動(dòng)詞
操作符規(guī)范
// 操作符的左右兩側(cè)各保留一個(gè)空格
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 直接退出整個(gè) for 循環(huán),跳到整個(gè)for循環(huán)下面的語(yǔ)句
}
console.log('我正在吃第' + i + '個(gè)包子呢');
}
單行注釋規(guī)范
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 單行注釋前面注意有個(gè)空格
}
console.log('我正在吃第' + i + '個(gè)包子呢');
}
其他規(guī)范
關(guān)鍵詞、操作符之間后加空格
小結(jié):
1.命名規(guī)范
2.變量規(guī)范
var name = 'zs';
3.注釋規(guī)范
// 這里是注釋
4.空格規(guī)范
5.換行規(guī)范
var arr = [1, 2, 3, 4];
if (a > b) {
}
for(var i = 0; i < 10; i++) {
}
function fn() {
}
作用域概述
通常來(lái)說(shuō),一段程序代碼中所用到的名字并不總是有效和可用的,
而限定這個(gè)名字的可用性的代碼范圍就是這個(gè)名字的作用域。
作用域的使用提高了程序邏輯的局部性,增強(qiáng)了程序的可靠性,減少了名字沖突。
JavaScript(es6前)中的作用域有兩種:
全局作用域
作用于所有代碼執(zhí)行的環(huán)境(整個(gè) script 標(biāo)簽內(nèi)部)或者一個(gè)獨(dú)立的 js 文件。
局部作用域
作用于函數(shù)內(nèi)的代碼環(huán)境,就是局部作用域。 因?yàn)楦瘮?shù)有關(guān)系,
所以也稱(chēng)為函數(shù)作用域。
JS沒(méi)有塊級(jí)作用域
-
塊作用域由 { } 包括。
-
在其他編程語(yǔ)言中(如 java、c#等),在 if 語(yǔ)句、循環(huán)語(yǔ)句中創(chuàng)建的變量,僅僅只能在本 if 語(yǔ)句、本循環(huán)語(yǔ)句中使用,如下面的Java代碼:
java有塊級(jí)作用域:
if(true){
int num = 123;
system.out.print(num); // 123
}
system.out.print(num); // 報(bào)錯(cuò)
以上java代碼會(huì)報(bào)錯(cuò),是因?yàn)榇a中 { } 即一塊作用域,其中聲明的變量 num,在 “{ }” 之外不能使用;
而與之類(lèi)似的JavaScript代碼,則不會(huì)報(bào)錯(cuò):
Js中沒(méi)有塊級(jí)作用域(在ES6之前)
if(true){
var num = 123;
console.log(123); //123
}
console.log(123); //123
小結(jié):
任何一對(duì)花括號(hào)({和})中的語(yǔ)句集都屬于一個(gè)塊,在這之中定義的所有變量在代碼塊外都是不可見(jiàn)的,我們稱(chēng)之為塊級(jí)作用域。
在es6之前沒(méi)有塊級(jí)作用域的的概念,只有函數(shù)作用域,現(xiàn)階段可以認(rèn)為JavaScript沒(méi)有塊級(jí)作用域
詞法作用域
變量的作用域是在定義時(shí)決定而不是執(zhí)行時(shí)決定,也就是說(shuō)詞法作用域取決于源碼,通過(guò)靜態(tài)分析就能確定,因此詞法作用域也叫做靜態(tài)作用域。
在 js 中詞法作用域規(guī)則:
- 函數(shù)允許訪(fǎng)問(wèn)函數(shù)外的數(shù)據(jù).
- 整個(gè)代碼結(jié)構(gòu)中只有函數(shù)可以限定作用域.
- 作用域規(guī)則首先使用提升規(guī)則分析
- 如果當(dāng)前作用規(guī)則中有名字了, 就不考慮外面的名字
變量的作用域
在JavaScript中,根據(jù)作用域的不同,變量可以分為兩種:
全局變量
在全局作用域下聲明的變量叫做全局變量(在函數(shù)外部定義的變量)。
- 全局變量在代碼的任何位置都可以使用
- 在全局作用域下 var 聲明的變量 是全局變量
- 特殊情況下,在函數(shù)內(nèi)不使用 var 聲明的變量也是全局變量(不建議使用)
局部變量
在局部作用域下聲明的變量叫做局部變量(在函數(shù)內(nèi)部定義的變量)
- 局部變量只能在該函數(shù)內(nèi)部使用
- 在函數(shù)內(nèi)部 var 聲明的變量是局部變量
- 函數(shù)的形參實(shí)際上就是局部變量
全局變量和局部變量的區(qū)別
- 全局變量:在任何一個(gè)地方都可以使用,只有在瀏覽器關(guān)閉時(shí)才會(huì)被銷(xiāo)毀,因此比較占內(nèi)存
- 局部變量:只在函數(shù)內(nèi)部使用,當(dāng)其所在的代碼塊被執(zhí)行時(shí),會(huì)被初始化;當(dāng)代碼塊運(yùn)行結(jié)束后,就會(huì)被銷(xiāo)毀,因此更節(jié)省內(nèi)存空間
作用域鏈
只要是代碼都一個(gè)作用域中,寫(xiě)在函數(shù)內(nèi)部的局部作用域,未寫(xiě)在任何函數(shù)內(nèi)部即在全局作用域中;如果函數(shù)中還有函數(shù),那么在這個(gè)作用域中就又可以誕生一個(gè)作用域;根據(jù)在[內(nèi)部函數(shù)可以訪(fǎng)問(wèn)外部函數(shù)變量]的這種機(jī)制,用鏈?zhǔn)讲檎覜Q定哪些數(shù)據(jù)能被內(nèi)部函數(shù)訪(fǎng)問(wèn),就稱(chēng)作作用域鏈
預(yù)解析的相關(guān)概念
JavaScript 代碼是由瀏覽器中的 JavaScript 解析器來(lái)執(zhí)行的。
JavaScript 解析器在運(yùn)行 JavaScript 代碼的時(shí)候分為兩步:預(yù)解析和代碼執(zhí)行。
-
預(yù)解析:在當(dāng)前作用域下, JS 代碼執(zhí)行之前,瀏覽器會(huì)默認(rèn)把帶有 var 和 function 聲明的變量在內(nèi)存中進(jìn)行提前聲明或者定義。
-
代碼執(zhí)行: 從上到下執(zhí)行JS語(yǔ)句。
預(yù)解析會(huì)把變量和函數(shù)的聲明在代碼執(zhí)行之前執(zhí)行完成。
變量預(yù)解析
預(yù)解析也叫做變量、函數(shù)提升。
變量提升(變量預(yù)解析): 變量的聲明會(huì)被提升到當(dāng)前作用域的最上面,變量的賦值不會(huì)提升。
console.log(num); // 結(jié)果是多少?
var num = 10; // ?
結(jié)果:undefined
注意:變量提升只提升聲明,不提升賦值
fn();
function fn() {
console.log('打印');
}
結(jié)果:控制臺(tái)打印字符串 --- ”打印“
注意:函數(shù)聲明代表函數(shù)整體,所以函數(shù)提升后,函數(shù)名代表整個(gè)函數(shù),
但是函數(shù)并沒(méi)有被調(diào)用!
函數(shù)表達(dá)式聲明函數(shù)問(wèn)題
函數(shù)表達(dá)式創(chuàng)建函數(shù),會(huì)執(zhí)行變量提升,此時(shí)接收函數(shù)的變量名無(wú)法正確的調(diào)用:
fn();
var fn = function() {
console.log('想不到吧');
}
結(jié)果:報(bào)錯(cuò)提示 ”fn is not a function'
解釋?zhuān)涸摱未a執(zhí)行之前,會(huì)做變量聲明提升,fn在提升之后的值是undefined;
而fn調(diào)用是在fn被賦值為函數(shù)體之前,此時(shí)fn的值是undefined
,所以無(wú)法正確調(diào)用
對(duì)象的相關(guān)概念
-
什么是對(duì)象?
在 JavaScript 中,對(duì)象是一組無(wú)序的相關(guān)屬性和方法的集合,所有的事物都是對(duì)象,例如字符串、數(shù)值、數(shù)組、函數(shù)等。
(現(xiàn)實(shí)生活中:萬(wàn)物皆對(duì)象,對(duì)象是一個(gè)具體的事物,一個(gè)具體的事物就會(huì)有行為和特征。)
對(duì)象是由屬性和方法組成的。
-
為什么需要對(duì)象?
保存一個(gè)值時(shí),可以使用變量,保存多個(gè)值(一組值)時(shí),可以使用數(shù)組。
如果要保存一個(gè)人的完整信息呢?
因此為了讓更好地存儲(chǔ)一組數(shù)據(jù),對(duì)象應(yīng)運(yùn)而生:對(duì)象中為每項(xiàng)數(shù)據(jù)設(shè)置了屬性名稱(chēng),可以訪(fǎng)問(wèn)數(shù)據(jù)更語(yǔ)義化,數(shù)據(jù)結(jié)構(gòu)清晰,表意明顯,方便開(kāi)發(fā)者使用。
JavaScript中的對(duì)象
JavaScript中的對(duì)象其實(shí)就是生活中對(duì)象的一個(gè)抽象
JavaScript的對(duì)象是無(wú)序?qū)傩缘募稀?屬性和方法
如果一個(gè)變量屬于一個(gè)對(duì)象所有,那么該變量就可以稱(chēng)之為該對(duì)象的一個(gè)屬性,
屬性一般是名詞,用來(lái)描述事物的特征
如果一個(gè)函數(shù)屬于一個(gè)對(duì)象所有,那么該函數(shù)就可以稱(chēng)之為該對(duì)象的一個(gè)方法,
方法是動(dòng)詞,描述事物的行為和功能
其屬性可以包含基本值、對(duì)象或函數(shù)。對(duì)象就是一組沒(méi)有順序的值。
我們可以把JavaScript中的對(duì)象想象成鍵值對(duì),其中值可以是數(shù)據(jù)和函數(shù)。
對(duì)象的行為和特征
特征---屬性
行為---方法
- 事物的特征在對(duì)象中用屬性來(lái)表示。
- 事物的行為在對(duì)象中用方法來(lái)表示。
創(chuàng)建對(duì)象的三種方式
-
利用字面量創(chuàng)建對(duì)象
使用對(duì)象字面量創(chuàng)建對(duì)象:
就是花括號(hào) { } 里面包含了表達(dá)這個(gè)具體事物(對(duì)象)的屬性和方法;{ } 里面采取鍵值對(duì)的形式表示
-
鍵:相當(dāng)于屬性名
-
值:相當(dāng)于屬性值,可以是任意類(lèi)型的值(數(shù)字類(lèi)型、字符串類(lèi)型、布爾類(lèi)型,函數(shù)類(lèi)型等)
代碼如下:
var star = {
name : 'pink',
age : 18,
sex : '男',
sayHi : function(){
alert('大家好啊~');
}
};
上述代碼中 star即是創(chuàng)建的對(duì)象。
-
對(duì)象的使用
-
利用 new Object 創(chuàng)建對(duì)象
-
利用構(gòu)造函數(shù)創(chuàng)建對(duì)象
-
構(gòu)造函數(shù)
-
構(gòu)造函數(shù):是一種特殊的函數(shù),主要用來(lái)初始化對(duì)象,即為對(duì)象成員變量賦初始值,它總與 new 運(yùn)算符一起使用。我們可以把對(duì)象中一些公共的屬性和方法抽取出來(lái),然后封裝到這個(gè)函數(shù)里面。
-
構(gòu)造函數(shù)的封裝格式:
function 構(gòu)造函數(shù)名(形參1,形參2,形參3) {
this.屬性名1 = 參數(shù)1;
this.屬性名2 = 參數(shù)2;
this.屬性名3 = 參數(shù)3;
this.方法名 = 函數(shù)體;
}
-
構(gòu)造函數(shù)的調(diào)用格式
var obj = new 構(gòu)造函數(shù)名(實(shí)參1,實(shí)參2,實(shí)參3)
以上代碼中,obj即接收到構(gòu)造函數(shù)創(chuàng)建出來(lái)的對(duì)象。
-
注意事項(xiàng)
- 構(gòu)造函數(shù)約定首字母大寫(xiě)。
- 函數(shù)內(nèi)的屬性和方法前面需要添加 this ,表示當(dāng)前對(duì)象的屬性和方法。
- 構(gòu)造函數(shù)中不需要 return 返回結(jié)果。
- 當(dāng)我們創(chuàng)建對(duì)象的時(shí)候,必須用 new 來(lái)調(diào)用構(gòu)造函數(shù)。
-
其他
構(gòu)造函數(shù),如 Stars(),抽象了對(duì)象的公共部分,封裝到了函數(shù)里面,它泛指某一大類(lèi)(class)
創(chuàng)建對(duì)象,如 new Stars(),特指某一個(gè),通過(guò) new 關(guān)鍵字創(chuàng)建對(duì)象的過(guò)程我們也稱(chēng)為對(duì)象實(shí)例化
new關(guān)鍵字
構(gòu)造函數(shù) ,是一種特殊的函數(shù)。主要用來(lái)在創(chuàng)建對(duì)象時(shí)初始化對(duì)象, 即為對(duì)象成員變量賦初始值,總與new運(yùn)算符一起使用在創(chuàng)建對(duì)象的語(yǔ)句中。
- 構(gòu)造函數(shù)用于創(chuàng)建一類(lèi)對(duì)象,首字母要大寫(xiě)。
- 構(gòu)造函數(shù)要和new一起使用才有意義。
new在執(zhí)行時(shí)會(huì)做四件事情
new會(huì)在內(nèi)存中創(chuàng)建一個(gè)新的空對(duì)象
new 會(huì)讓this指向這個(gè)新的對(duì)象
執(zhí)行構(gòu)造函數(shù) 目的:給這個(gè)新對(duì)象加屬性和方法
new會(huì)返回這個(gè)新對(duì)象
this詳解
JavaScript中的this指向問(wèn)題,有時(shí)候會(huì)讓人難以捉摸,隨著學(xué)習(xí)的深入,
我們可以逐漸了解
現(xiàn)在我們需要掌握函數(shù)內(nèi)部的this幾個(gè)特點(diǎn)
1. 函數(shù)在定義的時(shí)候this是不確定的,只有在調(diào)用的時(shí)候才可以確定
2. 一般函數(shù)直接執(zhí)行,內(nèi)部this指向全局window
3. 函數(shù)作為一個(gè)對(duì)象的方法,被該對(duì)象所調(diào)用,那么this指向的是該對(duì)象
4. 構(gòu)造函數(shù)中的this其實(shí)是一個(gè)隱式對(duì)象,類(lèi)似一個(gè)初始化的模型,
5. 所有方法和屬性都掛載到了這個(gè)隱式對(duì)象身上,后續(xù)通過(guò)new關(guān)鍵字來(lái)調(diào)用,
從而實(shí)現(xiàn)實(shí)例化
對(duì)象的使用
-
new關(guān)鍵字的作用
- 在構(gòu)造函數(shù)代碼開(kāi)始執(zhí)行之前,創(chuàng)建一個(gè)空對(duì)象;
- 修改this的指向,把this指向創(chuàng)建出來(lái)的空對(duì)象;
- 執(zhí)行函數(shù)的代碼
- 在函數(shù)完成之后,返回this---即創(chuàng)建出來(lái)的對(duì)象
5.3 遍歷對(duì)象
for...in 語(yǔ)句用于對(duì)數(shù)組或者對(duì)象的屬性進(jìn)行循環(huán)操作。
其語(yǔ)法如下:
for (變量 in 對(duì)象名字) {
// 在此執(zhí)行代碼
}
語(yǔ)法中的變量是自定義的,它需要符合命名規(guī)范,
通常我們會(huì)將這個(gè)變量寫(xiě)為 k 或者 key。
for (var k in obj) {
console.log(k); // 這里的 k 是屬性名
console.log(obj[k]); // 這里的 obj[k] 是屬性值
}
簡(jiǎn)單類(lèi)型和復(fù)雜類(lèi)型的區(qū)別
基本類(lèi)型又叫做值類(lèi)型,復(fù)雜類(lèi)型又叫做引用類(lèi)型
值類(lèi)型:簡(jiǎn)單數(shù)據(jù)類(lèi)型,基本數(shù)據(jù)類(lèi)型,在存儲(chǔ)時(shí),變量中存儲(chǔ)的是值本身,因此叫做值類(lèi)型。
引用類(lèi)型:復(fù)雜數(shù)據(jù)類(lèi)型,在存儲(chǔ)是,變量中存儲(chǔ)的僅僅是地址(引用),因此叫做引用數(shù)據(jù)類(lèi)型。
-
堆和棧
堆??臻g分配區(qū)別:
1、棧(操作系統(tǒng)):由操作系統(tǒng)自動(dòng)分配釋放 ,存放函數(shù)的參數(shù)值,
局部變量的值等。其操作方式類(lèi)似于數(shù)據(jù)結(jié)構(gòu)中的棧;
2、堆(操作系統(tǒng)): 存儲(chǔ)復(fù)雜類(lèi)型(對(duì)象),一般由程序員分配釋放,
若程序員不釋放,由垃圾回收機(jī)制回收,分配方式倒是類(lèi)似于鏈表。
注意:JavaScript中沒(méi)有堆和棧的概念,此處我們用堆和棧的目的方便理解
為什么會(huì)有堆內(nèi)存和棧內(nèi)存之分
首先 JavaScript 中的變量分為基本類(lèi)型和引用類(lèi)型。
基本類(lèi)型就是保存在棧內(nèi)存中的簡(jiǎn)單數(shù)據(jù)段,而引用類(lèi)型指的是那些保存在堆內(nèi)存中的對(duì)象。
1 、基本類(lèi)型
基本類(lèi)型有 Undefined、Null、Boolean、Number 和String。這些類(lèi)型在內(nèi)存中分別占有固定大小的空間,他們的值保存在??臻g,我們通過(guò)按值來(lái)訪(fǎng)問(wèn)的。
2 、引用類(lèi)型
引用類(lèi)型,值大小不固定,棧內(nèi)存中存放地址指向堆內(nèi)存中的對(duì)象。是按引用訪(fǎng)問(wèn)的。如下圖所示:棧內(nèi)存中存放的只是該對(duì)象的訪(fǎng)問(wèn)地址, 在堆內(nèi)存中為這個(gè)值分配空間 。 由于這種值的大小不固定,因此不能把它們保存到棧內(nèi)存中。但內(nèi)存地址大小的固定的,因此可以將內(nèi)存地址保存在棧內(nèi)存中。 這樣,當(dāng)查詢(xún)引用類(lèi)型的變量時(shí), 先從棧中讀取內(nèi)存地址, 然后再通過(guò)地址找到堆中的值。對(duì)于這種,我們把它叫做按引用訪(fǎng)問(wèn)。
PS:當(dāng)我們看到一個(gè)變量類(lèi)型是已知的,就分配在棧里面,比如INT,Double等。其他未知的類(lèi)型,比如自定義的類(lèi)型,因?yàn)橄到y(tǒng)不知道需要多大,所以程序自己申請(qǐng),這樣就分配在堆里面。
為什么會(huì)有棧內(nèi)存和堆內(nèi)存之分:
通常與垃圾回收機(jī)制有關(guān)。為了使程序運(yùn)行時(shí)占用的內(nèi)存最小。
當(dāng)一個(gè)方法執(zhí)行時(shí),每個(gè)方法都會(huì)建立自己的內(nèi)存棧,在這個(gè)方法內(nèi)定義的變量將會(huì)逐個(gè)放入這塊棧內(nèi)存里,隨著方法的執(zhí)行結(jié)束,這個(gè)方法的內(nèi)存棧也將自然銷(xiāo)毀了。因此,所有在方法中定義的變量都是放在棧內(nèi)存中的;
當(dāng)我們?cè)诔绦蛑袆?chuàng)建一個(gè)對(duì)象時(shí),這個(gè)對(duì)象將被保存到運(yùn)行時(shí)數(shù)據(jù)區(qū)中,以便反復(fù)利用(因?yàn)閷?duì)象的創(chuàng)建成本通常較大),這個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū)就是堆內(nèi)存。堆內(nèi)存中的對(duì)象不會(huì)隨方法的結(jié)束而銷(xiāo)毀,即使方法結(jié)束后,這個(gè)對(duì)象還可能被另一個(gè)引用變量所引用(方法的參數(shù)傳遞時(shí)很常見(jiàn)),則這個(gè)對(duì)象依然不會(huì)被銷(xiāo)毀,只有當(dāng)一個(gè)對(duì)象沒(méi)有任何引用變量引用它時(shí),系統(tǒng)的垃圾回收機(jī)制才會(huì)在核實(shí)的時(shí)候回收它。
|