javascript基礎(chǔ)

一、javascript簡介

輕量級 弱類型 腳本語言
js就是通過固定的語法來操作 瀏覽器和 頁面結(jié)構(gòu) 來實現(xiàn)網(wǎng)頁中的各種效果

1.1 javascript組成部分

  1. ECMAScript:定義了 javascript 的語法規(guī)范

  2. BOM:(browser object model)瀏覽器對象模型
    瀏覽器有一套成熟的 API 方法粪狼,通過 BOM 來操作瀏覽

  3. DOM(document objectmodel)文檔對象模型
    簡介有一套成熟的可以操作頁面元素的 API 方法退腥,通過 DOM 可以操作頁面元素

1.2 javascript書寫位置

1.2.1 行內(nèi)式 (一般不使用)

在 a 標(biāo)簽的 href 屬性中書寫代碼
javascript:js代碼;
或者在標(biāo)簽里書寫 onclick 然后書寫 JS 代碼

<!-此處的js寫法常用于a標(biāo)簽的阻止瀏覽器默認(rèn)跳轉(zhuǎn) -->
<a href="javascript:;">點一下但是不跳轉(zhuǎn)</a>

<div onclick='alert("點擊")'></div>

1.2.2 內(nèi)嵌式

js代碼書寫在 script 標(biāo)簽內(nèi)
瀏覽器打開的頁面的時候,會立即執(zhí)行script標(biāo)簽中的js代碼
script標(biāo)簽中的 type="text/javascript" 屬性可以省略
一個頁面中可以書寫多對script標(biāo)簽,但是script不能嵌套使用

<script>
  alert('內(nèi)嵌')
</script>

1.2.3 外鏈?zhǔn)?/h3>

script標(biāo)簽的src屬性中 書寫js文件的路徑地址
利于 HTML 頁面代碼結(jié)構(gòu)化再榄,把大段 JS 代碼獨立到 HTML 頁面之外狡刘,既美觀,也方便文件級別復(fù)用
引用外部 JS 文件的 srcipt 標(biāo)簽中間不可寫代碼
適用 JS 代碼量比較大的情況困鸥,開發(fā)常用

<script src="./test.js"></script>

二嗅蔬、javascript基礎(chǔ)語法

2.1 JS 注釋

在 JS 中有兩種注釋方式
注釋就是不會執(zhí)行的內(nèi)容,注釋是給程序員看的

2.1.1 單行注釋

// 編輯器快捷方式 Ctrl+/
// alert('666')

2.1.2多行注釋

/*
編輯器中默認(rèn)的是shift+Ctrl+a
alert('666')
alert('666')
alert('666')
alert('666')
*/

2.2 JS中常見的頁面輸出方式

2.2.1 彈窗輸出

alert(內(nèi)容) 提示彈窗輸出內(nèi)容

confirm(內(nèi)容) 確認(rèn)彈窗
返回值: 返回值就是 點擊確定為true 取消為false

prompt(輸入問題) 提問彈窗
返回值: 輸入啥內(nèi)容點擊確定時候返回值就是什么內(nèi)容,如果點擊取消則返回null

2.2.2 控制臺輸出

console.log(內(nèi)容) 在瀏覽器的控制臺中輸出內(nèi)容

2.2.3 頁面輸出

document.write(內(nèi)容) 在瀏覽器頁面中輸出內(nèi)容,會將內(nèi)容寫到頁面的body標(biāo)簽中
注意: 此方法會將內(nèi)容寫到body標(biāo)簽中,如果寫入的內(nèi)容有html標(biāo)簽,則頁面可以識別對應(yīng)的標(biāo)簽內(nèi)容

2.3 變量

在 js 程序中,變量是用來幫我們存儲中間值
注意: 在 js 中 一個等號表示賦值 將等號右邊的值 賦值給左邊

2.2.1 如何定義變量

定義變量:通過關(guān)鍵字 var 變量名
注意:一個變量中只能存儲一個值

var age // 表示定義了一個變量,名字為 age
var age = 100 // 表示定義了一個 age 變量并且賦值為 100

var age,username,gender // 一次定義多個變量
    age = 100 // 給已經(jīng)定義的變量賦值
    
var age = 17,username='小斌',gender='男' // 定義多個變量并賦值

// 使用定義的變量來接收 提問彈窗的返回值
var age = prompt('你多大?');
    // 在控制臺中將變量中的值輸出
    console.log( age );
    
// ! 注意 一個變量中只能存儲一個值
var age = 100 // 定義 age 變量并賦值 100
    age = 666 // 此時將 666 賦值給變量 age 中,則 age 中原來的值被覆蓋了
    console.log( age )    

2.2.2 變量名命名規(guī)則和規(guī)范

規(guī)則:死的無條件遵守疾就,服從命令為準(zhǔn)則
規(guī)范:如同道德品行澜术,盡量遵守

(1) 變量名的命名規(guī)則(必須遵守)

變量名只能由:數(shù)字 字母 下劃線 $ 組成
變量名不能以數(shù)字開頭
不能使用關(guān)鍵字和保留字為變量名
變量名不能有空格,不要使用中文
嚴(yán)格區(qū)分大小寫

(2) 變量名的規(guī)范(大家默認(rèn)遵守)

變量名盡量語義化
如果變量名由多個字母組成則盡量使用小駝峰命名(第一個單詞首字母小寫猬腰,后續(xù)單詞首字母大寫)

2.4 數(shù)據(jù)類型

基本數(shù)據(jù)類型:number string boolean undefined null
復(fù)雜數(shù)據(jù)類型(引用數(shù)據(jù)類型):object array function...(不展開講)

2.4.1 基本數(shù)據(jù)類型

(1) number 數(shù)值類型

取值: 數(shù)字 小數(shù),NaN...等等
NaN 表示這個數(shù)據(jù) 不是一個數(shù),但 NaN 是 number 數(shù)據(jù)類型

(2) string 字符串類型

取值:string
在 js 中所有使用單引號或雙引號包裹的都是字符串類型

(3) boolean 布爾類型

取值: true(真)鸟废,false(假)

(4) undefined 未定義,未賦值

取值: undefined
當(dāng)定義了一個變量,但是沒有賦值,此時變量的值就是 undefined

(5) null 空

取值: null

2.4.2 判斷數(shù)據(jù)類型

(1) 語法1: typeof 變量

// 定義了一個變量res來接收 typeof 變量 執(zhí)行的結(jié)果(返回值)
var res = typeof num
console.log( res ) // 'number'

(2) 語法2: typeof(變量)

var res = NaN
console.log( typeof res ) // 'number'

返回值: 通過字符串表示變量中數(shù)據(jù)的類型
注意: typeof 語法只能獲取基本數(shù)據(jù)類型,而且null類型獲取不到

var num = 100
var str = '小斌'
var flag = true
var und = undefined
var nul = null
console.log( typeof(num) ) // 'number 字符類型'
console.log( typeof(str) ) // 'string 字符串類型'
console.log( typeof(flag) ) // 'boolean 布爾類型'
console.log( typeof(und) ) // 'undefined 未定義類型'
console.log( typeof(nul) ) // 'object 空'

(3) 判斷一個值,是否是NaN

語法: isNaN(變量)

作用: 判斷這個變量的值,是否是一個非數(shù)字

返回值: 布爾類型
如果變量是一個數(shù),則返回 false
如果變量不是一個數(shù),則返回 true

注意: 此語法默認(rèn)會將變量中的值進行一次 隱式轉(zhuǎn)換(轉(zhuǎn)為數(shù)值)

var num = 100
console.log(isNaN(num)) // false

var num = 'xiaobin'
console.log(isNaN(num)) // true

2.4.3 數(shù)據(jù)類型的轉(zhuǎn)換(轉(zhuǎn)為數(shù)值類型)

(1) Number()

語法: Number(變量)
作用:將變量中的值轉(zhuǎn)為數(shù)值類型(無論是整數(shù)還是小數(shù)都可以轉(zhuǎn)換)
返回值: 轉(zhuǎn)換后的數(shù)字,或者NaN
注意: 將變量中的值轉(zhuǎn)為數(shù)值,只能轉(zhuǎn)數(shù)字,或小數(shù)數(shù)字

var str = '1234'
var res = Number(str)
console.log( res ) // 1234
console.log( typeof res ) // number

(2) parseInt()

語法: parseInt(變量) 將變量中的值轉(zhuǎn)為整數(shù)
返回值: 轉(zhuǎn)換后的整數(shù),或則NaN
轉(zhuǎn)換的時候,從數(shù)據(jù)的第一位開始轉(zhuǎn)換,直到遇見非數(shù)字,則停止轉(zhuǎn)換

(3) parseFloat()

語法: parseFloat(變量) 將變量轉(zhuǎn)為數(shù)值,可以轉(zhuǎn)小數(shù)
返回值: 數(shù)字,或 NaN
和parseInt一樣的轉(zhuǎn)換規(guī)則,只不過parseFolat可以識別一個小數(shù)點

(4) 隱式轉(zhuǎn)換

除了加號之外的 數(shù)學(xué)運算符(-,*,/,%) 會將變量中的值轉(zhuǎn)為數(shù)值類型,然后再運算
運算中的隱式轉(zhuǎn)換,就是在與那算之前會偷偷的將變量中的值 通過Number()方法轉(zhuǎn)為數(shù)值然后再進行運算

var num = '1000';
var res = num 0;
// 在運算之前,會隱式的將num中的值轉(zhuǎn)為數(shù)值類型,然后在運算
console.log( res ) //1000
console.log( typeof res ) // 'number'

2.4.4 數(shù)據(jù)類型的轉(zhuǎn)換(轉(zhuǎn)為字符串)

(1) String

語法: String(變量) 將變量中的值轉(zhuǎn)為字符串類型的值
返回值: 轉(zhuǎn)換后的字符串

var flag = true
console.log( String(flag) )// 'true'

(2) toString()

語法: 變量.toString() 將變量的值 轉(zhuǎn)為字符串類型 然后返回
返回值: 轉(zhuǎn)換后的字符串
注意: undefined 和 null 數(shù)據(jù)類型的變量不可以使用 toStirng 方法

(3) 加號

加號作用:1. 數(shù)學(xué)運算 2.字符串拼接

2.4.5 數(shù)據(jù)類型的轉(zhuǎn)換(轉(zhuǎn)為布爾類型)

(1) Boolean()

語法:Boolean(變量) 將變量中的值轉(zhuǎn)為布爾值然后返回
返回值: 轉(zhuǎn)換后的布爾值
在js中只有 1.空字符串 2.數(shù)值0 2.數(shù)值NaN 4.undefined 5.null 的值為false,其他別的數(shù)據(jù)轉(zhuǎn)換都是true
以后遇見任何 其他數(shù)據(jù)類型隱式轉(zhuǎn)為布爾值 都是隱式的調(diào)用了Boolean()方法類型轉(zhuǎn)換

var num1 = 0
var num2 = NaN
var str = ''
var und
var nul = null
console.log( Boolean(num1) ) // false
console.log( Boolean(num2) ) // false
console.log( Boolean(str) ) // false
console.log( Boolean(und) ) // false
console.log( Boolean(nul) ) // false

2.5 運算符

2.5.1 算術(shù)運算符

(1) 運算符

加 +
減 -
乘 *
除 /
取余(取模) %
注意:遵循先乘除后加減有括號要先算的數(shù)學(xué)運算法則

(2) + 特殊運算符

注意: 在 js 中 + 兩邊都是數(shù)值的時候,才是算術(shù)運算
如果 + 兩邊有一邊是字符串,則加號就是 字符串拼接的作用
如果 + 兩邊都是數(shù)值的之后,才進行加法運算

var res = 10 + 20
console.log( res ) // 30

var res1 = 10 + '20'
console.log( res1 ) // 1020

注意: 在js運算中,小數(shù)運算會有精度問題,在js中盡量避免小數(shù)運算
處理方式: 放大倍數(shù)的方式計算,然后縮小倍數(shù)得到結(jié)果

var res2 = (0.3*100 + 0.03*100)/100
console.log( res2 ) // 0.33

2.5.2 賦值運算符

(1) = 賦值

將等號右邊的值 賦值 給左邊的變量

var num = 100

(2) += 加等賦值

var n = 20
n += 20 // 等價于 n = n + 20
console.log( n )//40

var str = 'hello'
str += ' wolrd' // 拼接 str = str + ' wolrd'
console.log( str ) // hello wolrd

(3) -= 減等 *= 乘等 /=除等 %=取余等

var num = 100;
num -= 10; // 等價于 num = num 10
num *= 10; // 等價于 num = num * 10
num /= 10; // 等價于 num = num / 10
num %= 3; // 等價于 num = num % 3

2.5.2 比較運算符

(1) 大小比較

大于 >
小于 <
大于或者等于 >=
小于或者等于 <=

// 比較運算符,組成的表達式,返回值是布爾值
console.log(20 > 10)// true
console.log(20 < 10)// false
console.log(20 >= 20)// true
console.log(20 <= 20)// true

(2) == 等等比較

  1. 等等比較的時候,如果兩邊的數(shù)據(jù)類型不一致,則會發(fā)生隱式轉(zhuǎn)換

  2. 只會比較兩邊的值(如果兩邊的值都一樣的話則返回true)

  3. undefined和null 等等比較結(jié)果為true,其他任何數(shù)據(jù)和undefined或null比較都是false

  4. 數(shù)值NaN和任何數(shù)值比較都為false

  5. 如果是布爾值,則會先將布爾值轉(zhuǎn)為數(shù)值,然后比較
    布爾值true 轉(zhuǎn)為數(shù)值為1; 布爾值false 轉(zhuǎn)為數(shù)值為0

  6. 如果一邊是數(shù)值,則另一邊的值 隱式轉(zhuǎn)會為數(shù)值然后比較

console.log( 'leon' == 'leon' )// true
console.log( 10 == 10 ) // true
console.log( '10' == 10 ) // true
console.log( '10leon' == 10 ) // false
console.log( null == undefined ) // true
console.log( null == 0 ) // false
console.log( undefined == 0 ) // false
console.log( 1 == true ) // true
console.log( 0 == false )// true
console.log( '10leon' == true ) //  false
console.log( NaN == NaN ) //  false

(3) === 全等比較

只有兩邊的數(shù)據(jù)類型和值都相等的時候才為true

console.log( 10 === '10' ) // false
console.log( '10' === '10' ) // true

(4) != 不等比較

只有兩邊的值不相等,結(jié)果才為true

console.log( 10 != '10' ) // false
console.log( 100 != '10' ) // true

(5) !== 全不等比較

只要兩邊的數(shù)據(jù)類型和值有一個不相等,結(jié)果就是true

console.log( 10 !== '10' ) // true
console.log( '10' !== '101' ) // true
console.log( '10' !== '10' ) // false

2.5.3 邏輯運算符

(1) && 邏輯與

作為條件判斷的時候: && 符號兩邊都為true的時候,最終結(jié)果才為true,只要一邊為false,最終結(jié)果就是false

var res1 = true && true;
var res2 = true && false;
console.log( res1 )// true
console.log( res2 )// false

作為表達式的時候:
&& 符號如果左邊轉(zhuǎn)為布爾值 為false,則左邊的內(nèi)容就是表達式的結(jié)果

&& 符號如果左邊轉(zhuǎn)為布爾值 為true,則右邊的內(nèi)容就是表達式的結(jié)果

var res1 = 0 && 100;
var res2 = undefined && NaN;
var res3 = 100 && null;
var res4 = 100 && 200;
var res5 = (100 < 20) && 200;
console.log(res1) // 0
console.log(res2) // undefined
console.log(res3) // null
console.log(res4) // 200
console.log(res5) // false

(2) || 邏輯或

作為條件判斷的時候: || 符號兩邊都為false的時候,最終結(jié)果才為false,只要又一邊為true,最終結(jié)果就是true

var res1 = false || false;
var res2 = true || false;
console.log( res1 )// false
console.log( res2 )// true

作為表達式的時候:
|| 符號如果左邊轉(zhuǎn)為布爾值 為true,則左邊的內(nèi)容就是表達式的結(jié)果

|| 符號如果左邊轉(zhuǎn)為布爾值 為false,則右邊的內(nèi)容就是表達式的結(jié)果

var r1 = 1000 || 666;
var r2 = 1000 || 0;
var r3 = 0 || NaN;
var r4 = 0 || 888;
console.log(r1) // 1000
console.log(r2) // 1000
console.log(r3) // NaN
console.log(r4) // 888

(3) !變量 取反 邏輯非

返回值: 布爾值
隱式的將變量的值轉(zhuǎn)為布爾值,然后取反

console.log( !0 ) // true
console.log( !NaN )// true
console.log( !'' )// true
console.log( !undefined ) // true
console.log( !null ) // true
console.log( !'0' )// false

2.5.4 自操作運算符

(1) 自增 ++

++變量 前自增
先進行運算,然后才是別的操作

變量++ 后自增
先進行別的操作姑荷,然后才是別的運算

(2) 自減 --

--變量 前自減
先進行運算盒延,然后才是別的操作

變量 后自減
先進行別的操作,然后才是別的運算

var k = 10
var res = k++ + ++k + k++ + k--
// k = 10
// k++ + ++k + k++ + k-===> 10 + ++k + k++ + k-此時k=11
// 10 + ++k + k++ + k===> 10 + 12 + k++ + k此時k=12
// 10 + 12 + k++ + k ===> 10 + 12 + 12 + k 此時k=13
// 10 + 12 + 12 + k  ===> 10 + 12 + 12 + 13    此時k=12
// 47
console.log( res ) // 47
console.log( k )//12

2.6 分支結(jié)構(gòu)

流程控制: 代碼的執(zhí)行順序
順序結(jié)構(gòu)和分支結(jié)構(gòu)
分會結(jié)構(gòu): 條件分支 循環(huán)分支

2.6.1 條件分支

(1) if 單分支

單分支,有可能不執(zhí)行對應(yīng)的代碼
語法: if (條件) {條件為 true 執(zhí)行的代碼}

var money = 3000;
if(money < 8000){
  console.log( '上班通勤時間為2小時' )
}

(2) if-else 雙分支

雙分支,一定為執(zhí)行一個分支代碼
語法: if (條件) {條件為 true 執(zhí)行的代碼} else {條件為 false 執(zhí)行的代碼}

var age = 27;
if(age >= 18){
  console.log( '成年了' )
}else{
  console.log( '未成年' )
 }

(3) if-else if 多分支

多分支,有可能不執(zhí)行對應(yīng)的代碼
語法: if (條件1) {代碼1} else if (條件2) {代碼2} ......
條件1為true,執(zhí)行代碼1
條件1為false,條件2為true 執(zhí)行代碼2
如果前面的條件為true,則執(zhí)行對應(yīng)的代碼塊,但是不會再判斷后面的條件
判斷輸入的年份是否是普通閏年 還是世紀(jì)閏年 還是平年

var year = prompt('請輸入年份:')
if (year % 4 === 0 && year % 100 != 0) {
  console.log(year + '是普通閏年')
} else if (year % 400 === 0) {
  console.log(year + '是世紀(jì)閏年')
} else if (!(year % 4 === 0 && year % 100 != 0) && year % 400 != 0) {
  console.log( year + '是平年' )
}

(4) if-else if-...else 多分支

多分支,一定為執(zhí)行一個分支代碼
語法: if (條件1) {代碼1} else if (條件2) {代碼2} ......else {代碼n}
條件1為 true,執(zhí)行代碼1
條件1為 false,條件2為 true 執(zhí)行代碼2
如果前面的條件為 false,則執(zhí)行代碼 n
輸入一個1~7,輸出對應(yīng)是星期幾

var num = prompt('請輸入1~7的數(shù)字')
if (num == 1) {
  console.log('星期一')
} else if (num == 2) {
  console.log('星期二')
} else if (num == 3) {
  console.log('星期三')
} else if (num == 4) {
  console.log('星期四')
} else if (num == 5) {
  console.log('星期五')
} else if (num == 6) {
  console.log('星期六')
} else if (num == 7) {
  console.log('星期天')
} else {
  console.log( '請輸入1~7的數(shù)字' )
}

(5) switch-case 多分支

多分支,有可能不執(zhí)行對應(yīng)的代碼
注意: 1. 變量和 case 后面的值比較,是全等比較(需要比較數(shù)據(jù)類型和值)
注意: 2. break 關(guān)鍵值在 switch 語句中可以不寫,但是如果不寫的話,則代碼會繼續(xù)往下執(zhí)行,知道遇見break,或執(zhí)行結(jié)果,省略 break 的寫法叫做switch 穿透

switch(變量){
        case 值1:
          // 當(dāng)變量 和 值1 全等的情況執(zhí)行代碼;
          break;
        case 值2:
          // 當(dāng)變量 和 值2 全等的情況執(zhí)行代碼;
          break; // break的作用結(jié)束switch語句的執(zhí)行
            // ...
        default:
        // 當(dāng)變量和 上面的值都不相等的時候,執(zhí)行的代碼
      }
      
// 案列
var num = 11;
switch(num){
  case 10:
    console.log( '第一個case' );
    break;
  case 11:
    console.log( '第二個case' );
    // break;
    // 如果不寫這個break鼠冕,條件判斷執(zhí)行到此處添寺,switch語句不會結(jié)束,而是繼續(xù)往下執(zhí)行代碼(也不會進行判斷比較),直到遇見break才會結(jié)束
  case 12:
    console.log( '第三個case' );
    break; 
  case 13:
    console.log( '第四個case' );
    break;      
}

(6) 三元表達式

當(dāng)我們書寫雙分支的時候,可以使用三元表達式
雙分支: if(條件){代碼1}else{代碼2}
三元表達式: 條件?代碼1:代碼2
條件為true則執(zhí)行代碼1,否則執(zhí)行代碼2

// 雙分支案列
var num = 19
if (num >= 18){
  console.log( '成年了可以考駕照' );
} else {
  console.log( '未成年回家寫作業(yè)' );
}
// 使用三元表達式
var num = 17
num >= 18 ? console.log( '成年了可以考駕照' ) : console.log( '未成年回家寫作業(yè)' );
// 使用三元表達式判斷奇偶數(shù)
var n = Number(prompt('輸入一個數(shù)字判斷奇偶數(shù)'))
if (isNaN(n)) {
  console.log('請輸入一個數(shù)字')
} else {
  if (n === 0) {
    var res = '輸入的是0'
  } else {
    var res = n % 2 == 0 ? '偶數(shù)' : '奇數(shù)';
  }
  console.log(res)
}

2.6.2 循環(huán)分支

(1) while 循環(huán)

語法: while (條件) {循環(huán)代碼}
先條件判斷,如條件為 true,則執(zhí)行循環(huán)代碼
在執(zhí)行條執(zhí)行判斷,如果為 true,繼續(xù)執(zhí)行循環(huán)代碼....
直到條件判斷為 false 的時候,則循環(huán)結(jié)束
注意: 如果條件判斷一致為 true,就會形成 死循環(huán)懈费。所以一般會設(shè)置初始值,并且在循環(huán)體中改變初始值,而條件判斷也是根據(jù)變量值判斷的

// 案列1:和女朋友說 10次 對不起
// 1.設(shè)置初始值
var n = 0;
// 2.設(shè)置條件
while (n < 10){
  // 2.書寫循環(huán)體
  console.log( '對不起' )
  // 4.在循環(huán)體內(nèi), 改變值
  n++;
}
console.log( n+'循環(huán)結(jié)束' )

// 案例2:第一次彈窗的結(jié)果 str是循環(huán)的初始值
var str = prompt('你愛不愛我?(yes/no)');
while(str != 'yes'){  // 條件成立則執(zhí)行循環(huán)體
  // 循環(huán)體中代碼就是 彈出提問彈窗,并修改str的值
  str = prompt('你愛不愛我?(yes/no)')
}
// 當(dāng)輸入yes的時候循環(huán)結(jié)束
alert('我也愛你');

(2) do-while循環(huán)

執(zhí)行: 先執(zhí)行一次大括號中的循環(huán)代碼,然后條件判斷
條件判斷為true,則繼續(xù)執(zhí)行循環(huán)代碼,然后再條件判斷
條件判斷為true,則繼續(xù)執(zhí)行循環(huán)代碼,然后再條件判斷
....直到 條件判斷為false,則循環(huán)結(jié)束

特點: do-while語句 至少會執(zhí)行一次循環(huán)代碼
while循環(huán)有可能一次都不執(zhí)行循環(huán)代碼

do{
      循環(huán)代碼
    } while (條件)
    
// 需求: 和女朋友說 我錯了 5次
var n = 5;
do{
  console.log('我錯了');
  n--;
}while(n>0)

(3) for語句循環(huán)

/*
語法:
for(初始值1; 條件2; 值改變3){
    循環(huán)代碼4
}
  執(zhí)行: 1243-->243-->243-->.....繼續(xù)循環(huán)執(zhí)行,直到 條件2 判斷為false的時候,循環(huán)結(jié)束
*/

// 簡單的for循環(huán) 輸出1~5
 for (var i = 1; i <= 5; i++) {
   console.log(i)
 }
 
// for循環(huán)的變換寫法1
// 可以將for循環(huán)小括號中的初始值放到外面,但是小括號的分號不能省略
var i = 1;
for (;i<=5;i++) {
  console.log( i )
}

// for循環(huán)的變化寫法2
// 也可以將for選混中的值改變 在循環(huán)體內(nèi)書寫
var i = 1;
for (; i <= 5;) {
  console.log(i)
  i++
}

// 不要寫死循環(huán)   條件判斷一定要有
for(;;){
  console.log( 666 )
}

2.6.3 循環(huán)控制關(guān)鍵字

(1) break

// break 可以在循環(huán)中使用,表示結(jié)束循環(huán)
// 吃十個包子, 發(fā)現(xiàn)吃到第6個的時候,就飽了,就不吃了
for(var i = 1; i <= 10; i++){
  document.write('吃第' + i + '個包子<br>')
  if(i === 6){
    document.write('吃飽了')
    break// 結(jié)束循環(huán)
  }
}

(2) continue

// continue  結(jié)束本次循環(huán)代碼的執(zhí)行,直接跳到下一次的循環(huán)
// 吃十個包子, 發(fā)現(xiàn)吃到第6個的時候,第6個包子壞了,第6個包子不吃了,繼吃后面四個包子
for(var i = 1; i <= 10; i++){
  if(i === 6){
    console.log('第6個包子壞了,不吃')
    continue // 結(jié)束本次循環(huán)代碼的執(zhí)行,繼續(xù)下一次循環(huán)      
  }
  document.write('吃第' + i + '個包子<br>') 
}

(2) 循環(huán)小結(jié)

  1. while循環(huán)和for循環(huán)中的循環(huán)體,可能一次都不執(zhí)行,do-while循環(huán)至少會執(zhí)行一次循環(huán)體

  2. 如果知道循環(huán)次數(shù) 更多的時候使用 for循環(huán),如果不知道循環(huán)次數(shù),則使用while或do-while循環(huán)

  3. 循環(huán)控制關(guān)鍵字 break 和 continue 使用在循環(huán)體中的,無論是for循環(huán)還是while , do-while循環(huán)都可以使用

2.6.3 循環(huán)嵌套

循環(huán)嵌套: 循環(huán)體內(nèi) 寫循環(huán)

(1) 循環(huán)嵌套寫法

// 需要記錄多個跑圈,4個人,每人跑5圈
// 記錄一個人跑步,每跑一圈記錄一下
for (var i = 1; i <= 5; i++) {
  console.log('跑第' + i + '圈');
}
for (var j = 1; j <= 4; j++) {
  // 外層循環(huán),記錄的是第j個人的跑圈
  console.log('這是第' + j + '個人的跑圈記錄');
  for (var i = 1; i <= 5; i++) {
    // 內(nèi)層循環(huán),記錄 第j個人 跑的圈數(shù)
    console.log('這是第' + j + '個人跑第' + i + '圈');
  }
}


// 使用循環(huán)嵌套,在頁面中打印表格4*5的表格
// 奇數(shù)行和偶數(shù)行的背景顏色不一樣  
document.write('<table border="1">')
// 使用循環(huán)嵌套  輸出tr-td
for (var i = 1; i <= 4; i++) {
    // 外層循環(huán)控制輸出的行數(shù)
    if (i % 2 == 0) {
      document.write('<tr style="background:red">')
    } else {
      document.write('<tr style="background:skyblue">')
    }
    for (var j = 1; j <= 5; j++) {
      // 循環(huán)輸出td;內(nèi)層循環(huán)控制一行輸出多個td
      document.write('<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>')
    }
    document.write('</tr>')
  }

  document.write('</table>')

(1) 循環(huán)嵌套案列

// 在頁面中打印九九乘法表
/* 
  1*1=1
  2*1=1 2*2=4
  3*1=1 3*2=6 3*3=9
  4*1=1 4*2=8 4*3=12 4*4=16
  ...
  特點: 每一行輸出的等式個數(shù)  就是行數(shù)
 */
for (var i = 1; i <= 9; i++) { // i就是第幾行
  // 外層循環(huán)控制行數(shù) ,9行
  for (var j = 1; j <= i; j++) {
    // 內(nèi)層循環(huán) 控制 每一行輸出 等式 個數(shù)
    document.write(i + '*' + j + '=' + i * j+'&nbsp;&nbsp;&nbsp;');
  }
  // 通過在頁面中輸出換行標(biāo)簽來實現(xiàn) 換行    
  document.write('<br>');
}

2.7 函數(shù)

函數(shù)特點: 封裝, 復(fù)用, 即用

2.7.1 函數(shù)定義及調(diào)用

函數(shù)定義
使用關(guān)鍵字 function 來告訴瀏覽器, 要準(zhǔn)備一個 盒子
這個 盒子 要有一個名字,這個盒子的名字也就是函數(shù)的名字---函數(shù)名稱,和之前講過的變量名的命名規(guī)則和規(guī)范一樣
定義函數(shù)的過程 就是 將要執(zhí)行的代碼 放到 盒子 中的過程

(1) 聲明式定義函數(shù)

語法: function 函數(shù)名(){ 函數(shù)代碼 }
+ function 關(guān)鍵字和 函數(shù)名 之間的空格不能省略
+ 函數(shù)名后面的小闊號不能省略: 小括號中是寫 形參

聲明式定義的函數(shù),可以在定義之前或者定義之后調(diào)用該函數(shù)

賦值式定義的函數(shù),只能在定義之后調(diào)用該函數(shù)

// 聲明式定義函數(shù)
function fn() {
  console.log('這是fn函數(shù)')
}
fn() // 調(diào)用函數(shù)

(2) 賦值式定義函數(shù)----和之前講的定義變量并賦值是一樣

語法: var 變量名 = function (){ 函數(shù)代碼 }
+ 賦值給變量的是一個沒有名字的函數(shù)(匿名函數(shù))

fn(); // 報錯  ff is not a function
// 賦值式定義函數(shù)
var fn = function () {
  console.log('賦值式定義函數(shù)')
}
fn() // 調(diào)用函數(shù)
// 注意: 在js中代碼執(zhí)行報錯,會終止主程序的執(zhí)行(報錯之后的代碼不會執(zhí)行)

(3) 函數(shù)定義階段:

  1. 在內(nèi)存中開辟一個空間(創(chuàng)建了一個盒子)

  2. 將函數(shù)中的代碼一模一樣的放到這個中間中,此時不會解析函數(shù)中的變量
    (相當(dāng)于將函數(shù)中的代碼,當(dāng)做字符串一樣放到開辟的空間中)

  3. 將開辟的空間的 地址賦值給 函數(shù)名(變量)

函數(shù)調(diào)用階段:

  1. 先根據(jù) 函數(shù)名(變量)中存儲的地址,找到 函數(shù)代碼的存儲空間

  2. 將函數(shù)存儲空間中的代碼拿出來執(zhí)行,此時才會解析函數(shù)中的變量

  3. 函數(shù)調(diào)用的時候才會解析函數(shù)中的變量

2.7.2 函數(shù)的參數(shù)

(1) 形參:

在函數(shù)定義的時候 寫到小括號中的變量----形式參數(shù)
形參 也是 在函數(shù)中使用的變量
如果有多個形參,使用逗號分隔
形參個數(shù) 比 函數(shù)調(diào)用時候的實參要多這個形參的值就是undefined(相當(dāng)于在函數(shù)內(nèi)部定義了一個變量,但是調(diào)用的時候沒有賦值)

(2) 實參:

在函數(shù)調(diào)用的時候,寫在小括號中的具體的數(shù)據(jù),如果有多個也是用逗號分隔
實參 就是 在函數(shù)調(diào)用的時候,給對應(yīng)的形參賦的值
實參沒有賦值給對應(yīng)的形參,則在函數(shù)內(nèi)部不能通過形參得到這個實參的值

// 形參n 在函數(shù)內(nèi)使用的變量
function fn(n, m, x, y) { 
  console.log(n, m, x, y)
}
// 函數(shù)調(diào)用,100就是實參
fn(100, 200); // 100 200 undefined undefined

(3) arguments 關(guān)鍵字

function ff(n1, n2) {
  // 1. arguments 會接收所有函數(shù)調(diào)用傳遞的實參
  console.log(arguments)
 
  // 2. 在函數(shù)內(nèi)部,可以通過 arguments[下標(biāo)] 獲取對應(yīng)的實參
  console.log(arguments[0])
  console.log(arguments[1])
  console.log(arguments[2])
 
  // 3. 可以通過arguments.length 獲取實參的個數(shù)
  console.log(arguments.length)
}
// ff(10,20,30,40,50);
ff(10, 20, 30, 40, 50, 60);

2.7.3 函數(shù)的返回值

(1) 函數(shù)內(nèi)的關(guān)鍵字 return

  1. return 會終止函數(shù)內(nèi)代碼的執(zhí)行(return 關(guān)鍵字,下一行的代碼不會執(zhí)行)
  2. return 可以給函數(shù)創(chuàng)造一個返回值
    return 關(guān)鍵字后面跟的是什么內(nèi)容,函數(shù)調(diào)用返回的結(jié)果就是什么
    注意: return 關(guān)鍵字后如果什么都沒寫,則函數(shù)的返回值就是 undefined
    如果函數(shù)內(nèi)沒有return,則函數(shù)調(diào)用的返回值也是undefined
// return 會終止函數(shù)的執(zhí)行
function ff() {
  console.log( 1 )
  console.log( 2 )
  return;  // 函數(shù)內(nèi)的代碼執(zhí)行到此處的時候,后面的代碼就不會執(zhí)行了
  console.log( 3 )
  console.log( 4 )
}
ff();

// return 返回的值
function fn(n) {
    var i = n + 10
    return i// 返回值return
}
// 函數(shù)調(diào)用也是一個表達式,執(zhí)行后會有結(jié)果
// 將函數(shù)調(diào)用的結(jié)果 賦值給變量res
var res = fn(10); 
console.log(res) // 將 res 的值輸出 i 的值 20

(2) 函數(shù)練習(xí)

// 編寫一個函數(shù),計算兩個數(shù)值的和,差,積,商  并返回, 要求:使用傳參的方式
function getRes(n1, n2, opt) {
  // 校驗傳入的是n1,n2的值,是否是數(shù)值
  if (isNaN(n1) || isNaN(n2)) {
    alert('請輸入數(shù)字');
    return '輸入數(shù)字有誤'; // 終止函數(shù)代碼的執(zhí)行
  }
  var result; // 結(jié)果計算的結(jié)果
  // 使用switch-case多分支判斷,輸入的運算符,計算結(jié)果
  switch (opt) {
    case '+': result = n1 + n2; break;
    case '-': result = n1 n2; break;
    case '*': result = n1 * n2; break;
    case '/': result = n1 / n2; break;    
    default: 
      alert('請輸入正確的運算符');
      return '輸入的運算符有誤';
  }
  return result;
}
var a = parseInt(prompt('輸入第一個數(shù)字'))
var b = parseInt(prompt('輸入第二個數(shù)字'))
var f = prompt('請輸入計算方式:+,-,*,/')
// 函數(shù)調(diào)用
var res = getRes(a, b, f);
console.log(res)

2.7.4 函數(shù)的預(yù)解析

預(yù)解析: 在瀏覽器解析js代碼之前,會解析的內(nèi)容

(1) 預(yù)解析的內(nèi)容

  1. var 關(guān)鍵字定義的變量
    變量提升: 在瀏覽器解析js中的代碼之前,會將var 聲明的變量提升(提升到代碼的最前面)

  2. 聲明式定義函數(shù)
    函數(shù)提升: 在瀏覽器解析js代碼之前,會將 聲明式定義的函數(shù)提升到代碼的最前面
    注意: 函數(shù)調(diào)用,執(zhí)行函數(shù)內(nèi)部代碼之前,也會在函數(shù)內(nèi)部進行預(yù)解析,但是變量和函數(shù),只會提升到函數(shù)內(nèi)的最前面

(2) 預(yù)解析分析

console.log( num ); // undefined
var num = 100;
console.log( num ); // 100
/* 
  預(yù)解析分析:
    代碼執(zhí)行之前,只要發(fā)現(xiàn)代碼中有var 申明變量,會將var 聲明變量提升到最前面
    var num;
    console.log( num ) // undefined,聲明變量沒有賦值,變量就是undefined
    num = 100
    console.log( num ) // 100    
*/

/******************************************/
fn();
function fn() {
  console.log('fn')
}
fn();
/* 
  預(yù)解析分析:
    在代碼執(zhí)行之前,會將聲明式定義的函數(shù)提升到最前面
    function fn() {
      console.log( 'fn' )
    }
    fn();
    fn();
 */
 
 /**************************************************/
  fn();
  var fn = function () {
    console.log('fn')
  }
  fn();
  /* 
    預(yù)解析分析:
      代碼執(zhí)行之前,發(fā)現(xiàn)有var 聲明變量,會將變量聲明提升到最前面
      var fn;
      fn(); // 此時變量fn中的值undefined,所以此處函數(shù)調(diào)用報錯
      fn = function () {
        console.log('fn')
      }
      fn();
   */

  /**************************************************/
  function fn() {
    console.log(num)
    var num = 100;
    console.log(num)
  }
  fn();
  /* 
    預(yù)解析分析:
      fn函數(shù)調(diào)用,fn函數(shù)內(nèi)部代碼預(yù)解析
        function fn(){
          // 預(yù)解析
          var num;
          console.log(num) // undefined
          num = 100;
          console.log(num)// 100
        }
   */

(3) 預(yù)解析小結(jié):

  1. 只有var 聲明變量和聲明式定義的函數(shù)才會預(yù)解析
  2. 賦值式定義的函數(shù)不會函數(shù)提升預(yù)解析,只有可能會變量提升預(yù)解析
  3. 函數(shù)調(diào)動的時候,函數(shù)內(nèi)也會預(yù)解析,但是會先進行形參賦值,然后預(yù)解析
  4. 函數(shù)內(nèi)的return 不會影響函數(shù)內(nèi)的預(yù)解析
  5. 分支結(jié)構(gòu)中的條件和大括號也不會影響預(yù)解析(變量提升)

2.7.5 作用域

作用域: 就是變量的使用范圍
作用域分為全局作用域和局部作用域(私有作用域)

(1) 全局作用域: 一個頁面就是一個全局作用域

全局作用域中定義的變量,在全局中都可以使用
全局作用域的生命周期: 從頁面打開到頁面關(guān)閉

// 全局中定義的變量在全局中都能使用
var num =100;
function fn() {
  console.log( num );
}
fn();
console.log( num )

(2) 局部作用域:

也叫做私有作用域,在js中只有函數(shù)的大括號才能確定一個局部作用域(if和for的大括號不行)
在局部作用域中定義的變量,只能在這個局部作用域中使用,在別的地方不能使用

// 局部作用域
function ff() {
  // 此處就是ff的局部作用域
}
function ff2() {
  // 此處就是ff2的局部作用域
}

(3) 作用域中的反問規(guī)則

  • 變量的方式就是獲取這個變量的值

常見訪問變量值的方式:

  1. 輸出變量,
  2. 變量參與運算,
  3. 在函數(shù)中返回變量的值,
  4. 將變量當(dāng)中的值賦值給別的變量
  5. 函數(shù)調(diào)用變量作為實參
    ...
  • 會先在當(dāng)前自己作用域中查找,是否有定義這個變量,如果有則拿來使用
  • 如果當(dāng)前作用域中沒有這個變量,則去上一級作用域中查找,找到了則使用
  • 如果找不到,則再繼續(xù)去上一級作用域中查找這個變量,找到了則使用
  • 如果還是找不到,則再繼續(xù)去上一級作用域中查找這個變量,找到了則使用
  • 一直往上的作用域中查找,直到全局作用域查找,找到則使用
  • 如果在全局作用有中還是找到不到,則報錯(變量 is not defined)
  • 注意: 變量的訪問,找不到的時候只會去上一級作用域查找,不會往下的作用域中查找
function fn() {
  // fn的局部作用域
  var num = 200;
  function ff() {
    // ff局部作用域
    // console.log(username) // 報錯 
    // 當(dāng)前作用域沒有username,則去上一級fn作用域中查找,沒有找到,則繼續(xù)去上一級作用域全局中查找,沒有找到則報錯  username is not defined 
    function f1() {
      // f1的局部作用域
      var username = 'leon';
      // num變量運算和num變量賦值都是屬于 num變量訪問
      console.log(num + 100) // 300
      var n = num
    }
    f1();
  }
  ff();
}
fn();
// f1作用域的上一級是ff作用域
// ff作用域的上一級是fn作用域
// fn作用域的上一級是全局作用域

(4) 作用域中變量的賦值規(guī)則:

  • 當(dāng)作用域中有 給變量賦值的時候,
  • 會現(xiàn)在當(dāng)前作用域中找,是否有聲明這個變量,如果有聲明則賦值
  • 如果沒有,則去上一級作用域中查找,在上一級作用域中是否有聲明這個變量,如果有則賦值
  • 如果還是沒有,則繼續(xù)往上一級作用域中找,如果還是沒有,則繼續(xù)往上的作用域中找
  • 如果直到全局作用域找,還是沒有找到,則會將這個變量定義為 全局變量 ,并且賦值
  • 這中定義的變量 我們稱之為 隱式全局變量
function fn() {
  function ff() {
    var num = 200;
    function f1() {
      num = 100;
    }
    f1()
    // f1函數(shù)調(diào)用 執(zhí)行給變量num賦值, 在f1作用域中沒有聲明變量num,則去上一級作用域中找 是否有聲明變量num
    // ff作用域中 有聲明變量num, 則將100賦值給ff作用域中的num變量,f1函數(shù)執(zhí)行結(jié)束
    console.log( num )//100  此處代碼執(zhí)行的時候,num變量中的值 已經(jīng)是100了
  }
  ff();
}
fn();

(5) 作用域鏈

作用域鏈: 在變量的訪問和賦值的時候,先當(dāng)前作用域往上一級作用域,一直到到全局作用域,這樣形成的一個鏈?zhǔn)椒Q之為作用域鏈
作用域鏈的作用: 就是讓js代碼在執(zhí)行的時候,變量的訪問和賦值是有序的

2.7.6 事件

事件就是用戶在頁面的動作行為, 比如:鼠標(biāo)點擊,鼠標(biāo)移動,鍵盤按下等等

在js中可以通過頁面標(biāo)簽的id屬性值,直接獲取到頁面元素
console.log( box )

事件組成三要素:

  1. 事件源: 綁定事件的頁面元素
  2. 事件類型: 觸發(fā)的什么事件(鼠標(biāo)事件,鍵盤事件,表單事件....)
  3. 事件處理程序(函數(shù)): 事件觸發(fā)后要執(zhí)行的函數(shù)

1. 鼠標(biāo)事件

  • click 鼠標(biāo)左鍵單擊事件
  • dblclick 鼠標(biāo)左鍵雙擊事件
  • mouseover 鼠標(biāo)移入事件
  • mouseout 鼠標(biāo)移出事件
  • mousemove 鼠標(biāo)移動事件

2. 鍵盤事件

  • keydown 鍵盤按下事件(鍵盤按下不松開則會一直觸發(fā)此事件)
  • keyup 鍵盤彈起事件(鍵盤按下松開,只會觸發(fā)一次keyup)
  • 一般鍵盤事件綁定給頁面,js中docuemnt表示瀏覽器文本,文檔包含瀏覽器中整個顯示頁面

3. 表單事件

  • blur 表單輸入框的失去焦點(光標(biāo))事件
  • focus 表單輸入框的獲取焦點(光標(biāo))事件
  • input 表單輸入框的輸入事件

4. 瀏覽器事件

  • load 瀏覽器頁面加載事件(一般給綁定給window)
  • scroll 瀏覽器滾動事件

語法: 頁面元素.on+事件類型 = 函數(shù)

// box就是事件源
// click就是事件類型(click 是鼠標(biāo)左鍵單擊事件)
box.onclick = function () {
   console.log(666);
}
/* 
  此處我們可以理解為: 定義了一個匿名函數(shù),并且賦值給了box元素的點擊事件
  當(dāng)鼠標(biāo)點擊box元素的時候,就會觸發(fā)box的點擊事件,并執(zhí)行對應(yīng)的事件處理函數(shù)
*/

2.7.7 對象

對象: 是 js 中的一種數(shù)據(jù)類型,是復(fù)雜數(shù)據(jù)類型
對象是一個數(shù)據(jù)的集合,無序數(shù)據(jù)集合
對象也叫做 鍵值對集合, 對象可以存儲數(shù)據(jù), 對象存儲數(shù)據(jù)的形式----鍵值對形式存儲

(1) 對象語法

(1) 對象

語法:{}表示一個空對象

var o = {};
console.log( o )

(2) 有數(shù)據(jù)的對象

語法:{鍵名:鍵值,鍵名:鍵值,鍵名:鍵值....}

var per = {
  name: 'zs',
  name: 'lisi', // 對象中的鍵名唯一的不能重復(fù),所有后面的會將前面的覆蓋
  'age': 17,
  'flag': true,
  eat:function(){
    console.log( '西紅柿炒番茄' )
  }
}
console.log(per)

對象中的鍵名: 也叫做對象的屬性名,屬性名必須是字符串?dāng)?shù)據(jù)類型,屬性名可以可以加引號,也可以不加引號書寫,對象中屬性名是唯一的(不能重復(fù))
對象中的鍵值: 可以是任意數(shù)據(jù)類型的值 一組鍵值對組成了對象中的一個數(shù)據(jù)成員 對象中如果有多個數(shù)據(jù)成員(鍵值對),則使用逗號分隔

(2) 創(chuàng)建對象

1. 字面量創(chuàng)建對象

語法: 變量 = 對象

// 1. 字面量創(chuàng)建
// 字面量就是直接賦值的形式
var obj = {name:'zs',age:10};
console.log( obj )

2. 使用內(nèi)置構(gòu)造函數(shù)創(chuàng)建對象

Object是內(nèi)置的構(gòu)造函數(shù),通過new 的方式調(diào)用該函數(shù),可以創(chuàng)建對象
語法: 變量 = new Object()

// 2. 使用內(nèi)置構(gòu)造函數(shù)創(chuàng)建對象
var obj = new Object();
console.log( obj ) // 空對象

(3) 操作對象的成員:

  1. 添加對象成員
  • 點語法: 對象.屬性名 = 值
  • 數(shù)組關(guān)聯(lián)法: 對象['屬性名'] = 值
    • 使用數(shù)組關(guān)聯(lián)法,中括號里面的屬性名必須加引號
  1. 修改對象對應(yīng)的成員的值
  • 點語法: 對象.屬性名 = 值
  • 數(shù)組關(guān)聯(lián)法: 對象['屬性名'] = 值
  1. 訪問對象成
  • 點語法: 對象.屬性名
  • 數(shù)組關(guān)聯(lián)法: 對象['屬性名']
  1. 刪除對象成員
  • 點語法: delete 對象.屬性名
  • 數(shù)組關(guān)聯(lián)法: delete 對象['屬性名']
// 點語法操作
var obj = new Object();
// 添加
obj.name = 'zs';
obj.age = 17;
// 修改
obj.name = 'lisi'
// 刪除
delete obj.age;
// 訪問
console.log( obj.name ) // 'lisi'
// 訪問對象成員的時候,如果沒有這個屬性名,則值為undefined
console.log( obj.abcd ) // undefined
console.log( obj ) // {name: 'lisi'}

// 數(shù)組關(guān)聯(lián)法
var per = {};  
// 添加
per['name'] = 'zs';
per['age'] = 20;
// 修改
per['name'] = 'lisi';
// 刪除
delete per['age']
// 訪問
console.log( per['name'] ) // lisi
console.log( per['xyz'] ) // undefined  對象沒有xyz這個屬性名
console.log( per ) // {name: 'lisi'}

三计露、javascript數(shù)據(jù)操作

3.1 遞歸函數(shù)

在函數(shù)內(nèi)部調(diào)用函數(shù)本身

// 使用遞歸函數(shù),計算1+2+3+4+5的和
function ff(n) {
  // 結(jié)束條件
  if(n===1){
    return 1;
  }
  return n + ff(n - 1)
}
var res = ff(5);
console.log( res ) // 15

// 斐波那契數(shù)列
// 該數(shù)列的特點: 第一個和第二個的數(shù)值是1,從第三個開始,每一個數(shù)的值是前兩個數(shù)的和
// 1 1 2 3 5 8 13 21 34 55..
// 請使用遞歸函數(shù) 求第10個斐波那契數(shù)列的值
function getFeiBo(n) {
  // 結(jié)束條件,第一個和第二個的數(shù)值是1
  if (n === 1 || n === 2) {
    return 1
  }
  return getFeiBo(n - 1) + getFeiBo(n - 2)
}
console.log( getFeiBo(10) ) // 55

3.2 數(shù)組

數(shù)據(jù)類型: 基本數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型
基本數(shù)據(jù)類型: string boolean number undefined null
復(fù)雜數(shù)據(jù)類型: object array
數(shù)組 是js的復(fù)雜數(shù)據(jù)類型
數(shù)組就是一組有序的數(shù)據(jù)集合
因為數(shù)組中的每一個成員都有一個索引,這個索引就是成員在數(shù)組中的排序

數(shù)組: 使用中括號包裹,多個成員之間通過逗號分隔,數(shù)組中的數(shù)據(jù)成員可以是任意數(shù)據(jù)類型
數(shù)組的兩種創(chuàng)建方式

3.2.1 字面量創(chuàng)建數(shù)組

語法:var arr = []

//  1. 字面量創(chuàng)建數(shù)組
var arr = [];
console.log( arr ) // 空數(shù)組 沒有任何數(shù)據(jù)的數(shù)組
var arr1 = [1,2,3,4,'a','b','c',true,undefined,{}]
console.log( arr1 ) // [1, 2, 3, 4, 'a', 'b', 'c', true, undefined, {…}]

3.2.2 內(nèi)置構(gòu)造函數(shù)創(chuàng)建數(shù)組

  • var arr = new Array() // 得到一個空數(shù)組
  • var arr = new Array(一個數(shù)字) // 傳入的數(shù)字必須是大于0的整數(shù),得到一個有成員的數(shù)組,但是每一個成員的內(nèi)容都是(empty)
  • var arr = new Array(多個參數(shù)) // 多個參數(shù)可以是任意數(shù)據(jù)類型,得到一個有成員的數(shù)組,而且傳入的參數(shù)就是數(shù)組成員
// 2. 通過內(nèi)置構(gòu)造函數(shù)創(chuàng)建數(shù)組
var arr = new Array();
console.log( arr ) // []
var arr = new Array(5); 
console.log( arr ) // [empty × 5]
var arr = new Array('a','b',1,2);
console.log( arr ) // ['a', 'b', 1, 2]
var arr = new Array('10');
console.log( arr ) // ['10']

3.2.3 數(shù)組的長度和索引

(1) 數(shù)組長度

  • 數(shù)組中的數(shù)組,我們也叫做數(shù)組的成員
  • 數(shù)組成員的個數(shù) 就是數(shù)組的長度
  • 數(shù)組長度獲取
    • 數(shù)組.length
    • 返回數(shù)組成員的個數(shù)

(2) 數(shù)組的索引

  • 數(shù)組的每一個成員都有一個索引,表示成員在數(shù)組中序號
  • 數(shù)組的索引永遠(yuǎn)都是從0開始的連續(xù)自然數(shù)
  • 可以通過數(shù)組的索引,獲取修改數(shù)組對應(yīng)的成員數(shù)據(jù)
    • 語法: 數(shù)組[索引] // 獲取

(3) 數(shù)組索引和數(shù)組長度的關(guān)系

  • 數(shù)組索引的最大值 就是 數(shù)組長度減1
  • 數(shù)組長度 就是數(shù)組索引最大值加1

(4) 添加數(shù)組成員

  • 語法: 數(shù)組[索引] = 值
  • 注意: 如果數(shù)組中對應(yīng)的索引有值了,通過這個方式只能修改數(shù)組中索引對應(yīng)的值

(5) 數(shù)組的長度是可變的(可修改)

  • 隨著數(shù)組成員數(shù)的編,數(shù)組的長度也會變化
  • 而知可以通過改變數(shù)組的長度,修改數(shù)組成員個數(shù)
  • 注意: 因為數(shù)組的索引是連續(xù)的自然數(shù),如果跳過數(shù)組索引最大值添加成員,則長度以 最新的數(shù)組最大索引加1 為準(zhǔn)

(6) 遍歷數(shù)組: 循環(huán)的獲取數(shù)組中的每一個成員

// for循環(huán)來遍歷數(shù)組
for(var i = 0;i<數(shù)組.lengthl;i++){ // i 就是數(shù)組的索引
   數(shù)組[i]
}
var arr = ['a','b','c','d'];
console.log( arr.length ) // 4
console.log( arr ) // ['a','b','c','d']
console.log( arr[0] ) // ['a']
arr[3] = 4; // 修改
console.log( arr ) [4]
arr[4] = 'e'; // 添加
console.log( arr ) // ['a','b','c','d','e']

// 數(shù)組長度
var arr = ['a', 'b', 'c', 'd'];
// 直接修改數(shù)組長度 改變數(shù)組個數(shù)
arr.length = 2 
console.log(arr) // ["a", "b"]
arr.length = 0;
console.log(arr) // [] 

// 通過索引 添加數(shù)組成員,數(shù)組長度變化
arr[6] = 'f'; 
console.log(arr) // ['a', 'b', 'c', 'd', empty × 2, 'f']
console.log( arr.length ) // 7

// for 循環(huán)遍歷數(shù)組
var arr = ['a', 'b', 'c', 'd'];
// 利用了數(shù)組索引和數(shù)組長度的關(guān)系特點 使用for循環(huán)遍歷
// 數(shù)組的索引最大值 為 數(shù)組長度減1
for (var i = 0; i < arr.length; i++) {
  // i 就是數(shù)組的索引
  console.log( arr[i] ) // a b c d
}

3.2.4 數(shù)組常用方法

語法: 數(shù)組.數(shù)組方法()

數(shù)組方法 作用
push() 可以接收任意數(shù)量的參數(shù),把它們逐個添加到數(shù)組末尾憎乙,并返回修改后數(shù)組的長度薄坏。
pop() 從數(shù)組末尾移除最后一項,減少數(shù)組的length值寨闹,然后返回移除的項。
unshift() 方法能夠在數(shù)組前面添加任意個項并返回新數(shù)組的長度君账。
shift() 方法能夠移除數(shù)組中的第一個項并返回該項繁堡,同時將數(shù)組長度減 1。
reverse() 方法會反轉(zhuǎn)數(shù)組項的順序。
sort() 方法按字母表升序排列數(shù)組項椭蹄。
concat() 方法可以基于當(dāng)前數(shù)組中的所有項創(chuàng)建一個新數(shù)組闻牡,參數(shù)可以是數(shù)組項或者數(shù)組。
slice() 方法它能夠基于當(dāng)前數(shù)組中的一或多個項創(chuàng)建一個新數(shù)組绳矩≌秩螅可以接受一或兩個參數(shù)。
splice() 方法翼馆,對數(shù)組進行刪除割以、插入、替換应媚,是最強大的數(shù)組方法严沥,返回值是數(shù)組,改變原數(shù)組中姜。
join() 方法消玄,將數(shù)組轉(zhuǎn)換成對應(yīng)的字符串。參數(shù)就是連接符丢胚。
indexOf 根據(jù)傳入的參數(shù),去數(shù)組中從前往后查找,如果找到一樣的則返回索引,并停止查找翩瓜,如果數(shù)組中沒有一樣的元素, 則返回-1
// 1. pop()
// 語法: 數(shù)組.pop();
// 作用: 刪除數(shù)組的最后一個成員
// 返回值: 被刪除的數(shù)組成員
// 會改變原數(shù)組
var arr = ['a', 'b', 'c'];
var res = arr.pop();
console.log(res) // 'c' 刪除的元素作為返回值
console.log(arr) // ["a", "b"]

/***************************************/
// 2. unshift()
// 語法: 數(shù)組.unshift(參數(shù));
// 作用: 將參數(shù)作為數(shù)組的成員,添加到數(shù)組里面的最前面
// 返回值: 返回添加之后的數(shù)組長度
// 會改變原數(shù)組
var arr = ['a', 'b', 'c'];
var res = arr.unshift(1);
console.log(res) // 4
console.log(arr) // [1, "a", "b", "c"]

/***************************************/
// 3. splice
// 語法1: 數(shù)組.spice(起始索引,刪除幾個元素)
// 作用: 從指定的索引開始刪除數(shù)組元素
//  如果沒有傳入刪除的個數(shù),則默認(rèn)從起始索引開始刪除元素一直到最后一個元素
// 返回值: 以數(shù)組的形式返回刪除的元素
// 會改變原數(shù)組
var arr = ['a', 'b', 'c', 'd', 'e'];
var resArr = arr.splice(2, 2);
console.log( '返回值:',resArr ) // ["c", "d"]
console.log( '原數(shù)組:',arr ) // ["a", "b", "e"]

// 語法2: 數(shù)組.spice(起始索引,刪除幾個元素,將這個東西替換刪除的內(nèi)容...)
// 作用: 從指定的索引開始刪除數(shù)組元素,并替換為傳入的內(nèi)容
// 返回值: 以數(shù)組的形式返回刪除的元素
var arr = ['a', 'b', 'c', 'd', 'e'];
var resArr = arr.splice(2, 2, 1, 2);
console.log('返回值:', resArr) // ["c", "d"]
console.log('原數(shù)組:', arr) // ["a", "b", 1, 2, "e"]

/**********************************************************/
// 4. sort
// 語法1: 數(shù)組.sort()
// 作用: 按照數(shù)組的元素的逐位數(shù)值排序
// 返回值: 排序后的數(shù)組
// 會改變原數(shù)組 
var arr = [11,31,4,2];
var resArr = arr.sort();
console.log('返回值:', resArr) // [11, 2, 31, 4]
console.log('原數(shù)組:', arr) // [11, 2, 31, 4]
// 語法2: 數(shù)組.sort(參數(shù))
//  參數(shù)必須是一個函數(shù),函數(shù)要有兩個形參 函數(shù)內(nèi)返回兩個形參的差值
// 作用: 按照數(shù)組的元素的數(shù)值排序
// 返回值: 排序后的數(shù)組
// 會改變原數(shù)組 
var arr = [11, 31, 4, 2];
var resArr = arr.sort(function (a, b) {
  return a - b
});
console.log('返回值:', resArr) // [2, 4, 11, 31]
console.log('原數(shù)組:', arr) // [2, 4, 11, 31]
  
var arr = [11, 31, 4, 2];
var resArr = arr.sort(function (a, b) {
  return b - a
});
console.log('返回值:', resArr) // [31, 11, 4, 2]
console.log('原數(shù)組:', arr) // [31, 11, 4, 2]

3.2.5 遍歷對象

因為數(shù)組是有序(索引)的數(shù)據(jù)集合
所以很容易使用for循環(huán)遍歷數(shù)組
但是對象是一個無序的數(shù)據(jù)(鍵值對)集合
使用for循環(huán)則無法遍歷對象,需要使用for-in語法遍歷

// for-in語法:
// 對象有多少個成員就會循環(huán)多少次
for(var 變量 in 對象){
  // 變量就是對象的鍵名
}

var obj = {
  name: 'xiaobin',
  age: 18,
  yyds: '牛逼'
}
for (var key in obj) {
  // key就是對象的所有鍵名
  // console.log(key)
  // 此處的key是變量,通過對象獲取鍵值,不能使用點語法
  console.log(key, obj[key])
}

3.2.6 二維數(shù)組

數(shù)組中存儲數(shù)組,我們把大數(shù)組稱之為多維數(shù)組
如果數(shù)組外面只嵌套了一層數(shù)組,那么就是二維數(shù)組

// 二維數(shù)組
var friends = [ // 模擬qq分組數(shù)據(jù)
  ['zs1','lisi1','ww1'],  // 好友
  ['zs2','lisi2','ww2'],  // 黑名單
  ['zs3','lisi3','ww3'],  // 陌生人
]
// 獲取二維數(shù)組中所有的數(shù)據(jù)
console.log( friends[0][0] )
console.log( friends[0][1] )
console.log( friends[0][2] )
console.log( '--------------' )
console.log( friends[1][0] )
console.log( friends[1][1] )
console.log( friends[1][2] )
console.log( '--------------' )
console.log( friends[2][0] )
console.log( friends[2][1] )
console.log( friends[2][2] )

/********************************************/
var friends = [ // 模擬qq分組數(shù)據(jù)
  ['zs1', 'lisi1', 'ww1'], // 好友
  ['zs2', 'lisi2', 'ww2'], // 黑名單
  ['zs3', 'lisi3', 'ww3'], // 陌生人
]
// 使用循環(huán)遍歷二維數(shù)組
for (var i = 0; i < friends.length; i++) {
  // 外層循環(huán) 大數(shù)組中的小數(shù)組
  console.log(friends[i])
  // console.log( '------' )
  for (var j = 0; j < friends[i].length; j++) {
    // 內(nèi)層循環(huán)遍歷小數(shù)組的每一個數(shù)據(jù)
    console.log(friends[i][j])
    // i表示小數(shù)組在大數(shù)組中的索引,j表示具體數(shù)據(jù)在小數(shù)組中的索引
  }
}

3.3 數(shù)據(jù)類型

3.3.1 數(shù)據(jù)類型的存儲區(qū)別

存儲內(nèi)存分為:

  1. 棧內(nèi)存
  2. 堆內(nèi)存

js 中的數(shù)據(jù)類型 分為基本數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型(引用數(shù)據(jù)類型)
基本數(shù)據(jù)類型的數(shù)據(jù) 存儲在棧內(nèi)存 中 棧內(nèi)存中的標(biāo)識對應(yīng)的變量
復(fù)雜數(shù)據(jù)類型數(shù)據(jù)存儲在 堆內(nèi)存 中 而地址存儲在棧內(nèi)存中

小結(jié): 給變量賦值一個基本數(shù)據(jù)類型,則在這個變量的 棧內(nèi)存 中直接存儲數(shù)據(jù)
給變量賦值一個復(fù)雜數(shù)據(jù)類型,則就是將 數(shù)據(jù) 存儲在堆內(nèi)存,然后將存儲空間的地址 直接存儲在變量的 棧內(nèi)存中

3.3.2 不同數(shù)據(jù)類型之間變量賦值區(qū)別

  1. 基本數(shù)據(jù)類型之間的變量賦值, 賦值之后,變量之間互不影響

  2. 復(fù)雜數(shù)據(jù)類型之間的變量賦值,其實就是地址的賦值

    • 賦值后兩個變量的地址指向同一個 存儲空間,操作的也是同一個存儲空間
    • 注意: 函數(shù)調(diào)用的實參賦值給形參,形參賦值也遵守上面兩條 數(shù)據(jù)類型變量的賦值
// 基本數(shù)據(jù)類型之間的變量賦值
var n1 = 100;
var n2 = n1;
n2 = 200;
console.log(n1) // 100
console.log(n2) // 200

// 復(fù)雜數(shù)據(jù)類型之間的變量賦值
var arr = ['a', 'b', 'c'];
var arr2 = arr;
arr2[0] = 666;
console.log( arr ) // [666, "b", "c"]
console.log( arr[0] ) // 666

// 形參賦值1
function fn(n) {
 n = 200;
}
var num = 100
fn(num);
console.log(num) // 100

3.3.3 數(shù)據(jù)類型之間變量的比較

基本數(shù)據(jù)類型的變量比較 其實就是值的比較
復(fù)雜數(shù)據(jù)類型的變量比較 其實就是地址的比較

// 基本數(shù)據(jù)類型
var num1 = 100;
var num2 = 100;
console.log( num1 == num2 )//true

// 復(fù)雜數(shù)據(jù)類型  
var arr1 = [1, 2, 3];
var arr2 = [1, 2, 3];
console.log(arr1 == arr2) // false

3.3.4 數(shù)組排序

(1) 冒泡排序

遍歷數(shù)組,在循環(huán)中用前一個數(shù)組元素和后一個數(shù)組元素來兩兩比較
如果前一個值比后一個更大,則交換位置,如果沒有更大,則不交換位置
遍歷結(jié)束后保證了數(shù)組中的最大值在最后面
進行多次的循環(huán)比較交換位置后,數(shù)組排序就完成了

var arr = [3, 5, 6, 4, 9, 7, 8, 2, 1];
for (var j = 0; j < arr.length - 1; j++) {
  for (var i = 0; i < arr.length - 1 - j; i++) {
    // 前一個和后一個比較,如果前一個更大,則交換位置
    if (arr[i] > arr[i + 1]) { // 交換位置
      var tmp = arr[i];
      arr[i] = arr[i + 1];
      arr[i + 1] = tmp;
    }
  }
}
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

(2) 選擇排序

第一次假設(shè)數(shù)組下標(biāo)為0是最小值
從數(shù)組下標(biāo)1開始遍歷數(shù)組,拿數(shù)組中的每一個元素逐個和假設(shè)的值比較
如果某一個值比假設(shè)的更小,則記錄下索引
然后用記錄索引的值和后面的數(shù)組元素繼續(xù)比較,如果更小則替換索引
遍歷結(jié)束之后,將記錄的索引的值和下標(biāo)為0 的值交換位置

第二次假設(shè)數(shù)組下標(biāo)為1是最小值
從數(shù)組下標(biāo)2開始遍歷數(shù)組,拿數(shù)組中的每一個元素逐個和假設(shè)的值比較
如果某一個值比假設(shè)的更小,則記錄下索引
然后用記錄索引的值和后面的數(shù)組元素繼續(xù)比較,如果更小則替換索引
遍歷結(jié)束之后,將記錄的索引的值和下標(biāo)為1 的值交換位置
在進行多次選擇比較(交換位置)后,數(shù)組排序完成

// 進行j次假設(shè)遍歷后,數(shù)組排序完成
for (var j = 0; j < arr.length - 1; j++) {
  // 假設(shè)數(shù)組索引 j 就是最小值
  var minIndex = j; // 定義遍歷記錄最小值索引
  // 從數(shù)組索引 j+1 遍歷
  for (var i = j + 1; i < arr.length; i++) {
    // 數(shù)組元素和索引為minIndex的值比較
    if (arr[i] < arr[minIndex]) { // 如果某一個值比minIndex的值更小則將索引記錄在minIndex中
      minIndex = i;
    }
  }
  // 遍歷結(jié)束,將索引為minIndex中的值和索引為j的值交換位置
  //  如果minIndex就是我們一開始假設(shè)的最小值的索引 j ,則不需要交換位置
  if (minIndex != j) {
    var tmp = arr[j];
    arr[j] = arr[minIndex]
    arr[minIndex] = tmp;
  }
}
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

3.4 字符串

3.4.1 嚴(yán)格模式

因為一開始的時候,js語法設(shè)計不是很嚴(yán)謹(jǐn)
js嚴(yán)格模式,主要是消除一些語法不合理的地方
也是為了未來新版本語法鋪墊
開啟嚴(yán)格模式,在代碼的最前面直接書寫 字符串 'use strict'

// 1. 嚴(yán)格模式下,沒有var 聲明的變量會報錯
num = 200; // 報錯
console.log( num )

// 2. 在嚴(yán)格模式下,定義的函數(shù)不能使用同名形參
function fn(num,num,num) {}  //報錯

// 3. 在嚴(yán)格模式下,全局函數(shù)中的this沒有任何指向
function ff() {
  console.log( this ) // undefined
}
ff(); // 函數(shù)中的this關(guān)鍵字,在函數(shù)普通調(diào)用方式的時候,this指向window

// 4. 在嚴(yán)格模式下,函數(shù)中不能使用arguments.callee 
function f2() {
  console.log( arguments )
  // console.log( arguments.callee ) // 報錯
}
f2(1,2,3,4)

// 5. 在嚴(yán)格模式下,不能書寫0開頭的八進制寫法
var n = 012;// 報錯
var n1 = 0o12; // 標(biāo)準(zhǔn)的0o開頭八進制數(shù)寫法可以使用
var n2 = 0b11; // 0b開頭的數(shù)字就是二進制數(shù)
var n3 = 0x11; // 0x開頭的數(shù)字就是十六進制數(shù)
console.log( n1,n2,n3 )

3.4.2 ES5中的數(shù)組常用方法

語法 作用
indexOf() 從前往后查找數(shù)組元素,返回索引或-1
lastIndexOf() 從后往前查找數(shù)組元素,返回索引或-1
forEach() 數(shù)組遍歷方法 沒有返回值
map() 數(shù)組映射方法 返回一個新數(shù)組
filter() 數(shù)組過濾方法 返回一個新數(shù)組
every() 數(shù)組判斷方法 返回布爾值
some() 數(shù)組判斷方法 返回布爾值

(1) indexOf

語法: 數(shù)組.indexOf(參數(shù))
根據(jù)傳入的參數(shù),去數(shù)組中從前往后查找,如果找到一樣的則返回索引,并停止查找
如果數(shù)組中沒有一樣的元素, 則返回-1
作用: 查找數(shù)組元素
返回值: 索引 或 -1 不會改變原數(shù)組

var arr = [1,2,3,4,5,2];
var res1 = arr.indexOf(2)
console.log('返回值:', res1) // 1 

(2) lastIndexOf

語法: 數(shù)組.lastIndexOf(參數(shù))
作用: 從數(shù)組元素的后面開始查找,參數(shù)在數(shù)組中是否存在,存在則返回索引,否則返回-1
返回值: 索引或 -1

var arr = [1, 2, 6, 4, 5, 6];
console.log( arr.lastIndexOf(6) ) // 5
console.log( arr.lastIndexOf(7) ) // -1

(3) forEach 數(shù)組遍歷方法

語法: 數(shù)組.forEach(參數(shù))
參數(shù)是一個函數(shù),函數(shù)有三個形參
作用: 遍歷數(shù)組, 數(shù)組有多少個元素,則執(zhí)行forEach中的函數(shù)多少次
這個方法沒有返回值

var arr = ['a', 'b', 'c', 'd'];
var res = arr.forEach(function (item,index,ar) {
  // item 每次函數(shù)執(zhí)行 表示數(shù)組的元素
  // index 每次函數(shù)執(zhí)行 表示數(shù)組元素的索引
  // ar 每次函數(shù)執(zhí)行 表示調(diào)用forEach的數(shù)組(原數(shù)組)
  console.log( item,index,ar )
})
console.log( res ) // undefined

(4) map 數(shù)組映射方法

語法: 數(shù)組.map(參數(shù))
參數(shù)是一個函數(shù),函數(shù)有三個形參
作用: 按照既定的條件操作數(shù)組的每一個元素, 數(shù)組有多少個元素,則執(zhí)行map中的函數(shù)多少次
這個map方法有返回值: 一個新數(shù)組
函數(shù)中return的結(jié)果就是組成新數(shù)組的元素,所以此函數(shù)要有return
此方法不會改變原數(shù)組

var arr = [10, 20, 30, 40];
var res = arr.map(function (item, index, ar) {
  // item 每次函數(shù)執(zhí)行 表示數(shù)組的元素
  // index 每次函數(shù)執(zhí)行 表示數(shù)組元素的索引
  // ar 每次函數(shù)執(zhí)行 表示原數(shù)組
  // console.log(item, index, ar)
  return item+5;
})
console.log( res ) // [15, 25, 35, 45]
console.log( arr ) // [10, 20, 30, 40]

(5) filter 數(shù)組過濾方法

語法: 數(shù)組.filter(參數(shù))
參數(shù)是一個函數(shù),函數(shù)有三個形參
作用: 數(shù)組有多少個元素,則執(zhí)行filter中的函數(shù)多少次
這個filter方法有返回值: 一個新數(shù)組
函數(shù)中return的結(jié)果,如果為true,則對應(yīng)的這個數(shù)組元素作為新數(shù)組的元素骨宠,如果為false,則對應(yīng)的這個數(shù)組元素不會作為新數(shù)組的元素此方法不會改變原數(shù)組

var arr = [10, 20, 30, 40];
var res = arr.filter(function (item, index, ar) {
  // item 每次函數(shù)執(zhí)行 表示數(shù)組的元素
  // index 每次函數(shù)執(zhí)行 表示數(shù)組元素的索引
  // ar 每次函數(shù)執(zhí)行 表示原數(shù)組
  // console.log(item, index, ar)
  return item>=30;
}) 
console.log( res ) // [30, 40]
console.log( arr ) // [10, 20, 30, 40]

(6) every 數(shù)組判斷方法

語法: 數(shù)組.every(參數(shù))
參數(shù)是一個函數(shù),函數(shù)有三個形參
作用: 如果 函數(shù)return false ,則不再執(zhí)行繼續(xù)執(zhí)行函數(shù),不再遍歷數(shù)組,every方法的返回值就是false, 如果數(shù)組遍歷到結(jié)束 每次函數(shù)返回 都是true,則every方法的返回
為true
返回值: 布爾值
此方法不會改變原數(shù)組

var arr = [10, 20, 30, 40, 50];
var res = arr.every(function (item, index, ar) {
  // item 每次函數(shù)執(zhí)行 表示數(shù)組的元素
  // index 每次函數(shù)執(zhí)行 表示數(shù)組元素的索引
  // ar 每次函數(shù)執(zhí)行 表示原數(shù)組
  // console.log(item, index, ar)
  // return item <= 30;
  return item>5;
})
console.log(res) // true
console.log( arr ) // [10, 20, 30, 40]

(7) some 數(shù)組判斷方法

語法: 數(shù)組.some(參數(shù))
參數(shù)是一個函數(shù),函數(shù)有三個形參
作用: 如果 函數(shù)返回 true ,則不再執(zhí)行繼續(xù)執(zhí)行函數(shù),不再遍歷數(shù)組,some方法的返回值就是true, 如果數(shù)組遍歷到結(jié)束 每次函數(shù)返回 都是false,則some方法的返回值為false
返回值: 布爾值
此方法不會改變原數(shù)組

var arr = [10, 20, 30, 40, 50];
var res = arr.some(function (item, index, ar) {
  // item 每次函數(shù)執(zhí)行 表示數(shù)組的元素
  // index 每次函數(shù)執(zhí)行 表示數(shù)組元素的索引
  // ar 每次函數(shù)執(zhí)行 表示原數(shù)組
  console.log(item, index, ar)
  // return item>5;
  // return item >= 30;
  return item>100
})
console.log(res) // false
console.log( arr ) // [10, 20, 30, 40]

3.4.3 字符串常用方法

(1) 字符串.charAt(索引)

根據(jù)索引查找字符串中對應(yīng)的字符并返回,如果查找不到,則返回空字符串

var str = 'hello';
console.log( str.charAt(0) ); // 'h'
console.log( str.charAt(5) ); // ''
console.log( typeof str.charAt(5) ); // string

(2) 字符串.charCodeAt(索引)

根據(jù)索引查找字符串中對應(yīng)的字符的編碼值并返回,如果查找不到,則返回NaN

var str = 'hello';
console.log( str.charCodeAt(0) ); // 104 'h'的阿斯克編碼是104
console.log( str.charCodeAt(5) ); // NaN

(3) 字符串.indexOf(參數(shù)) 參數(shù)也是一個字符串

查找參數(shù)在字符串中是否存在,從前往后查找,找到了則停止,存在則返回對應(yīng)的索引,不存在則返回-1

var str = 'hel--lo';
console.log( str.indexOf('h') ); // 0
console.log( str.indexOf('l') ); // 2
// indexOf(參數(shù),起始索引)  從起始索引開始 查找
console.log( str.indexOf('l',3) ); // 5

(4) 字符串.lastIndexOf(參數(shù)) 參數(shù)也是一個字符串

查找參數(shù)在字符串中是否存在,從后往前查找,找到了則停止,存在則返回對應(yīng)的索引,不存在則返回-1

var str = 'hel--lo';
console.log( str.lastIndexOf('h') ); // 0
console.log( str.lastIndexOf('z') ); // -1
console.log( str.lastIndexOf('l') ); // 2
// lastIndexOf(參數(shù),起始索引)  從起始索引開始往前 查找
console.log( str.lastIndexOf('l',3) ); // 2

(5) 字符串.substring(起始索引,結(jié)束索引)

起始索引和結(jié)束索引 是按照傳入的索引 從小到大截取
從起始索引開始截取字符串中的內(nèi)容到結(jié)束索引為止(不包含結(jié)束索引)

var str = 'abcdefg';
console.log(str.substring(2, 5)); // 'cde' 
console.log(str.substring(5, 2)); // 'cde'

(6) 字符串.substr(起始索引,截取個數(shù))

從起始索引開始截取字符串中的內(nèi)容

var str = 'abcdefg';
console.log(str.substr(2, 5)); // 'cdefg'
console.log(str.substr(5, 2)); // 'fg'

(7) 字符串.slice(起始索引,結(jié)束索引)

從起始索引開始截取字符串中的內(nèi)容 到結(jié)束索引為止 (不包含結(jié)束索引)
結(jié)束索引可以是負(fù)數(shù) -1表示最后一個字符,-2表示倒數(shù)第二個字符....

var str = 'abcdefg';
// console.log(str.slice(2, 5)); // 'cde'
console.log(str.slice(2, -1)); // 'cdef'
console.log(str.slice(0, 0)); // ''

(8) 字符串.split(參數(shù)) 參數(shù)也是字符串

根據(jù)傳入的內(nèi)容,將字符串打斷(分割),組成一個數(shù)組返回
如果不傳入?yún)?shù),或傳入的參數(shù)在字符串中不存在,則整個字符串就當(dāng)做一個數(shù)組的元素,返回此數(shù)組
如果傳入的是空字符串,則將字符串中的每一個字符,當(dāng)做數(shù)組元素,返回數(shù)組

var str = '2022-6-30';
console.log(str.split('-')); // ["2022", "6", "30"]
console.log(str.split()); // ["2022-6-30"]
console.log(str.split('+')); // ["2022-6-30"]
console.log(str.split('')); //["2", "0", "2", "2", "-", "6", "-", "3", "0"]

(9) 字符串.toLowerCase() 將字符串全轉(zhuǎn)為小寫

var str = 'He-L-lo';
console.log(str.toLowerCase()); // he-l-lo

(10) 字符串.toUpperCase() 將字符串全轉(zhuǎn)為大寫

var str = 'He-L-lo123';
console.log(str.toUpperCase()); // HE-L-LO

(11) 字符串.replace(要替換的內(nèi)容,替換為什么)

var str = 'He-L-lo';
// 替換字符串內(nèi)容,只會替換第一部分內(nèi)容
console.log(str.replace('-','+')); // He+L-lo

(12) 練習(xí)

// 需求: 假設(shè)上傳商品圖片的應(yīng)用場景,需要判斷上傳文件后綴是圖片
var allow = ['jpg', 'png'];
// 給btn一個點擊事件
btn.onclick = function () {
  // 獲取選擇的完整文件名
  // input標(biāo)簽的值: 元素.value
  var fileName = img.value;
  // console.log( fileName )
  // 獲取上傳文件的后綴
  var arr = fileName.split('.');
  // arr數(shù)組的最后一個元素就是文件后綴
  var ext = arr[arr.length - 1];
  // 判斷上傳的文件是否是允許的圖片類型
  if(allow.indexOf(ext) === -1){
    alert('不是圖片')
  }else{
    alert('上傳中');
  }
}

3.4.4 進制轉(zhuǎn)換

(1) 數(shù)值變量.toString(參數(shù))

參數(shù)就是我們要將數(shù)值轉(zhuǎn)換為多少進制的數(shù)字字符串顯示
默認(rèn)不傳參數(shù)就是十進制
參數(shù)的取值范圍: 2~36
返回值: 進制轉(zhuǎn)化后的字符串

// var num = 20;
console.log( num.toString() ); // '20'
console.log( num.toString(2) ); // '10100'
console.log( num.toString(8) ); // '24'
console.log( num.toString(16) ); // '14'
console.log( num.toString(3) ); // '202'

(2) parseInt(數(shù)字或字符串)

數(shù)字或字符串,將第一個參數(shù)當(dāng)做幾進制計算
如果第二個參數(shù)不寫,就是當(dāng)做十進制數(shù)轉(zhuǎn)給十進制整數(shù)
返回值: 十進制的整數(shù)或者NaN

var str = '1010';
console.log( parseInt(str) ) // 1010
console.log( parseInt(str,2) ) // 10
console.log( parseInt('a1',2) ) // NaN
console.log( parseInt('a1',16) ) // 161

3.5 Math和Date

3.5.1 Math

Math是js中的內(nèi)置一個對象,這個對象中有很多操作數(shù)值的方法

(1) random() 獲取0~1的隨機數(shù)

console.log( Math.random() )

(2) round(數(shù)值) 四舍五入取整

console.log( Math.round(5.1) ) // 5
console.log( Math.round(5.5) ) // 6
console.log( Math.round(5.9) ) // 6

(3) abs(數(shù)值) 求數(shù)值的絕對值

console.log( Math.abs(100) ) // 100
console.log( Math.abs(-100) ) // 100

(4) floor(數(shù)值) 對數(shù)值向下取整

console.log(Math.floor(5.1)) // 5
console.log(Math.floor(5.5)) // 5
console.log(Math.floor(5.9)) // 5

(5) ceil(數(shù)值) 對數(shù)值向上取整

console.log(Math.ceil(5.1)) // 6
console.log(Math.ceil(5.5)) // 6
console.log(Math.ceil(5.9)) // 6

(6) max(多個數(shù)值) 求多個數(shù)值中的最大值

console.log( Math.max(1,2,32,4,1000) ); // 1000

(7) min(多個數(shù)值) 求多個數(shù)值中的最小值

console.log(Math.min(1, 2, 32, 4, 1000)); //1

(8) sqrt(數(shù)值) 求數(shù)值的平方根

console.log( Math.sqrt(4) ); // 2
console.log( Math.sqrt(16) );// 4
console.log( Math.sqrt(25) ); // 5

(9) pow(數(shù)值,多少次方) 求數(shù)值的多次冪

console.log(Math.pow(2, 2)); // 4
console.log(Math.pow(2, 3)); // 8
console.log(Math.pow(2, 4)); // 16
console.log(Math.pow(5, 5)); // 3125

(10) PI 求圓周率

console.log( Math.PI ); // 3.141592653589793

(11) 練習(xí)

// 數(shù)字字母混合驗證碼
// 獲取一個四位的驗證碼
var str = '1234567890qwertyuiopasdfghjklmnbvcxz';
var code = ''; //四位驗證碼變量
// str字符串的索引范圍 0~str.length-1
// 四次獲取str隨機的索引,并根據(jù)索引獲取對應(yīng)的字符然后拼接
for (var i = 0; i < 4; i++) {
  var index = getNum(0, str.length - 1); // 獲取隨機索引
  code += str.charAt(index); // 根據(jù)索引獲取對應(yīng)的字符,然后拼接在code中
}
console.log( code )
// 獲取n~m的范圍隨機整數(shù)
function getNum(n, m) {
  var max = Math.max(n, m);
  var min = Math.min(n, m);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

3.5.2 date

Date是js的系統(tǒng)內(nèi)置構(gòu)造函數(shù)
可以通過 new Date() 創(chuàng)建一個時間對象

(1) new Date() 創(chuàng)建時間對象

在new Date() 創(chuàng)建時間對象的時候

  1. 不傳參數(shù),則返回當(dāng)前的時間對象
  2. 傳遞參數(shù),如果單獨傳遞的是年月日時分秒?yún)?shù),則至少要傳遞兩個
  3. 如果傳遞的月份,日期,小時,分鐘,秒超過了范圍,則往上一級時間累計
參數(shù) 表示
YYYY 年份
MM 月份(0~11 0表示1月方灾,11表示12月)
DD 日期(月份中的第幾天)
hh 小時(0~23)
mm 分鐘(0~59)
ss 秒(0~59)
// 不傳參數(shù)得到當(dāng)前時間
// 在控制臺輸出的時候,會讓時間對象調(diào)用toString()方法,轉(zhuǎn)為時間字符串
console.log( new Date() ) // Mon Jul 04 2022 21:13:34 GMT+0800 (中國標(biāo)準(zhǔn)時間)
console.dir(數(shù)據(jù))  可以查看到數(shù)據(jù)的結(jié)構(gòu)
console.dir( new Date() ) // Object
console.log( new Date() == new Date() ) // false 說明是復(fù)雜數(shù)據(jù)結(jié)構(gòu)

// 傳遞參數(shù)
// 星期 月份 日期 年份 時間
console.log( new Date('2022','6') ) // Fri Jul 01 2022 00:00:00 GMT+0800 (中國標(biāo)準(zhǔn)時間)
// 如果月份傳遞的超過11,則年份+1進行計算
console.log( new Date('2022','12') ) // Sun Jan 01 2023 00:00:00 GMT+0800 (中國標(biāo)準(zhǔn)時間)
console.log( new Date('2022','6','4','21','25','30') ) //Mon Jul 04 2022 21:25:30 GMT+0800 (中國標(biāo)準(zhǔn)時間)

(2) 時間字符串

如果傳遞的是時間字符串,則1就是表示1月份
'YYYY-MM-DD hh:mm:ss'
'YYYY/MM/DD hh:mm:ss'
'YYYY.MM.DD hh:mm:ss'

console.log( new Date('2022-07-05 00:00:00') ) // Tue Jul 05 2022 00:00:00 GMT+0800 (中國標(biāo)準(zhǔn)時間)
console.log( new Date('2022/07/05 00:00:00') ) // Tue Jul 05 2022 00:00:00 GMT+0800 (中國標(biāo)準(zhǔn)時間)
console.log( new Date('2022.07.05 00:00:00') ) // Tue Jul 05 2022 00:00:00 GMT+0800 (中國標(biāo)準(zhǔn)時間)

(3) 時間方法

js給我們共了很多操作時間的方法
主要分為兩套操作時間的方法

  1. get一套 是獲取時間的方法
  2. set一套 設(shè)置時間的方法
  3. 注意:get和set方法一致
獲取時間方法 描述
getFullYear() 獲取年份
getMonth() 獲取月份 0~11
getDate() 獲取日期 1~31
getHours() 獲取小時數(shù) 0~23
getMinutes() 獲取分鐘數(shù) 0~59
getSeconds() 獲取秒 0~1000
getMilliseconds() 獲取毫秒數(shù)
getDay() 獲取星期幾 0~6
getTime() 獲取時間戳
var time = new Date();  
console.log( time )
// get一套
// 1. getFullyear() 獲取年份
console.log( time.getFullYear() ) // 2022

// 2. getMonth()  獲取月份 0~11
// 0表示1月份  11表示12月份
console.log( time.getMonth() ) // 6

// 3. getDate()  獲取日期 1~31
console.log( time.getDate() ) // 4

// 4. getHours()  獲取小時數(shù) 0~23
console.log( time.getHours() ) // 21

// 5. getMinutes()  獲取分鐘數(shù) 0~59
console.log( time.getMinutes() ) //35

// 6. getSeconds() 獲取秒 0~1000
console.log( time.getSeconds() )

// 7. getMilliseconds()  獲取毫秒數(shù)
console.log( time.getMilliseconds() )

// 8. getDay()  獲取星期幾 0~6
// 0 就是星期天 6就是星期六
console.log( time.getDay() ) // 1

// 9. getTime()  獲取時間戳
// 時間戳: 就是從格林威治時間到 這個時間對象 經(jīng)歷過的時間毫秒數(shù)
// 格林威治時間: 1970-01-01 00:00:00 
console.log( time.getTime() )

// set一套 用于設(shè)置時間對象的方法
// 1. setFullYear()
time.setFullYear(2023)
console.log( time ) // Tue Jul 04 2023 21:42:02 GMT+0800 (中國標(biāo)準(zhǔn)時間

// 2. setMonth() 設(shè)置月份 0~11 
// 0表示1月份  11表示12月份
time.setMonth(0);
console.log( time ) // Tue Jan 04 2022 21:43:01 GMT+0800 (中國標(biāo)準(zhǔn)時間)

(4) 練習(xí)

// 求兩個時間的 時間差,返回相差 多少天 多少小時 多少分 多少秒
// 定義一個獲取兩個時間的時間差函數(shù),返回相差的 多少天 多少小時 多少分 多少秒
function getDiff(t1, t2) {
  // // 1. 將傳入的兩個時間對象轉(zhuǎn)為時間戳(毫秒數(shù))
  // t1 = t1.getTime()
  // t2 = t2.getTime()
  // console.log( t1,t2 )
  // // 2. 時間戳相減,得到個相差的毫秒數(shù),除1000 然后取整 得到相差的秒數(shù)
  // var diff = Math.round((t2-t1)/1000);
  // console.log( diff )
  // 獲取兩個時間對象 相差的毫秒數(shù)可以直接將兩個時間對象相減
  // 因為在相減的時候,會將兩個時間對象轉(zhuǎn)為 對應(yīng)的時間戳然后相減
  // console.log( Math.round((t2-t1)/1000) )
  var diff = Math.round((t2 - t1) / 1000);
  // 根據(jù)diff計算出 相差的整 天數(shù)
  // diff/一天的秒數(shù)  然后取整
  var days = parseInt(diff / (24 * 60 * 60));
  // 根據(jù)diff計算出 相差的小時數(shù)(不足一天的小時數(shù))
  // diff/60/60%24 取整
  var hours = parseInt(diff / 60 / 60 % 24);
  // console.log( hours )
  // 根據(jù)diff計算出 相差的分鐘(不足一小時的分鐘數(shù))
  // diff/60%60 取整
  var minutes = parseInt(diff / 60 % 60);
  // console.log( minutes );
  // 根據(jù)diff計算出 相差的秒數(shù)(不足一分鐘的秒數(shù))
  // diff%60 
  var seconds = diff % 60;
  // 拼接字符串并返回
  return days + '天' + hours + '小時' + minutes + '分鐘' + seconds + '秒';
}
// // 獲取兩個時間對象
// var time1 = new Date();
// var time2 = new Date('2023-01-22 00:00:00');
// // var time2 = new Date('2022-07-06 00:00:00');
// var str = getDiff(time1,time2);
// console.log( str )
// 在頁面中顯示距離春節(jié)的倒計時
// document.write(str)
// 可以使用定時器完成倒計時
// 語法: setInterval(函數(shù),時間)
// 每過一段時間會執(zhí)行一次函數(shù)
// 時間單位是毫秒
setInterval(function () {
  // 獲取兩個時間對象
  var time1 = new Date(); // 當(dāng)前時間
  var time2 = new Date('2023-01-22 00:00:00'); // 春節(jié)時間
  var str = getDiff(time1, time2);
  // 設(shè)置頁面元素中的內(nèi)容: 語法:元素.inneText = 內(nèi)容. 覆蓋性的設(shè)置
  dv.innerText = '距離春節(jié)還有:'+str;
}, 1000)

四嘿棘、BOM 和 DOM

4.1 BOM 瀏覽器對象模型

瀏覽器對象模型: 所有的瀏覽器操作方法都在對象中

  1. BOM中的頂級對象 是window
  2. 瀏覽器操作中的各個操作對象 都是window對象的屬性成員
  3. 全局中的this和top關(guān)鍵字 指向window對象
  4. BOM操作中 可以省略window焦人,比如: 瀏覽器彈窗 windiw.alert()花椭,實際使用中可以省略window 直接 alert()
  5. 在全局中通過var定義的變量或函數(shù) 其實就是添加在window對象中的屬性和方法

4.1.1 瀏覽器事件

(1) load 瀏覽器加載事件

// 1. load  瀏覽器加載事件(當(dāng)瀏覽器頁面中將所有資源[圖片,cssm,js....]都加載完畢的時候觸發(fā))
window.onload = function () {
  // 這個函數(shù)會在 頁面中所有內(nèi)容都加載完畢后才觸發(fā) 執(zhí)行
  console.log( dv ) // <div id="dv"></div>
}

(2) scroll 瀏覽器頁面滾動滾動事件

// 2. scroll  瀏覽器頁面滾動滾動事件
window.onscroll = function () {
  console.log( '瀏覽器滾動了' )
}

(3) resize 瀏覽器可視窗口的尺寸變化事件

// 3. resize  瀏覽器可視窗口的尺寸變化事件
window.onresize = function(){
  console.log( '窗口大小變化了' );
}

4.1.2 BOM的相關(guān)操作

(1) 獲取瀏覽器的窗口尺寸

  1. window.innerWidth 瀏覽器可視窗口的寬度(包含滾動條)
  2. window.innerHeight 瀏覽器可視窗口的高度(包含滾動條)
console.log( window.innerWidth )
console.log( window.innerHeight )

// 在窗口大小變化事件中獲取窗口大小
// 當(dāng)瀏覽器可視窗口大小小于 800的時候div不顯示
window.onresize = function () {
  console.log(window.innerHeight)
  console.log(window.innerWidth)
  if (window.innerWidth < 800) {
    // div隱藏
    dv.style.display = 'none'
  } else {
    dv.style.display = 'block'
  }
}

(2) 瀏覽器信息

瀏覽器信息通過navigator對象獲取,window.navigator

// 1. 獲取瀏覽器整體信息
console.log( navigator.userAgent ) // Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36

(3) 瀏覽器地址欄

1. location.href 獲取設(shè)置瀏覽器地址url的

// location.href 獲取設(shè)置瀏覽器地址url的,如果給location.href一個新的地址,則頁面會發(fā)生跳轉(zhuǎn)
btn1.onclick = function () {
  location.;
}
// 地址中的 中文等特殊字符會被轉(zhuǎn)為url編碼格式展示
console.log( location.href )

2. location.reload() 刷新頁面

// location.reload()  刷新頁面,注意: 不要在全局中直接書寫,不然會一直刷新頁面
location.reload()
btn2.onclick = function () {
  location.reload();  
}

(4) 瀏覽器的歷史記錄信息

1. history.back()
回退到歷史記錄中的上一個頁面,前提要有歷史記錄

2. history.forward()
前進到歷史記錄中的下一個頁面,前提要有歷史記錄

3. history.go(n)
n為正數(shù)則前進到歷史記錄中的前幾個頁面
n為負(fù)數(shù)則回退到歷史記錄中的后幾個頁面
history.go(-1) 相當(dāng)于 history.back()
history.go(1) 相當(dāng)于 history.forward()
history.go() 會刷新頁面

(5) 瀏覽器的滾動距離

瀏覽器水平滾動距離
瀏覽器垂直滾動距離

1.頁面有DOCTYPE文檔聲明的時候
通過 document.documentElement.scrollLeft 獲取
通過 document.documentElement.scrollTop 獲取

console.log( window.document.documentElement.scrollLeft )
console.log( document.documentElement.scrollTop )

2.頁面沒有DOCTYPE文檔聲明的時候
通過 document.body.scrollLeft 獲取
通過 document.body.scrollTop 獲取
javascript

console.log(document.body.scrollLeft)
console.log( document.body.scrollTop )

(6) 頂部通欄

// 當(dāng)瀏覽器滾動距離小于(800)的時候,隱藏頂部通欄,否則顯示
window.onscroll = function () {
  // 獲取滾動的距離
  var goLength = document.documentElement.scrollTop;
  if (goLength >= 800) {
    top1.style.height = '80px';// 顯示頂部通欄
  } else {
    top1.style.height = '0px';// 隱藏頂部通欄
  }
}

4.2 定時器

在前端 js中 代碼執(zhí)行是單線程(同一時間只能做一件事)
JS 提供給我們一個 異步代碼執(zhí)行機制

異步代碼執(zhí)行機制(EventLoop)

  • 當(dāng)代碼執(zhí)行過程中,遇見異步代碼了
  • 不會立即執(zhí)行異步代碼,而是將異步代碼放到 事件隊列池 中等待
  • 繼續(xù)向后執(zhí)行同步代碼
  • 等到所有同步代碼執(zhí)行完畢之后,調(diào)用棧清空了,再去異步事件隊列池中拿到異步代碼執(zhí)行
    定時器中的函數(shù)是異步執(zhí)行的代碼

4.2.1 定時器開啟

(1)延時定時器

  • 語法: setTimeout(函數(shù),數(shù)字,參數(shù)1,參數(shù)2,參數(shù)3,...)
    • 函數(shù): 表示時間達到的時候要執(zhí)行的函數(shù)
      第一個位置的參數(shù),可以不寫函數(shù),寫js代碼字符串也行
    • 數(shù)字: 倒計時間, 單位毫秒
    • 第二位置之后的參數(shù),是前面函數(shù)執(zhí)行時候的實參
console.log( new Date() )
setTimeout(function () {
  console.log( '兩秒過去了' )
  console.log( new Date() )
},2000)

(2)間隔定時器

  • 語法: setInterval(函數(shù),數(shù)字,參數(shù)1,參數(shù)2,參數(shù)3,...)
    • 函數(shù): 表示每間隔一段時間要執(zhí)行的函數(shù)
      第一個位置的參數(shù),可以不寫函數(shù),寫js代碼字符串也行
    • 數(shù)字: 倒計時間, 單位毫秒
    • 第二位置之后的參數(shù),是前面函數(shù)執(zhí)行時候的實參
setInterval(function(){
  console.log( '2s過去了' )
},2000)

4.2.2 定時器返回值

  • 返回值為數(shù)字,表示開始定時器的標(biāo)識
  • 兩種定時器的返回值都是一個樣
  • 不區(qū)分定時器種類,只是表示定時器的第幾個定時器
var t1 = setTimeout(function () {})
var t2 = setInterval(function () {})
console.log( 't1:',t1 )
console.log( 't2:',t2 )

4.2.3 關(guān)閉定時器

  • 關(guān)閉銷毀定時器的是,不區(qū)分定時器種類,只要給出的定時器標(biāo)識數(shù)是對的,就可以銷毀
  • 語法:
    • clearInterval(定時器標(biāo)識)
    • clearTimeout(定時器標(biāo)識)
var t1 = setTimeout(function () {console.log( 'timeout' )},3000);
var t2 = setInterval(function () {console.log( 'Interval' )},1000);
btn.onclick = function () {
  // clearInterval(t1)
  // clearInterval(t2)
  clearTimeout(t1)
  clearTimeout(t2)
}

4.3 DOM

認(rèn)識DOM - Document Object Model 文檔對象模型

  1. 如何找到頁面中我們操作的元素
  2. 操作(操作文本,操作屬性,操作樣式,操作增刪改查)

4.3.1 DOM獲取元素

用一個變量保存頁面中某一個或某些元素
獲取元素方法分兩類獲取非常規(guī)元素和獲取常規(guī)元素

(1) 獲取非常規(guī)元素

  • html: document.documentElement
  • head: document.head
  • body: document.body
  • title: document.title

(2)獲取常規(guī)元素

語法 名字 返回值
.getElementById() id 獲取元素,只能獲取一個元素 有則返回元素奕污,無則返回null
.getElementsByTagName() 標(biāo)簽名來獲取元素, 返回類數(shù)組 有則返回到數(shù)組中嘱根,無則返回空偽數(shù)組
.getElementsByClassName() 類名來獲取元素该抒, 返回類數(shù)組 有則返回數(shù)組凑保,無則返回空偽數(shù)組,為數(shù)組有l(wèi)ength屬性
.querySelector() 選擇器來獲取元素芝此, 只能獲取到匹配的第一個 有則返回第一個元素婚苹,無則返回null
.querySelectorAll() 選擇器來獲取元素, 返回類數(shù)組 有則返回數(shù)組廓译,無則返回空偽數(shù)組责循,可以使用forEach遍歷數(shù)組方法

4.3.2 元素屬性

標(biāo)簽屬性分類有三種

(1) 原生屬性

  • 在 W3C 規(guī)范中有的屬性名
  • 比如: id class style type src href...

(2) 自定義屬性

  • 在 W3C 規(guī)范中沒有的屬性名,是我們自己在書寫在標(biāo)簽上的

(3) H5 自定義屬性

  • 目的: 就是為了區(qū)分自定義屬性和原生屬性寫在標(biāo)簽上的形式
  • 要求: 書寫 H5 自定義屬性的時候,都要 data- 開頭
  • 比如: data-index = '888'
    • data- 表示這個是 H5 自定義屬性
    • index 表示屬性名
    • '888' 表示屬性值

4.3.3 操作元素屬性

(1) 操作原生屬性

  • 語法: 元素.屬性名 = 屬性值
  • 注意: 如果遇到布爾類型屬性,可以使用false或true賦值

(2) 操作自定義屬性(非H5)

<div id="box" index='666' data-index='888' data-id=999>hello</div>
<img src="https://img1.baidu.com/it/u=3923683862,2037492630&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=587"> <br>
<script>
//設(shè)置 語法: 元素.setAttribute(屬性名,屬性值)
dv.setAttribute('stock',99);

// 刪除 語法: 元素.removeAttribute(屬性名)
dv.removeAttribute('index')

// 獲取 語法: 元素.getAttribute(屬性名)
// 返回值: 該元素自定義屬性的值
var res = dv.getAttribute('index');
console.log( res ) // '666'
</script>

(3) 操作H5自定義屬性

每一個 元素節(jié)點 身上都有一個自帶的屬性名叫做 dataset
這個屬性的值是一個類似于 對象的數(shù)據(jù)結(jié)構(gòu),存儲的改標(biāo)簽上所有的H5自定義屬性
H5 自定義屬性的操作,就是對象dataset這個數(shù)據(jù)結(jié)構(gòu)的操作(同對象操作語法)

// 獲取元素
var dv = document.getElementById('box');
var img = document.querySelector('img');
// 查 語法: 元素.dataset.屬性名
console.log( dv.dataset.size )

// 增 語法: 元素.dataset.屬性名 = 屬性值
dv.dataset.size = 999;

// 改 語法: 元素.dataset.屬性名 = 屬性值
dv.dataset.id = 777

// 刪 語法: delete 元素.dataset.屬性
delete dv.dataset.index;

(4) 練習(xí)全選案例

  1. 全選按鈕的點擊操作
  • 當(dāng)全選按鈕是選中的狀態(tài)的時候,所有選項按鈕都是選中狀態(tài)
  • 當(dāng)全選按鈕是未選中的狀態(tài)的時候,所有選項按鈕都是未選中狀態(tài)
  1. 點擊每一個選項按鈕的操作
  • 每一個選項按鈕點擊的時候,都要判斷
  • 如果所有選項按鈕都是選中狀態(tài),則全選按鈕選中
  • 如果所有選項按鈕有任何一個未選中,則全選按鈕未選中
* {
  margin: 0;
  padding: 0;
}
.box {
  width: 100px;
  padding: 20px;
  margin: 50px auto;
  border: 2px solid #333;
  border-radius: 10px;
}
hr {
  margin: 10px 0;
}
<div class="box">
  <input type="checkbox" class="all">全選
  <hr>
  <input type="checkbox" class="item"> 選項一<br>
  <input type="checkbox" class="item"> 選項二<br>
  <input type="checkbox" class="item"> 選項三<br>
  <input type="checkbox" class="item"> 選項四<br>
</div>
// 獲取元素
var allBtn = document.querySelector('.all');
// 將偽數(shù)組轉(zhuǎn)為真數(shù)組方法
// 語法: Array.from(偽數(shù)組)
// 返回一個真數(shù)組(元素和偽數(shù)組元素一模一樣)
// 為了后面方便操作,將獲取的所有選項按鈕偽數(shù)組轉(zhuǎn)為真數(shù)組
var items = Array.from(document.querySelectorAll('.item'));
// 1. 全選按鈕的點擊操作
allBtn.onclick = function () {
  // 遍歷選項按鈕數(shù)組
  items.forEach(function (item) {
    // 將全選按鈕的 選中 狀態(tài)給每一個選項按鈕
    item.checked = allBtn.checked;
  })
}
// 2. 點擊每一個選項按鈕的操作
items.forEach(function (item) {
  // 遍歷選項按鈕元素數(shù)組,給每一個選項按鈕點擊事件
  item.onclick = function () { // 事件處理函數(shù)
    // 通過數(shù)組的every方法 判斷 是否 每一個選項按鈕都是 選中
    //  選項按鈕全選中為true,只有有一個沒有選中則為false
    // 將結(jié)果 給全選按鈕的checked屬性
    allBtn.checked = items.every(function (item) {
      return item.checked;
    })
  };
})

4.3.4 操作元素的樣式

在js中操作元素的樣式有三種

  1. 獲取元素行內(nèi)樣式(只能獲取元素的行內(nèi)樣式)
  2. 獲取元素的非行內(nèi)樣式(包含了行內(nèi)樣式和非行內(nèi)樣式)
  3. 設(shè)置元素的樣式(只能設(shè)置元素的行內(nèi)樣式)

注意: 涉及到帶中劃線的樣式名的時候

  • 轉(zhuǎn)為駝峰寫法
  • 使用數(shù)組關(guān)聯(lián)法

(1) 獲取元素的行內(nèi)樣式

語法: 元素.style.樣式名

console.log( ele.style.width );// 100px
console.log( ele.style.height );// 非行內(nèi)樣式
console.log( ele.style.backgroundColor ) // green
console.log( ele.style['background-color'] ) // green

(2) 獲取元素的非行內(nèi)樣式

語法: window.getComputedStyle(你要獲取樣式的元素).樣式名

// 注意:getComputedStyle在低版本ie中不能使用
console.log( window.getComputedStyle(ele).width ) // 100px
console.log( window.getComputedStyle(ele).height ) // 200px
console.log( window.getComputedStyle(ele).fontSize ) // 20px
console.log( window.getComputedStyle(ele)['font-size'] ) // 20px

// 在低版本ie中獲取元素的非行內(nèi)樣式
// 語法: 元素.currentStyle.樣式名  在主流瀏覽器中不能使用
console.log( ele.currentStyle.fontSize ) // 20px
console.log( ele.currentStyle.width ) // 100px

(3) 設(shè)置元素的樣式(只能設(shè)置行內(nèi)樣式)

語法: 元素.style.樣式名 = 樣式值

ele.style.backgroundColor = 'blue';
ele.style['background-color'] = 'blue';
ele.style.fontSize = '50px';

4.3.5 操作元素的類名

  1. className
  • 就是原生屬性的操作 元素.屬性名
  • 因為 JS中有一個關(guān)鍵字叫 class,為了避開改名叫做className
  • 注意: 類名的值 是字符串,可以多個類名一起
  1. classList
  • 每一個元素身上都有一個屬性 叫做classList
  • 該屬性對應(yīng)的值是一個類似于 數(shù)組的解構(gòu),方法是該元素的所有類名
  • 增刪改查都是對象元素的classList操作,有專門的方法
    • 增: 元素.classList.add(類名)
    • 刪: 元素.classList.remove(類名)
    • 切換: 元素.classList.toggle(類名)
    • 原來有該類名則刪除,沒有則添加
// className
// 設(shè)置: 元素.className = "值"
// 因為是用的是 = 賦值,會把之前的類名覆蓋
ele.className = 'box';
ele.className = '';
// 追加類名 元素.className += ' 值'
ele.className += ' box'

// classList
console.log( ele.classList )
// 增
ele.classList.add('box');
ele.classList.add('active');
// 刪除
ele.classList.remove('b');
// 切換
ele.onclick = function () {
  ele.classList.toggle('active');
}

4.3.6 操作元素的內(nèi)容

(1) innerText

  • 語法: 元素.innerText
  • 獲取元素的所有文本內(nèi)容
  • 語法: 元素.innerText = '值'
  • 作用: 完全覆蓋是的書寫標(biāo)簽文本內(nèi)容
  • 注意: 沒有辦法識別解析 html格式的字符串
//  innerText
console.log(ele.innerText)
ele.innerText = '666';
ele.innerText = '<h1>888</h1>';

(2) innerHTML

是一個讀寫屬性

  • 語法: 元素.innerHTML
  • 獲取元素的所有內(nèi)容(包含了超文本內(nèi)容),以html格式字符串的形式返回
  • 語法: 元素.innerHTML = '值'
  • 作用: 完全覆蓋是的書寫標(biāo)簽 超文文本內(nèi)容
  • 注意: 可以識別解析 html格式的字符串
//  innerHTML
console.log(ele.innerHTML)
ele.innerHTML = '666';
ele.innerHTML = '<h1>888</h1>';

(3) value

表單標(biāo)簽的內(nèi)容操作
一個讀寫屬性,其實就是原生屬性value操作

  • 語法: 表單元素.value
  • 得到: 該表單元素的value值
  • 語法: 表單元素.vlaue = '值'
  • 作用: 設(shè)置表單元素的value值
// value
console.log( inp.value )
inp.value = 888

4.3.7 獲取元素的尺寸

有兩套語法offsetWdith和offsetHeight

(1) 語法

  • 元素.offsetWdith
    • 獲取元素的 內(nèi)容+padding+border 區(qū)域的寬度
  • 元素.offsetHeight
    • 獲取元素的 內(nèi)容+padding+border 區(qū)域的高度
  • 注意: 不管盒子是什么模型,區(qū)域不變
// // 1. offset方式
console.log( ele.offsetWidth )
console.log( ele.offsetHeight )

(2) 語法

  • 元素.clientWdith
    • 獲取元素的 內(nèi)容+padding 區(qū)域的寬度
  • 元素.clientHeight
    • 獲取元素的 內(nèi)容+padding 區(qū)域的高度
// 2. client方式
console.log(ele.clientWidth)
console.log(ele.clientHeight)

4.3.8 獲取元素的偏移量

(1) 獲取偏移量參考元素

語法: 元素.offsetParent
得到: 該元素的偏移量參考父級

  • 就是該元素的定位父級
  • 如果到body都沒有定位父級,那么這里的offsetParent就是body

(2)第一套語法

  • 元素.offsetLeft
    • 獲取元素相對于 offsetParent 的左側(cè)距離
  • 元素.offsetTop
    • 獲取元素相對于 offsetParent 的上方距離

(3)第二套語法

  • 元素.clientLeft
    • 獲取元素(內(nèi)容+padding區(qū)域) 相對于該元素border左邊的尺寸
  • 元素.clientTop
    • 獲取元素(內(nèi)容+padding區(qū)域) 相對于該元素border上邊的尺寸
console.log( 'offsetParent:',spanEle.offsetParent )

console.log( 'offsetLeft:',spanEle.offsetLeft )
console.log( 'offsetTop:',spanEle.offsetTop )

console.log( 'clientLeft:',spanEle.clientLeft )
console.log( 'clientTop:',spanEle.clientTop )

4.3.9 獲取可視窗口尺寸

BOM 級別獲取: 包含滾動條

  • innerWidth
  • innerHeight

DOM 級別獲取: 不包含滾動條

  • document.documentElement.clientHeight
  • document.documentElement.clientWidth
// 獲取可視窗口
console.log( 'BOM' )
console.log( '寬度',window.innerWidth )
console.log( '高度',window.innerHeight )

console.log( 'DOM' )
console.log( '寬度',document.documentElement.clientWidth)
console.log( '高度',document.documentElement.clientHeight)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市暮芭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瑞筐,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膘格,死亡現(xiàn)場離奇詭異,居然都是意外死亡政敢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門褪尝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來避诽,“玉大人沙庐,你說我怎么就攤上這事≈郑” “怎么了鹊汛?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我有梆,道長,這世上最難降的妖魔是什么痰催? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮缝裁,結(jié)果婚禮上韩脑,老公的妹妹穿的比我還像新娘段多。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缀程,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撩满。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機與錄音张咳,去河邊找鬼脚猾。 笑死,一個胖子當(dāng)著我的面吹牛泌参,可吹牛的內(nèi)容都是我干的盖溺。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼蝇庭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了北发?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎僵井,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體驻债,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了恨闪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咙咽。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出炊昆,到底是詐尸還是另有隱情视乐,我是刑警寧澤佑淀,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站景图,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏妆毕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一润努、第九天 我趴在偏房一處隱蔽的房頂上張望任连。 院中可真熱鬧,春花似錦、人聲如沸秉沼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽休建。三九已至,卻和暖如春砌些,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背有巧。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留逊笆,地道東北人。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谍憔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容