0 介紹
0.1 ECMAScript
ECMA-262 的第 5 版是 JS 的第一個(gè)穩(wěn)定版本,得到了各瀏覽器廠商的支持。<br />
- 語(yǔ)法
- 類型
- 語(yǔ)句
- 關(guān)鍵詞
- 保留字
- 操作符
- 對(duì)象
0.2 DOM
文檔對(duì)象模型是針對(duì) XML 但經(jīng)過(guò)擴(kuò)展用于 HTML 的 API 。DOM 把整個(gè)頁(yè)面映射為一個(gè)多層次節(jié)點(diǎn)結(jié)構(gòu)。HTML 或 XML 頁(yè)面中的每個(gè)組成部分都是某種類型的節(jié)點(diǎn),這些節(jié)點(diǎn)又包含著不同類型的數(shù)據(jù)灼狰。<br />document object model 文檔對(duì)象模型,里面提供了一些屬性和方法浮禾,可以讓我們操作頁(yè)面的元素
0.3 BOM
原則上講交胚,BOM只處理瀏覽器窗口和框架,但下面一些針對(duì)瀏覽器的 JS 擴(kuò)展也被看做是BOM的一部分盈电。<br />browser object model 瀏覽器對(duì)象模型蝴簇,里面提供了一些屬性和方法,可以讓我們操作瀏覽器匆帚。
1 導(dǎo)入JS
1.1 三種常見(jiàn)導(dǎo)入
1.1.1 行內(nèi)導(dǎo)入JS(慎重:不安全)
<div onclick="alert('hello world')"></div>
1.1.2 內(nèi)嵌式
<script>
alert('hello world')
</script>
1.1.3 外鏈?zhǔn)?/h3>
// 新建一個(gè)js文件
<script src="./js/demo.js"></script>
// or
<script src="./js/demo.js" type="text/javascript"></script>
1.2 內(nèi)嵌與外鏈不能同時(shí)操作
內(nèi)嵌導(dǎo)入和外鏈導(dǎo)入不能合并在一起熬词,如果當(dāng)前是外鏈導(dǎo)入的,那么在script腳本塊找那個(gè)編寫(xiě)的所有代碼都不會(huì)被執(zhí)行吸重。
<script src="./js/demo.js">
alert('hello world')
</script>
1.3 位置編寫(xiě)位置
我們一般性會(huì)把css放在body的上面互拾,把js放在body末尾(約定速成的規(guī)范)
但是如果放在了標(biāo)簽前面那么將如何處理?
頁(yè)面加載完所有資源之后執(zhí)行操作
// 新建一個(gè)js文件
<script src="./js/demo.js"></script>
// or
<script src="./js/demo.js" type="text/javascript"></script>
內(nèi)嵌導(dǎo)入和外鏈導(dǎo)入不能合并在一起熬词,如果當(dāng)前是外鏈導(dǎo)入的,那么在script腳本塊找那個(gè)編寫(xiě)的所有代碼都不會(huì)被執(zhí)行吸重。
<script src="./js/demo.js">
alert('hello world')
</script>
我們一般性會(huì)把css放在body的上面互拾,把js放在body末尾(約定速成的規(guī)范)
但是如果放在了標(biāo)簽前面那么將如何處理?
頁(yè)面加載完所有資源之后執(zhí)行操作
在js中
window.onload=function(){
}
在jq中
$(document).ready(function(){
})
window.addEventListener('load',function(){},false);
// ie8以下
window.attachEvent('onreadystatechange',function(){
})
2 JS常用的輸出方式
2.1.彈窗輸出
2.1.1 alert
- 在瀏覽器中彈出一個(gè)提示框(提供確定按鈕,點(diǎn)擊確定彈窗消失)
- 使用alert彈窗信息嚎幸,提示的內(nèi)容最后都會(huì)轉(zhuǎn)換成字符串(調(diào)用了toSring這個(gè)方法)
alert(1)
alert({name:'wjw'}) //=> '[object Object]'
alert([13,14]) //=> '12,13'
2.1.2 confirm
- 在alert基礎(chǔ)上增加了讓用戶選擇的操作(提供兩個(gè)按鈕:確定和取消)
- 當(dāng)用戶點(diǎn)擊確定按鈕的時(shí)候颜矿,我們接收到的結(jié)果是true,點(diǎn)擊是取消按鈕我們接受到的結(jié)果是false嫉晶,此后我們可以根據(jù)結(jié)果來(lái)處理即可
var wjw = confirm("are you sure");
alert(wjw);
2.1.3 prompt
- 在confirm 基礎(chǔ)上增加讓用戶增加輸入的效果
- 用戶點(diǎn)擊取消按鈕骑疆,我們獲取到的結(jié)果是null,如果用戶點(diǎn)擊是確定按鈕田篇,我們將獲取用戶輸入的信息
- 在真實(shí)的項(xiàng)目中,一般性會(huì)使用二次封裝的彈窗封断,不會(huì)使用這種彈窗
var flag = prompt("are you sure");
alert(flag)
2.2 控制臺(tái)輸出
控制臺(tái)輸出斯辰,方便開(kāi)發(fā)調(diào)試
2.2.1 console
- 在控制臺(tái)輸出舶担,優(yōu)勢(shì)不會(huì)轉(zhuǎn)換數(shù)據(jù)類型坡疼,輸出什么格式的數(shù)據(jù)都可以
console.log({name:'wjw'});
console.dir() //比log輸出更加詳細(xì)一些
console.table //把json數(shù)據(jù)展示成一個(gè)表格
3 JS定義值
語(yǔ)法
ECMAScript 的語(yǔ)法大量借鑒了 C 及其他類 C 語(yǔ)言(如 Perl 和 Java)的語(yǔ)法。
區(qū)分大小寫(xiě)
3.1 注釋
// 單行注釋
/*
* 這是一個(gè)多行
* (塊級(jí))注釋
*/
3.2 嚴(yán)格模式
嚴(yán)格模式
ES5 引入了嚴(yán)格模式的概念衣陶,在嚴(yán)格模式下柄瑰,ES3 中的一些不確定行為將得到處理,而且隊(duì)某些不安全的操作也會(huì)拋出錯(cuò)誤剪况。要在整個(gè)腳本中啟用嚴(yán)格模式教沾,可以在頂部添加如下代碼:<br />這行代碼看起來(lái)像是字符串,而且也沒(méi)有賦值給任何變量译断,但其實(shí)它是一個(gè)編譯指
示(pragma)授翻,用于告訴支持的JavaScript引擎切換到嚴(yán)格模式。在函數(shù)內(nèi)部的上方包含這條編譯指示孙咪,也可以指定函數(shù)在嚴(yán)格模式下執(zhí)行:
function doSomething(){
"use strict"; //函數(shù)體
}
3.3 變量堪唐、常量
變量是可以變得
常量是不可變的
3.3.1變量
- 變量其實(shí)只是一個(gè)無(wú)意義的名字,它所代表的意義都是其存儲(chǔ)的那個(gè)值
- 讓原有的num變量存儲(chǔ)的值修改為13(變量只能代表一值)
js定義變量的方法
// var 變量名 = 值;
var num = 12;
var name = 'wjw'
3.3.1常量
- 任何一個(gè)具體的數(shù)據(jù)都是常量翎蹈,例如12是個(gè)常量
- 和變量累死淮菠,我們?cè)O(shè)置一個(gè)常量(也就是一個(gè)名字),給其存儲(chǔ)一個(gè)值荤堪,但是這個(gè)存儲(chǔ)的值不能修改
const num = 12;
3.4 JS中命名規(guī)范
- JS中嚴(yán)格區(qū)分大小寫(xiě)
var test = 'wjw';
var Test = 'wjh';
console.log(test);
// 輸出test
- 遵循國(guó)際命名規(guī)則"駝峰命名法"
第一個(gè)單詞首字母小寫(xiě)合陵,其余每一個(gè)有意義單詞首字母大寫(xiě)
var studentInfo; // 學(xué)生信息
// 所見(jiàn)即所得
// 例子:
/*
* info : information 信息
* init : initlization 初始化
* add/insert/create 增加插入創(chuàng)建
* remove/rm/clear/del/delete 刪除
* update 修改
* get/query/select : 查詢獲取
*/
- 命名的時(shí)候可以使用$、_澄阳、數(shù)字拥知、字母,但是數(shù)字不能作為名字的第一位
var student_info;
var $xxx; //=> 一般都是應(yīng)用jq獲得到的值
var _xxx; //=> 一般這樣的情況代表變量是一個(gè)局或者公共的變量
- JS中很多字都是有特殊含義的碎赢,我們這些詞低剔,叫做關(guān)鍵詞;現(xiàn)在沒(méi)有特殊含義揩抡,以后可能會(huì)作為關(guān)鍵的户侥,我們叫做保留字;二關(guān)鍵詞和保留字不可以隨便用來(lái)命名峦嗤;
<br />
4 JS數(shù)據(jù)類型
4.1 數(shù)據(jù)類型
4.1.1 基本數(shù)據(jù)類型(值類型)
- Number 數(shù)字
- String 字符串
- 單引號(hào)包裹起來(lái)的都是字符串(單雙號(hào)沒(méi)有區(qū)別)
- Boolean 布爾
- true false => 布爾值只有兩個(gè)值
- null 空對(duì)象指針
- undefined 未定義
4.1.2 引用數(shù)據(jù)類型
- {} 普通對(duì)象
- [] 數(shù)組
- /^$/ 正則
- ...
4.1.3 function數(shù)據(jù)類型
- funciotn fn (){}
4.2 數(shù)據(jù)類型檢查
- typeof
- 用來(lái)檢測(cè)數(shù)據(jù)類型的運(yùn)算符
- instanceod
- 檢測(cè)某個(gè)實(shí)例是否屬于這個(gè)類
- constructor
- 獲取當(dāng)前實(shí)例的構(gòu)造器
- Object prototype.toSting.call()
- 獲取當(dāng)前實(shí)例的所屬類信息
4.2.1 typeof
操作符
typeof 是用來(lái)檢測(cè)給定變量的數(shù)據(jù)類型的操作符蕊唐。對(duì)一個(gè)值使用 typeof 操作符可能返回下列某個(gè)字符串:
"undefined"
"boolean"
"string"
"number"
"object" // 如果這個(gè)值是對(duì)象或者null "function"
4.3 布爾值
Boolean()
- 把其他數(shù)據(jù)類型的值轉(zhuǎn)化為布爾類型
- 只有0、Nan烁设、null替梨、undefined這五個(gè)數(shù)據(jù)值轉(zhuǎn)換為布爾類型的false钓试,其余的都會(huì)變成true
嘆號(hào)在JS中海油一個(gè)作用:取反,先把值轉(zhuǎn)換為布爾類型副瀑,然后再去取反
!!
在嘆號(hào)取反的基礎(chǔ)上取反弓熏,取反兩次相當(dāng)于沒(méi)有操作,但是卻已經(jīng)其他類型值轉(zhuǎn)化為布爾類型了糠睡,和Boolean是相同的效果
4.4 字符串
在JS中單引號(hào)和雙引號(hào)包起來(lái)的都是字符串
12 - > number
'12' -> string
'[12,23]' -> string
4.4.1 toString()
第一種是使用幾乎每個(gè)值都有的 toString()方法挽鞠。多數(shù)情況下,調(diào)用 toString() 方法不必傳遞參數(shù)狈孔,但在調(diào)用數(shù)值的 toString()方法時(shí)信认,可以傳遞一個(gè)參數(shù):輸出數(shù)值的基數(shù)。默認(rèn)情況下均抽,toString() 方法以十進(jìn)制格式返回?cái)?shù)值的字符串表示嫁赏。而通過(guò)傳遞基數(shù),toString() 可以輸出二進(jìn)制油挥、八進(jìn)制潦蝇、十六進(jìn)制等。
var num = 10;
alert(num.toString()); // "10"
alert(num.toString(2)); // "1010"
alert(num.toString(8)); // "12"
alert(num.toString(10)); // "10"
alert(num.toString(16)); // "A"
常用方法<br />4.5 number數(shù)字
0 12-22 12.5 js中多增加了一個(gè)number類型的數(shù)據(jù)NaN typeof NaN -> Number
var intNum = 55; // 十進(jìn)制整數(shù) var octalNum1 = 070; // 八進(jìn)制的56
var octalNum1 = 079; // 無(wú)效的八進(jìn)制數(shù)值——解析為79
var octalNum1 = 08; // 無(wú)效的八進(jìn)制數(shù)值——解析為8
var hexNum1 = 0xA; // 十六進(jìn)制的10
var hexNum2 = 0x1F; // 十六進(jìn)制的31
注意深寥,八進(jìn)制字面量在嚴(yán)格模式下是無(wú)效的攘乒,會(huì)導(dǎo)致拋出錯(cuò)誤。
4.5.1 數(shù)值范圍
ECMAScript 能夠表示的最小數(shù)值保存在 Number.MIN_VALUE 中——在多數(shù)瀏覽器中翩迈,這個(gè)值是 5e-324持灰;能夠 Number.MAX_VALUE 中——在大多數(shù)瀏覽器中,這個(gè)值是1.7976931348623157e+308负饲。如果某次計(jì)算的結(jié)果得到了一個(gè)超過(guò)JavaScript 數(shù)值范圍的值堤魁,那么這個(gè)數(shù)值將會(huì)自動(dòng)轉(zhuǎn)換為 Infinity 值,如果這個(gè)數(shù)值是負(fù)數(shù)返十,則會(huì)轉(zhuǎn)換成 -Infinity(負(fù)無(wú)窮)妥泉,如果這個(gè)數(shù)值是正數(shù),則會(huì)轉(zhuǎn)換成Infinity(正無(wú)窮)洞坑。要確定一個(gè)數(shù)值是不是有窮的盲链,可以使用 isFinite() 函數(shù)。
4.5.2 NaN
- not a numer : 不是一個(gè)數(shù)迟杂,但是屬于number類型
- NaN == NaN : false , NaN 和任何其他值都不相等
4.5.3 isNaN()
- 用來(lái)檢測(cè)當(dāng)前這個(gè)值是否是非有效數(shù)字刽沾,如果不是有效數(shù)字,檢測(cè)的結(jié)果是true , 反之是有效數(shù)字則為false
isNaN(0) // ->false
isNaN(NaN) // ->true
- 當(dāng)我們使用isNaN檢測(cè)值的時(shí)候排拷,檢測(cè)的值不是number類型的侧漓,瀏覽器默認(rèn)的吧值先轉(zhuǎn)換為number類型,任何再去檢測(cè)
isNaN('12') //->false
4.5.4 Number()
- 把其他數(shù)據(jù)類型值轉(zhuǎn)化成number類型的值
Number('12') // -> 12
Number('12px') // ->NaN
// 在使用Number轉(zhuǎn)換的時(shí)候只要字符串中出現(xiàn)任何一個(gè)非有效數(shù)字字符监氢,最后的結(jié)果都是NaN
Number(true) //-> 1
Number(false) //-> 0
Number(null) // -> 0
Number(undefined) //->NaN
- 把引用數(shù)據(jù)類型轉(zhuǎn)換成number布蔗,首先需要吧引用數(shù)據(jù)類型轉(zhuǎn)為字符串(toString)藤违,在把字符串轉(zhuǎn)換為number即可
Number([]) // -> ""
Number([12]) // -> 12
Number([12,13]) // -> 12,13 (,是非有效字符) -> NaN
Number({age:12}) // ->NaN
Number({}) // -> NaN
4.5.5 pareInt
- 也是吧其他數(shù)據(jù)類型值轉(zhuǎn)換為number,和Number方法在處理字符串的時(shí)候有所區(qū)別
Number('12px') // -> NaN
parseInt('12px') // -> 12
- 提取規(guī)則:從左到右依次查找有效數(shù)字字符纵揍,知道遇到非有效數(shù)字字符為止(不管后端是否還有顿乒,都不找了)
parseInt('12px13') // -> 12
4.5.6 數(shù)值轉(zhuǎn)換
處理整數(shù)最常用的還是 parseInt() ,它會(huì)忽略字符前面的空格泽谨,直到找到第一個(gè)非空格字符璧榄。如果第一個(gè)字符不是數(shù)字字符或者負(fù)號(hào),parseInt() 就會(huì)返回 NaN隔盛;也就是說(shuō)犹菱,用 parseInt() 轉(zhuǎn)換空字符串會(huì)返回 NaN 。如果第一個(gè)字符是數(shù)字字符吮炕, parseInt() 會(huì)繼續(xù)解析第二個(gè)字符,直到解析完所有后續(xù)字符或者遇到了一個(gè)非數(shù)字字符访得。如果字符以“0x”開(kāi)頭且后面跟數(shù)字字符龙亲,會(huì)被解析為 16 進(jìn)制整數(shù);<br />以“0”開(kāi)頭且后面跟數(shù)字字符悍抑,會(huì)被解析為 8 進(jìn)制整數(shù)鳄炉。下面給出一些例子:
var num1 = parseInt("1234blue"); // 1234
var num2 = parseInt(""); // NaN
var num3 = parseInt("0xA"); // 10(十六進(jìn)制)
var num4 = parseInt(22.5); // 22
var num5 = parseInt("70"); // 70
var num6 = parseInt("0xf"); // 15(十六進(jìn)制)
4.5.7 pareFloat
- 在pareInt的基礎(chǔ)上可以識(shí)別小數(shù)點(diǎn)
pareInt('12.5px') -> 12
pareFloat('12.5px') -> 12.5
4.6 null 和undefined
- null : 空,沒(méi)有
- undefined :未定義搜骡,沒(méi)有
- "" : 空字符串拂盯,沒(méi)有
- 0: 也可以理解為沒(méi)有
4.6.1 空字符串和null的區(qū)別
- 都是去去種樹(shù)
- 空字符串屬于去挖了個(gè)坑,但是沒(méi)有種任何東西
- null屬于連坑都沒(méi)挖
- 空字符串相對(duì)于null來(lái)說(shuō)開(kāi)辟了內(nèi)存地址记靡,消耗了那么一丟丟的性能
4.6.2 null和undefined的區(qū)別
- null一般都是暫時(shí)沒(méi)有谈竿,預(yù)期中以后會(huì)有的(可能以后也沒(méi)有達(dá)到預(yù)期),在js中null都是手動(dòng)先賦值為null摸吠,后期我們?cè)诮o其賦具體值
- undefined:完全沒(méi)有預(yù)料之內(nèi)的
4.7 Object 對(duì)象
ECMAScript 中的對(duì)象其實(shí)就是一組數(shù)據(jù)和功能的集合空凸。對(duì)象可以通過(guò)執(zhí)行 new 操作符后跟要?jiǎng)?chuàng)建的對(duì)象類型的名稱來(lái)創(chuàng)建。而創(chuàng)建 Object 類型的實(shí)例并為其添加屬性和(或)方法寸痢,就可以創(chuàng)建自定義對(duì)象呀洲,如下所示:
var o = new Object();
每一個(gè)對(duì)象都是由零到多組 屬性名(key鍵):屬性值(value值) 組成的,或者說(shuō)有多組鍵值對(duì)組成的,每一組鍵值對(duì)中間用逗號(hào)分隔
4.7.1 屬性
描述這個(gè)對(duì)象特點(diǎn)特征的
var obj ={name:'wjw',age:8};
4.7.2 獲取
某個(gè)屬性名對(duì)應(yīng)的屬性值或者數(shù)字格式的
obj.name
obj['name']
4.7.3 存儲(chǔ)
屬性值可以是任何數(shù)據(jù)類型
- 對(duì)象名.屬性名:忽略屬性名的單雙引號(hào)
- 對(duì)象名[屬性名]:不能忽略單雙引號(hào)
// 如果屬性名是數(shù)字如何操作
obj.0 語(yǔ)法不支持
obj[0] / obj['0'] 兩種都支持
如果操作的屬性名在對(duì)象中不存在啼止,獲取的結(jié)果是undefined
obj.sex // ->undefined
4.7.4 設(shè)置/修改
一個(gè)對(duì)象的屬性名是不能重復(fù)的(唯一性)道逗,如果之前存在就是修改屬性值的操作,反之不存在就是新的設(shè)置屬性的操作
obj.sex = '男';
obj['age'] = 9;
4.7.5 刪除
假刪除:讓其屬性賦值為null献烦,但是屬性還是對(duì)象
obj.sex = null;
真刪除:把整個(gè)屬性都在對(duì)象中暴力移出
delete obj.sex
4.8 基本數(shù)據(jù)類型 和 引用數(shù)據(jù)類型的區(qū)別
JS是運(yùn)行在瀏覽器中的(內(nèi)核引擎)滓窍,瀏覽器會(huì)為JS提供賴以生存的環(huán)境(提供給js代碼執(zhí)行的環(huán)境)=> 全局作用域window(global)
var a = 12;
var b = a; // 把A變量存儲(chǔ)的值賦值給B
b = 13;
console.log(a);
var n ={name:'wjh'};
var m = n;
m.name = 'wjw'
console.log(n.name)
- 基本數(shù)據(jù)類型是按值操作的:基本數(shù)據(jù)類型的賦值的時(shí)候,是直接把值賦值給變量即可
- 引用數(shù)據(jù)類型是按照空間地址(引用地址)來(lái)操作的: var n = {name:'wjw'}
- 先創(chuàng)建一個(gè)變量n
- 瀏覽器首先會(huì)吧開(kāi)辟一個(gè)新的存儲(chǔ)控件(內(nèi)存控件)仿荆,目的是吧對(duì)象中需要存儲(chǔ)的內(nèi)容(鍵值對(duì))分別的存儲(chǔ)在這個(gè)空間中贰您,為了方便后期找到這個(gè)空間坏平,瀏覽器給空間設(shè)定一個(gè)地址(16進(jìn)制)
- 把空間的地址賦值給了變量
4.9 function數(shù)據(jù)類型
函數(shù)數(shù)據(jù)類型也要按照引用地址來(lái)操作的
函數(shù):具備一定功能的方法
// => 創(chuàng)建函數(shù):
function 函數(shù)名(){
//=> 函數(shù)體:實(shí)現(xiàn)某一個(gè)功能的具體JS代碼
}
// => 執(zhí)行函數(shù):相當(dāng)于使用洗衣機(jī)洗衣服(如果函數(shù)只創(chuàng)建了,但是沒(méi)有去執(zhí)行锦亦,函數(shù)沒(méi)有任何的意義)
// 函數(shù)名()
function fn(){
console.log(1+1);
}
fn; // => 輸出函數(shù)本身
fn(); // => 把函數(shù)執(zhí)行(吧函數(shù)體重實(shí)現(xiàn)功能的代碼執(zhí)行)
形參:形式參數(shù)(變量)舶替,函數(shù)的入口<br />當(dāng)我們創(chuàng)建一個(gè)函數(shù)想要實(shí)現(xiàn)個(gè)功能的時(shí)候,發(fā)現(xiàn)有一些材料不清楚杠园,只有當(dāng)函數(shù)運(yùn)行的時(shí)候顾瞪,別人傳遞給我,我才知道抛蚁,此時(shí)我們就需要設(shè)定入口,讓用戶執(zhí)行的時(shí)候通過(guò)入口把值把我們
function fn(num1,num2){
console.log(num1+num2)
}
// 實(shí)參:函數(shù)執(zhí)行傳遞給函數(shù)的具體值就是實(shí)參
fn(1,2);
fn(10,20);
4.10 數(shù)據(jù)類型轉(zhuǎn)換
把其他數(shù)據(jù)類型轉(zhuǎn)換為number類型<br />-> isNaN陈醒、Number、pareInt瞧甩、parseFloat<br />-> 在進(jìn)行數(shù)據(jù)加減乘除數(shù)學(xué)運(yùn)算的時(shí)候
// true -> 1 false->0
// ''->0 '12'->12 '12px'->NaN/12
// '小伙子'->NaN
// null -> 0
// undefined-> NaN
{} /^$/ function() ->NaN
[]
[12]->'12'->12
['12,13']->'12,23'->NaN
// => 引用數(shù)據(jù)類型轉(zhuǎn)換為數(shù)字
// 通過(guò)toString方法把數(shù)組轉(zhuǎn)換為字符串钉跷,然后在調(diào)用Number轉(zhuǎn)換為數(shù)字
4.10.1 JS中的數(shù)據(jù)運(yùn)算
- +、-肚逸、*爷辙、/加減乘除
- 除了加法有特殊性,其余的運(yùn)算符都是數(shù)學(xué)運(yùn)算朦促,也是遇到非數(shù)字類型膝晾,需要把其轉(zhuǎn)換為number再運(yùn)算
1-'1' -> 0
10*null -> 0
10/undefined -> NaN
10*[10]->100
4.10.2 加法的特殊性:
- 在遇到字符串的時(shí)候,+不是數(shù)學(xué)運(yùn)算务冕,而是字符串拼接血当,只要不遇到字符串就是數(shù)學(xué)運(yùn)算
1+'1' -> '11'
null+'1' -> ‘null1’
- 字符串拼接:是把其它的值轉(zhuǎn)換為字符串然后再拼接(toString)
- 其它數(shù)據(jù)類型的toString是直接的把值用單(雙)引號(hào)包起來(lái)極客,只有對(duì)象的特殊性禀忆,對(duì)象的有特殊性臊旭,對(duì)象.toStirng==='[Object Object]
4.10.3 將其它數(shù)據(jù)類型轉(zhuǎn)換為布爾類型
- Boolean、油湖!巍扛、!乏德!
- 在條件判斷的時(shí)候撤奸、也是轉(zhuǎn)換為布爾類型,然后驗(yàn)證條件的真假
- 只有0喊括、NaN胧瓜、空字符串、null郑什、undefined五個(gè)轉(zhuǎn)換為false府喳、其余的都是轉(zhuǎn)換為true
[] -> true
-1 -> true
if(box){
// => 首先把box變量存儲(chǔ)的值獲取到,轉(zhuǎn)化為布爾類型蘑拯,如果為true條件成立钝满,反之不成立
}
if(3+'3px'){
// 條件成立: 3 + '3px' = '33px'
}
if(3-'3px'){
// 條件不成立: 3-'3px' = NaN
}
4.10.4 在使用==進(jìn)行比較的時(shí)候
在使用==進(jìn)行比較的時(shí)候兜粘,如果左右兩邊的數(shù)據(jù)不相同,瀏覽器默認(rèn)轉(zhuǎn)換為相同的類型弯蚜,然后在比較('==='不會(huì)這樣操作)
// 對(duì)象和對(duì)象: 應(yīng)用數(shù)據(jù)類型比較的空間地址不一樣孔轴,不是一個(gè)空間
[] == [] -> false
var a ={}
var b = a;
a==b -> true
4.10.5 對(duì)象和數(shù)字:吧對(duì)象轉(zhuǎn)換成數(shù)字
[]== 0 -> true
({})=== NaN -> false
NaN和自己不相等和其它任何值都不相等
4.10.6 對(duì)象和字符串:把兩邊都轉(zhuǎn)換為數(shù)字比較的
[]==='' -> true
4.10.7 對(duì)象和布爾值:把兩邊都轉(zhuǎn)換成數(shù)字
[]==true -> 0==1 ->false
[]==false -> 0==0 ->true
![]==false -> ![] ->把數(shù)組變成為布爾在取反=false
false=false -> true
字符串和數(shù)字:字符串轉(zhuǎn)換為數(shù)字<br />字符串和布爾:都轉(zhuǎn)為數(shù)字<br />布爾和數(shù)字:布爾轉(zhuǎn)換為數(shù)字
規(guī)律:兩個(gè)等于號(hào)比較,左右兩邊數(shù)字值的類型不一樣碎捺,瀏覽器會(huì)吧兩邊的類型都轉(zhuǎn)換為數(shù)字然后再比較路鹰,但是null和undefined除外<br />null==undefined -> true<br />null===undefined -> false<br />null 和 undefined 和其它任何都不相等<br />null==0 -> false null以及undefined和其它任何值都不相等
5 JS中常見(jiàn)的操作的語(yǔ)句
5.1 if、else if 收厨、else
判斷操作語(yǔ)句
if(條件1){
//=>條件1成立執(zhí)行的操作
}else if(條件2){
//=>上面條件不成立晋柱,條件2成立,執(zhí)行的操作
}
...
else{
// => 以上條件都不成立執(zhí)行的操作
}
如果好幾個(gè)條件都成立了诵叁,只吧第一個(gè)成立的條件執(zhí)行雁竞,后面成立的條件忽略不管<br />條件:
A==B、A!=B黎休、A>B浓领、A<B
if(A){} // 先把A轉(zhuǎn)換為布爾類型,判斷真假以此來(lái)決定是否成立
//否成立
if(A>B&&A<10){} //只有兩個(gè)小條件都是真势腮,整體條件為真
if(A>B||A<10){} // 只要其中一個(gè)小條件成立,整體條件是真
BAT 面試題
var num = parseFloat('width:12.5px');
if(num==12.5){ // =>NaN
alert(12.5);
}else if(num==NaN){ // NaN!=NaN
alert(NaN);
}else if(typeof num=='number'){ //
alert(0)
}else{
alert("啥也不是")
}
5.2 三元運(yùn)算符
條件漫仆?條件成立執(zhí)行:條件不成立執(zhí)行
if(條件){}else : 三元運(yùn)算符就是這種簡(jiǎn)單if..else..的另一種寫(xiě)法
var num = 10;
if(num>5&&num<10){
num++;//累加1
}else{
num--;
}
// 修改成為三元運(yùn)算符,如果條件成立或者不成立的某一種情況并不需要什么處理
// 我們空著語(yǔ)法不符合捎拯,我們使用null、undefined盲厌、void 0(就是undefined)占位就可以
num>5&&num<10?num++:num--;
var num = 10;
if(num>5 && num<10){
num++;
break;/continue;/return;
}
// => 修改成為三元運(yùn)算符
// 在三元運(yùn)算符的操作中不能出現(xiàn)break署照、continue、return這樣的關(guān)鍵詞吗浩,所以我們無(wú)法用三目代替if建芙、else
num>5 && num<10?
(num++,return):null;
5.3 swith case
swith case應(yīng)用于if、else中一個(gè)變量在不同值情況下的不同操作
var num =10;
switch(num){
//switch后面小括號(hào)中存放的是一個(gè)值(一般我們都寫(xiě)變量;把變量存儲(chǔ)的值拿來(lái)用懂扼,有時(shí)候也可能是一個(gè)計(jì)算)
case 1:
// case后面放的都是值禁荸,目的驗(yàn)證switch后面的值和哪一種case后面的值相等,相等的進(jìn)行對(duì)應(yīng)的處理
...
break;
// 每一種case借宿后都要加break借宿當(dāng)前的判斷
case 10:
...
break;
default:
// switch后面的值和每一種case情況對(duì)應(yīng)的值都不相等阀湿,執(zhí)行最后的default赶熟,類似于false
...
}
案例分析
var num = 5;
switch(num%2){//=>先把取余操作進(jìn)行運(yùn)算,拿運(yùn)算結(jié)果case比較
case 0:
num++;
break; //不加break陷嘴,不管后面的條件是夠成立映砖,都會(huì)繼續(xù)向下執(zhí)行,知道遇到break為止
// 不加break灾挨,就可以實(shí)現(xiàn)||這樣的操作
case: 2-1: //case后面也應(yīng)該是值邑退,此處先把2-1計(jì)算竹宋,把計(jì)算的結(jié)果和switch值比較
num--;
// 最后一項(xiàng)可以不加break,不加也能跳出判斷
break;
}
num%2:讓num存儲(chǔ)的值除以2去余數(shù)(0或者1)
swich case 中的比較實(shí)用的"==="
- =:賦值地技,等號(hào)左邊是變量蜈七,右邊是值
- ==:比較,如果左邊兩邊的類型不一樣乓土,瀏覽器默認(rèn)轉(zhuǎn)換為一樣的然后再進(jìn)行比較 '6'==6 => 6==6 =>true
- ===:絕對(duì)相等擎宝,不僅要求值一樣,并且類型也要完全一樣
5.4 循環(huán)操作語(yǔ)句
循環(huán)著隆,重復(fù)做一件事情
for(設(shè)置循環(huán)起始值凿歼;設(shè)置循環(huán)執(zhí)行的條件;步長(zhǎng)累加){
// 循環(huán)體:重復(fù)做的事情都是在循環(huán)體重
}
- 設(shè)置初始值
- 驗(yàn)證條件
- 條件成立食磕,執(zhí)行循環(huán)體:不成立尽棕,循環(huán)借宿
- 步長(zhǎng)累加
for(;i<5;;){
consloe.log(i);
//沒(méi)有步長(zhǎng)累加,我們的i永遠(yuǎn)是0彬伦,循環(huán)條件永遠(yuǎn)成立“死循環(huán)”;
//項(xiàng)目中不能出現(xiàn)死循環(huán)滔悉,一旦出現(xiàn),循環(huán)下面的事情都做不了
}
5.4.1 continue
結(jié)束本輪循環(huán),繼續(xù)執(zhí)行下一輪:循環(huán)體重continue后面的代碼都不會(huì)在執(zhí)行单绑,它會(huì)直接的去執(zhí)行步長(zhǎng)回官,然后進(jìn)行下一輪
for(var i=0;i<5;i+=2){
console.log(i)
continue;
}
5.4.2 break
結(jié)束整個(gè)循環(huán):循環(huán)體重一旦遇到break首先后面代碼不執(zhí)行了,而且步長(zhǎng)累加也不執(zhí)行了搂橙,循環(huán)都結(jié)束了
for(var i=0;i<5;i+=2){
console.log(i)
break;
}
BAT面試題
for(var i=1;i<10;i+=2){
if(i<5){
i++;
continue;
}else{
i+=3;
break;
}
console.log(i)
}
console.log(i) // =>10
5.4.3 for in
用來(lái)遍歷(循環(huán))對(duì)象鍵值對(duì)的
- var key;var attr(attribute);
- 對(duì)象中有多少鍵值對(duì)歉提,我們的for in 循環(huán)遍歷多少次(多少次)
- 第一次循環(huán)key這個(gè)遍歷存儲(chǔ)的都是當(dāng)前循環(huán)這個(gè)組鍵值隊(duì)的屬性名
- key存儲(chǔ)的值都是字符串格式的(不管屬性名是否為數(shù)字)
- 在for in 循環(huán)的遍歷時(shí)候,大部分瀏覽器都是先把對(duì)象中的鍵值對(duì)進(jìn)行排序(把數(shù)字屬性的排在前面区转,并且排列的時(shí)候安卓數(shù)字由小達(dá)大排列),其次在把非數(shù)字的屬性名按照之前編寫(xiě)的順序苔巨,循環(huán)的時(shí)候按照重新排列循序一次遍歷(小數(shù)算作字母不要做數(shù)字)
var obj = {name:wjw,age:8,0:'wjh',3:'ylp',1:'cx'}
for(var key in obj){
console.log('ok')
// key 屬性名 string
console.log(obj.key)
//獲取obj中key這個(gè)屬性對(duì)應(yīng)的值 ->undefined <=> obj['key']
console.log(obj[key]);
//->每一次循環(huán)把key變臉存儲(chǔ)的值(當(dāng)前遍歷的屬性名)獲取到放在中括號(hào)中,獲取obj對(duì)應(yīng)的屬性值
}
for(var key in obj){
if(obj.hasOwnProperty(key)){
}
}
6 JS的DOM獲取節(jié)點(diǎn)
DOM:document object model 文檔對(duì)象模型废离,提供一些屬性和方法可以讓我們?nèi)ゲ僮鱀OM元素
6.1 節(jié)點(diǎn)介紹
node 節(jié)點(diǎn)侄泽,瀏覽器默認(rèn)在一個(gè)html頁(yè)面中的所有內(nèi)容都是節(jié)點(diǎn)(包括標(biāo)簽、注解蜻韭、文字文本等)
- 元素節(jié)點(diǎn):HTML標(biāo)簽
- 文本節(jié)點(diǎn):文字內(nèi)容(大部分瀏覽器會(huì)把空格和換行也當(dāng)做文本節(jié)點(diǎn))
- 注解節(jié)點(diǎn)
- document文檔節(jié)點(diǎn)
元素節(jié)點(diǎn)
- nodeType:1
- 屬性含有某個(gè)節(jié)點(diǎn)的名稱
- nodeName: 大寫(xiě)標(biāo)簽名(在部分瀏覽器的怪異模式下悼尾,我們寫(xiě)的標(biāo)簽名是小寫(xiě),它獲取的就是小寫(xiě)...)
- 對(duì)于元素節(jié)點(diǎn)湘捎,因?yàn)楸旧聿恢苯影谋揪骰恚詎odeValue是不可用的。當(dāng)然你也可以在示例中自己寫(xiě)試試看有什么結(jié)果出現(xiàn)窥妇。
- 對(duì)于文本節(jié)點(diǎn)舷胜,nodeValue=文本值
- 對(duì)于屬性節(jié)點(diǎn),nodeValue=屬性值
- nodeValue:null
- 對(duì)于元素節(jié)點(diǎn),nodeType=1
- 對(duì)于文本節(jié)點(diǎn)烹骨,nodeType=3
- 對(duì)于屬性節(jié)點(diǎn)翻伺,nodeType=2
- 對(duì)于注釋元素,nodeType=8
- 對(duì)于文檔元素沮焕,nodeType=9
[curEle].tagName:獲取當(dāng)前元素的標(biāo)簽名(獲取的標(biāo)簽名一般都是大寫(xiě))
文本節(jié)點(diǎn)
nodeType:3<br />nodeName:#text<br />nodeValue:文本內(nèi)容
注釋節(jié)點(diǎn)
nodeType:8<br />nodeName:#comment<br />nodeValue:注釋內(nèi)容
文檔節(jié)點(diǎn)
nodeType:9<br />nodeName:#document<br />nodeValue:null
<-- div#box>(ul>li{0$}*3)+div{內(nèi)容$}*3-->
<div id="box">
<ul>
<li>01</li>
<li>02</li>
<li>03</li>
</ul>
<div>內(nèi)容1</div>
<div>內(nèi)容2</div>
<div>內(nèi)容3</div>
</div>
6.2 獲取dom元素
6.2.1 document.getElementById 一個(gè)元素
- 此方法的上下文只能document
- 一個(gè)html頁(yè)面中元素的id理論上是不能重復(fù)的,如果頁(yè)面中ID重復(fù)了吨岭,我們獲得結(jié)果第一個(gè)id對(duì)應(yīng)的元素對(duì)象
- 在ie7更低的版本瀏覽器中,會(huì)把表單元素的name值當(dāng)做id來(lái)識(shí)別使用(項(xiàng)目中盡量不要讓表單的name和其他元素的id相同)
- 如果我們把js放在結(jié)構(gòu)的下面峦树,我們可以直接使用id值獲取這個(gè)元素(不需要通過(guò)getElementById獲取)辣辫,而且這種方式會(huì)把頁(yè)面中所有id是他的元素都獲取到(元素對(duì)象,或者集合) => 不推薦
<div id="box1"></div><div id="box2"></div><div id="box1"></div>
<script>
console.log(box1) // -> [div#box1, div#box1, box1: div#box1]
</script>
<input id="myInput" type="text" size="20"/><br />
<script>
var x=document.getElementsByName("myInput");
</script>
6.2.2 document.getElementClassName 元素集合
- 上下文是可以自己來(lái)指定
- 獲取到的結(jié)果是一個(gè)元素集合(類數(shù)組集合)
- 獲取的結(jié)果是集合魁巩,哪怕集合中只有一項(xiàng)急灭,我們想要操作的是這一項(xiàng)(元素對(duì)象),需要先從集合中獲取出來(lái)谷遂,然后再操作
- 但是真實(shí)的項(xiàng)目中我們經(jīng)常會(huì)通過(guò)樣式類名獲取元素葬馋,getElementClassName這個(gè)方法在ie6-8不兼容的
<input name="myInput" type="text" size="20"/><br />
<script>
var x=document.getElementsByName("input");
</script>
var bodyBox = document.getElementsByTagName('body');
bodyBox[0].getElementsByTagName('div');
6.2.3 document.getElementsTagName 元素集合
<input name="myInput" type="text" size="20"/><br />
<script>
var x=document.getElementsByName("input");
</script>
6.2.4 document.getElementsByName 節(jié)點(diǎn)集合
通過(guò)元素的NAME屬性值獲取一組元素(類數(shù)組:節(jié)點(diǎn)集合NodeList)
他的上下文只能是document
- IE瀏覽器只能識(shí)別表單元素的name屬性值,所以我們這個(gè)方法一般都用來(lái)操作表單元素的
- 獲取html獲得body的元素對(duì)象
<input name="myInput" type="text" size="20"/><br />
<script>
var x=document.getElementsByName("myInput");
</script>
6.2.5 domcument.domcumentElement 獲取整個(gè)html的對(duì)象
document.documentElement.clientWidth||document.body.clientWidth
// 獲取當(dāng)前瀏覽器可視區(qū)域的寬度(當(dāng)前頁(yè)面一個(gè)屏幕的寬度)
// =>clientHieght 獲取高度
6.2.6 domcument.body 獲取body對(duì)象
6.2.7 domcument.head 獲取整個(gè)head對(duì)象
6.2.8 [context]querySelector 一個(gè)元素對(duì)象 / [context]querySelectorAll 獲取元素集合
- ie6-8不兼容肾扰,而且沒(méi)有特別好的辦法處理他的兼容畴嘶,所以這兩個(gè)方法一般多用于移動(dòng)端開(kāi)發(fā)使用
querySelector 獲取一個(gè)元素對(duì)象<br />querySelectorAll 獲取的一個(gè)元素集合<br />只要css支持的選擇器,這里大部分都支持
document.querySelector('#box1');
document.querySelectorAll('.box1');
document.querySelectorAll('div');
document.querySelectorAll('body>div');
document.querySelectorAll('#box1 li');
6.3 節(jié)點(diǎn)關(guān)系屬性
節(jié)點(diǎn)是用來(lái)描述頁(yè)面中每一部門之間關(guān)系的,只要我可以獲取頁(yè)面中的一個(gè)頁(yè)面集晚,那么我就可以通過(guò)相關(guān)的屬性和方法獲取頁(yè)面中所有的節(jié)點(diǎn)
6.3.1 childNodes
獲取當(dāng)前元素所有的子節(jié)點(diǎn)(節(jié)點(diǎn)集合:類數(shù)組)
注:不僅僅是元素子節(jié)點(diǎn)窗悯,文本、注釋等都會(huì)包含在內(nèi):子節(jié)點(diǎn)說(shuō)明只是在兒子輩分中查找
6.3.2 children
獲取所有的元素子節(jié)點(diǎn)(元素集合)
在IE6-8下獲取的結(jié)果和標(biāo)準(zhǔn)瀏覽器中有區(qū)別(IE6-8中會(huì)把注釋點(diǎn)當(dāng)做元素節(jié)點(diǎn)獲取到)
6.3.3 pareNode
獲取當(dāng)前元素的父節(jié)點(diǎn)(元素對(duì)象)
6.3.4 previousibing
獲取當(dāng)前節(jié)點(diǎn)的上一個(gè)各個(gè)節(jié)點(diǎn)上一個(gè)哥哥節(jié)點(diǎn)(不一定是元素節(jié)點(diǎn)也可能是文本或者注釋)
6.3.5 nextibling
獲取當(dāng)前節(jié)點(diǎn)的下一個(gè)弟弟節(jié)點(diǎn)
6.3.6 previousElementbling
獲取當(dāng)前節(jié)點(diǎn)的上一個(gè)哥哥元素節(jié)點(diǎn)
6.3.7 nextElementsIbling
獲取當(dāng)前節(jié)點(diǎn)下一個(gè)弟弟元素節(jié)點(diǎn)
IE6-8不兼容
6.3.8 firstChild
當(dāng)前元素所有子節(jié)點(diǎn)中的第一個(gè)(也不一定是元素節(jié)點(diǎn)偷拔,可能是文本和注釋)
6.3.9 lastChild
當(dāng)前元素多有子節(jié)點(diǎn)中的最后一個(gè)
fistElementChild lastElementChild(IE6-8兼容)
6.4 創(chuàng)建和增加DOM元素
真實(shí)項(xiàng)目中蟀瞧,我們偶爾會(huì)在js中動(dòng)態(tài)創(chuàng)建html標(biāo)簽,然后把其增加到頁(yè)面中
6.4.1 document.createElement
在js中動(dòng)態(tài)創(chuàng)建一個(gè)html標(biāo)簽
6.4.2 appendChild
容器.appendChild(新元素)
把當(dāng)前創(chuàng)建的新元素添加到容器的末尾位置
6.4.3 inserBefore
容器.inserBefore(新元素条摸、老元素)
在當(dāng)前容器中,把新創(chuàng)建的元素增加到老元素之前
// 創(chuàng)建
var oDiv = document.createElement('div');
oDiv.id='div1';
oDiv.className = 'box';
// 添加到頁(yè)面中
document.body.appendChild(oDiv);
document.body.inserBefore(oDiv,box2);
var link = document.createElement('a');
link.
consloe.dir(link);
// hash:存儲(chǔ)餓哈希值 '#haha'
// hostname:域名 'www.baidu.com'
// pathname:路徑 '/stu/'
// protocol:協(xié)議 'http:'
// search:問(wèn)號(hào)傳遞參數(shù)值 '?nname=1&age=2'
真實(shí)項(xiàng)目中很多需要通過(guò)動(dòng)態(tài)創(chuàng)建元素來(lái)完成的铸屉,其中有一個(gè)需求:解析一個(gè)url地址每一部分的信息(包括問(wèn)號(hào)傳值的參數(shù)值)
- 純字符串拆分截取
- 編寫(xiě)強(qiáng)大的正則钉蒲,捕獲到需要的結(jié)果
- 通過(guò)動(dòng)態(tài)創(chuàng)建一個(gè)a標(biāo)簽,利用a標(biāo)簽的一些內(nèi)置屬性來(lái)分別獲取每一部分的內(nèi)容
function queryURLParameter(url){
var link = document.createElement('a');
link.href=url;
var search = link.search,
obj = {}'
if(search.length===0) return;
search = search.substr(1).split(/&|=/g);
for(var i=0;i<search.length;i+=2){
var key = search[i],
value = search[i+1];
obj[key]=value;
}
link = null;
return obj;
}
6.5 修改刪除克隆DOM元素
6.5.1 removeChild
- 容器.removeChild(元素)
- 在當(dāng)前容器中把每一個(gè)元素移出掉
6.5.2 replaceChild
- 容器.removeChild(新元素彻坛,老元素)
- 把原有的元素克隆一份一模一樣的顷啼,false:只克隆當(dāng)前元素本身,true:深度克隆昌屉,吧當(dāng)前元素本身以及元素的所有后代都進(jìn)行克隆
6.5.3 [set/get/remove]Attribute
給當(dāng)前元素設(shè)置/獲取/移出屬性的(一般操作的都是它的自定義屬性)
box.setAttribute('myIndex',0)
box.getAttribute('myIndex')
box.removeAttribute('myIndex')
使用xxx.index=0 和xxx.setAttribute('index',0)這兩種設(shè)置自定義屬性的區(qū)別
xxx.index : 是吧當(dāng)前操作的元素當(dāng)做一個(gè)普通對(duì)象钙蒙,為其設(shè)置一個(gè)屬性名<br />xxx.setAttribute:把元素當(dāng)做特殊的元素對(duì)象來(lái)處理,設(shè)置的自定義屬性是和頁(yè)面結(jié)構(gòu)中的DOM元素映射在一起的
JS中獲取的元素對(duì)象间驮,我們可以把他理解為兩種角色:
- 與頁(yè)面HTML結(jié)構(gòu)無(wú)關(guān)的普通對(duì)象
- 與頁(yè)面HTML結(jié)構(gòu)存在映射關(guān)系的元素對(duì)象
元素對(duì)象中的內(nèi)置屬性躬厌,大部分都和頁(yè)面的標(biāo)簽存在映射關(guān)系:<br />xxx.style.backgroundColor = 'xxx' 此時(shí)不僅把js中對(duì)象對(duì)應(yīng)的屬性值改變了,而且也會(huì)映射到頁(yè)面的html標(biāo)簽上(標(biāo)簽中有一個(gè)style行內(nèi)樣式竞帽,元素的樣式改變了)<br />xxx.className = 'xxx'此時(shí)不僅是吧js對(duì)象中的屬性值改變了扛施,而且頁(yè)面中的標(biāo)簽增加了class樣式類(可以看見(jiàn)的)
元素對(duì)象中的自定義屬性: xxx.index=0<br />僅僅是吧js對(duì)象中增加了一個(gè)屬性名(自定義的)鸿捧,和頁(yè)面中的html沒(méi)啥關(guān)系(在結(jié)構(gòu)上看不見(jiàn))
xxx.setAttribute:通過(guò)這種方式設(shè)置的自定義屬性和之前提到的內(nèi)置屬性差不多,都是和html結(jié)構(gòu)存在映射關(guān)系的(設(shè)置的自定屬性可以呈現(xiàn)在結(jié)構(gòu)上)
6.6 面試題
把當(dāng)前頁(yè)面中所有id叫做box1的都獲取到
var allList = document.getElementsByTagName(*);
var result = []
for(var i=0;i<allList.length;i++){
var item = allList[i];
item.id === 'box1'?result.push(item)
}
console.log(result)
獲取當(dāng)前元素的上一個(gè)哥哥元素節(jié)點(diǎn)(兼容所有的瀏覽器)
curEle:current element
// 首先獲取當(dāng)前元素的上一個(gè)哥哥節(jié)點(diǎn)疙渣,判斷當(dāng)前獲取的節(jié)點(diǎn)是否為元素節(jié)點(diǎn)(nodeType===1)
// 如果不是基于當(dāng)前獲取的節(jié)點(diǎn)匙奴,找他的上一個(gè)哥哥節(jié)點(diǎn)..(找?guī)状尾恢?一直到找到的節(jié)點(diǎn)是元素節(jié)點(diǎn)為止
// 如果在查找過(guò)程中,發(fā)現(xiàn)沒(méi)有上一個(gè)哥哥節(jié)點(diǎn)妄荔,找到頭了泼菌,則不再繼續(xù)查找
function prev(curEle){
var p = curEle.previousSibling; // 屬性返回同一樹(shù)層級(jí)中指定節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)。
while(p&&p.nodeType!==1){ //p:p!=null
p = p.previousSibling;
}
return p;
}
// 擴(kuò)展
// next: 獲取下一個(gè)弟弟元素節(jié)點(diǎn)
// prevAll:獲取所有的哥哥元素節(jié)點(diǎn)
// nextAll:獲取所有的弟弟元素節(jié)點(diǎn)
// siblings:獲取所有的兄弟元素節(jié)點(diǎn)
// index:獲取當(dāng)前元素的兄弟中排名索引
7 Math的常用方法
7.1 數(shù)學(xué)函數(shù)
但是他是對(duì)象數(shù)據(jù)類型的
- 'object'
- Math對(duì)象中給我們提供了很多常用操作數(shù)字的方法
- console.dir(Math) // 查看所有方法
7.1.1 abs
Math.abs 取絕對(duì)值
7.1.2 cell / floor
cell: 向上取整
floor: 向下取整
7.1.3 round
round: 四舍五入
7.1.4 random
random: 獲取一個(gè)[0,1]之間的一個(gè)隨機(jī)小數(shù)
7.1.5 max/minx
max 獲取一組值中的最大值
minx 獲取一組值中的最小值
7.1.6 PI
Math.PI 獲取圓周率
7.1.7 pow / sqrt
pow 獲取一個(gè)值的多少冪
sqrt 獲取一個(gè)值的開(kāi)平方
8 字符串及常用的方法
在js中用單(雙)引號(hào)包裹起來(lái)的都是字符串
var str = 'welcome to credan!'
字符串就是由零到多個(gè)字符串組成的
第一個(gè)字符索引0<br />第二個(gè)字符索引1<br />...<br />有l(wèi)ength的屬性啦租,存儲(chǔ)的是當(dāng)前字符串中字符的個(gè)數(shù)(字符串的長(zhǎng)度)
以數(shù)字作為索引哗伯,從零開(kāi)始的
str[0] -> 'w' 第一個(gè)字符<br />strlength-> 46<br />str[str.length-1] -> '!' 最后一個(gè)字符<br />str[100] -> undefined 如果指定的索引不存在獲取的結(jié)果是undefined
真實(shí)項(xiàng)目中,我們經(jīng)常操作字符串刷钢,此時(shí)我們需要掌握常用的一些字符床操作方法
console.dir(String.prototype)
charAt && charCodeAt
8.1 str.charCodeAt(索引):
在charAt 基礎(chǔ)上笋颤,把獲取的字符變?yōu)閁nicode編碼值(對(duì)應(yīng)ASCll碼表)
- 48-57 0-9
- 65-90 A-Z
- 97-122 a-z
- ...
String.fromCharCode(十進(jìn)制的Unicode值),把值按照ascll碼表中的信息内地,轉(zhuǎn)為原有字符伴澄,charCodeAt正好對(duì)應(yīng)<br />
8.2 substr && substring && slice
- 實(shí)現(xiàn)字符串截取的三個(gè)辦法
- str.substr(n.m) : 從索引n開(kāi)始,截取m個(gè)字符
- str.substring(n,m):從索引n開(kāi)始阱缓,截取到索引為m處(包含m)非凌,把找到的部分截取
- str.slice(n,m):和substring語(yǔ)法意義,區(qū)別在于slice支持一負(fù)數(shù)做索引
當(dāng)索引是負(fù)數(shù)的時(shí)候荆针,瀏覽器在處理的時(shí)候敞嗡,是用字符串的總長(zhǎng)度加上負(fù)數(shù)索引,然后按照正數(shù)處理操作
細(xì)節(jié):
- 如果只傳遞了n(str.substr(n)/str.substring(n)),相當(dāng)于索引n開(kāi)始的一直截取到字符串的末尾
- 如果傳遞的索引超出最大限制航背,也是吧能截取的部分截取掉即可
- 如果一個(gè)參數(shù)都不傳遞:相當(dāng)于吧證書(shū)字符串都截取(字符串的克隆)
indexOf && lastIndexOf
- str.indexOf 獲取當(dāng)前字符在字符串中第一次出現(xiàn)位置的索引
- str.lastIndexOf 獲取的是最后一次出現(xiàn)位置的索引
如果當(dāng)前字符在字符串中沒(méi)有出現(xiàn)過(guò)喉悴,結(jié)果是-1:我們根據(jù)這個(gè)規(guī)律可言驗(yàn)證一下當(dāng)前字符串中是否包含某個(gè)字符
if(str.indexOf('?')===-1){
// => 沒(méi)有出現(xiàn)過(guò)
}
if(str.indexOf('?')>=-1){
// => 出現(xiàn)過(guò)
}
8.3 split
str.split 按照某個(gè)字符串分成數(shù)組中的某一項(xiàng),和數(shù)組中的join方法是對(duì)應(yīng)
8.4 replace
str.replace 實(shí)現(xiàn)字符的替換
執(zhí)行一次replace 只能替換一次玖媚,如果有好幾個(gè)都需要替換箕肃,在不適用正則的情況下,我們需要執(zhí)行很多次replace
有些需求及時(shí)執(zhí)行很多次repalce也實(shí)現(xiàn)不了今魔,此時(shí)需要使用正則處理勺像,真實(shí)項(xiàng)目中replace一般都是和正則搭配使用的
8.5 trim && trimLeft && trimRight
- str.trimLeft : 去除字符串開(kāi)始的口空格
- str.trimRight : 去除字符串結(jié)尾的口空格
- str.trim 去除字符串首位的空格
獲取地址欄的值
function queryURLPrameter(url){
// => url 傳遞的參數(shù)
var quesIndex = url.indexOf('?'),
obj = {}
if(quesIndex === -1){ // url中沒(méi)有問(wèn)號(hào)傳參 直接返回空
retrun obj;
}
url = url.substr(quesIndex + 1);
var ary = url.split('&');
for(var i =0;i<ary.length;i++){
var curAry = ary[i].split('=');
obj[curAry[0]] = curAry[i];
}
return obj
}
String.prototype.myQueryURLParameter = function
myQueryURLParamter(){
var obj = /([^=?&]+)=([^=?&]+)/g;
this.replace(reg,function(){
var arg = argments;
obj[arg[1]] = arg[2]
})
return obj;
}
var str = 'https://www/baidu.com/s?wd=1233213&issp=1';
console.log(str.myQueryURLParameter());
9 Date的基礎(chǔ)知識(shí)
9.1 Data 是日期類
通過(guò)它可以對(duì)時(shí)間進(jìn)行處理
var time = new Date();
// 獲取當(dāng)前客戶端本機(jī)時(shí)間(當(dāng)前獲取的時(shí)間不能作為重要的參考依據(jù))
// 獲取結(jié)果是一個(gè)日期格式的對(duì)象
// Wed Mar 20 2019 17:37:16 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)
typeof new Date() -> object
time.getFullYear() 獲取四位數(shù)整年
time.getMonth() 獲取月份
time.getDate() 獲取日
time.getDay() 獲取星期(0-6代表周日-周六)
time.getHours() 獲取小時(shí)
time.getMinutes() 獲取分鐘
time.getSeconds() 獲取秒
time.getMilliseconds() 獲取毫秒
time.getTime() 獲取當(dāng)前日期距離'1970-01-01 00:00:00'的毫秒差
var time = new Date('2017-10-22');
// 當(dāng)new Date 中傳遞一個(gè)時(shí)間格式的字符串,相當(dāng)于把這個(gè)字符串換位標(biāo)準(zhǔn)時(shí)間對(duì)象
// (轉(zhuǎn)換完成后错森,就可以調(diào)取上面我們講的那些方法)
// 時(shí)間格式的字符串<br />'2017-10-22' (IE下識(shí)別不了)<br />'2017/10/22 16:15:34'<br />'1508659621314'(如果傳遞的是距離1970年那個(gè)毫秒查吟宦,也可以識(shí)別轉(zhuǎn)換的,但是只能是數(shù)字,不能是字符串)<br />
10 數(shù)組的函數(shù)
10.1 數(shù)組的基礎(chǔ)結(jié)構(gòu)
- 數(shù)組也是對(duì)象數(shù)據(jù)類型 typeof [] -> 'object'
- 數(shù)組也是屬性名涩维,只不過(guò)屬性名是數(shù)字殃姓,我們把數(shù)字屬性名稱之為它的索引:數(shù)組是以數(shù)字為索引,索引從零開(kāi)始,有一個(gè)length屬性代表數(shù)組的長(zhǎng)度
<br />
類數(shù)組:類似于數(shù)組辰狡,但是不是數(shù)組
- 通過(guò)getElementsByTageName 獲取的元素集合是類數(shù)組
- 函數(shù)中的實(shí)參集合argument也是類數(shù)組
<br />
// for 循環(huán)操作
for(var i =0;i<ary.length;i++){
console.log(ary[i])
}
// for in 循環(huán)操作
for(var key in ary){
// key:屬性名(數(shù)組中的屬性名是索引)
console.log(ary[key]);
}
// for 循環(huán)只能遍歷到數(shù)組私有的一些屬性锋叨,而for in 循環(huán)可以吧一些自定義的公共屬性也能遍歷到
10.2 數(shù)組中的常用方法
數(shù)組中有很多方法
console.dir(Array.prototype)
- 方法的意義和作用
- 方法的形參
- 方法的返回值
- 通過(guò)此方法,原來(lái)的數(shù)組是否發(fā)生了改變
實(shí)現(xiàn)數(shù)組的增加宛篇、修改娃磺、刪除
10.2.1 增加
push : 向數(shù)組的末尾追加新內(nèi)容
參數(shù):一到多個(gè),任何數(shù)據(jù)類型都可以叫倍,想要給數(shù)組末尾追加什么偷卧,直接傳遞到push方法中極客,傳遞多個(gè)逗號(hào)隔開(kāi)<br />返回值:新增后數(shù)組的長(zhǎng)度<br />原有數(shù)組改變了
unshift:向數(shù)組開(kāi)頭追加新內(nèi)容
參數(shù):需要追加的內(nèi)容(可以是多個(gè)任何數(shù)據(jù)類型的值)<br />返回值:新增后 數(shù)組的長(zhǎng)度<br />原來(lái)數(shù)組改變了
把數(shù)組當(dāng)做一個(gè)普通的對(duì)象吆倦,使用對(duì)象鍵值對(duì)的操作听诸,給其設(shè)置新的屬性(索引)<br />ary[ary.length]=xxx 向數(shù)組的末尾追加了新的內(nèi)容
10.2.2 刪除
pop 刪除數(shù)組最后一項(xiàng)
參數(shù):無(wú)<br />返回值:被刪除的那一項(xiàng)內(nèi)容<br />原有數(shù)組改變了
shift:刪除數(shù)組第一項(xiàng)
參數(shù):無(wú)<br />返回值:被刪除那一項(xiàng)的內(nèi)容<br />原有數(shù)組改變了<br />使用shift刪除第一項(xiàng)之后,后面每一項(xiàng)的索引都要向前進(jìn)一位(導(dǎo)致后面項(xiàng)的索引發(fā)生了改變)
把數(shù)組當(dāng)做一個(gè)普通對(duì)象操作<br />delete刪除:delete ary[索引]刪除指定索引這一項(xiàng)(當(dāng)前項(xiàng)被刪除后),原有數(shù)組其它項(xiàng)的索引不會(huì)改變:當(dāng)前數(shù)組的length也不會(huì)改變
ary.length--:刪除數(shù)組最后一項(xiàng)
splice:數(shù)組中內(nèi)置的方法蚕泽,可以實(shí)現(xiàn)數(shù)組的增加晌梨、修改、刪除
splice實(shí)現(xiàn)刪除<br />splice(n,m):從索引n開(kāi)始刪除m個(gè)(m不寫(xiě)是個(gè)刪除列數(shù)組的末尾须妻,n也不寫(xiě))<br />返回值:被刪除的內(nèi)容(以一個(gè)新數(shù)組保存)<br />原有數(shù)組改變了<br />splice(0) 清空數(shù)組<br />splice() 一項(xiàng)都不刪除仔蝌,返回一個(gè)新的空數(shù)組<br />splice(0,1)刪除第一項(xiàng)
splice實(shí)現(xiàn)修改
splice(n,m,x):在原有刪除的基礎(chǔ)上,用x代替刪除的內(nèi)容
splice實(shí)現(xiàn)增加<br />splice(n,0,x):在修改的基礎(chǔ)上荒吏,我們一項(xiàng)都不刪除敛惊,把x插入到索引n的前面<br />ary.splice(0,0,x) 向數(shù)組末尾追加新元素
數(shù)組的查詢
slice 數(shù)組的查詢
- 參數(shù):slice(n,m) 從索引n開(kāi)始找到索引m處(不包含m)
- 返回值:吧找到的部分已一個(gè)新數(shù)組返回
- 原來(lái)的數(shù)組不變
slice(n) 從索引n開(kāi)始找到末尾<br />slice(0) /slice() 數(shù)組克隆,克隆一份和原來(lái)數(shù)組一模一樣的的新數(shù)組<br />slice支持負(fù)載索引绰更,如果傳遞的索引為負(fù)數(shù)瞧挤,瀏覽器解析的時(shí)候是按照總長(zhǎng)度+負(fù)數(shù)索引 來(lái)處理的
將兩個(gè)數(shù)組進(jìn)行拼接
concat:將多個(gè)數(shù)組拼接在一起
- 參數(shù):要拼接的內(nèi)容(把內(nèi)容放在原數(shù)組的后面),可以是一個(gè)數(shù)組
- 返回:拼接后的新數(shù)組
10.3 數(shù)組的查詢
slice: 數(shù)組的查詢<br />參數(shù): slice(n,m) 從索引n開(kāi)始找到索引為m處(不包含m)<br />返回值:把找到的部分已一個(gè)新數(shù)組返回<br />原來(lái)的數(shù)組不變
slice(n) 從索引n開(kāi)始找到末尾
slice(0) / slice() 數(shù)組克隆儡湾,克隆一份和原來(lái)數(shù)組一模一樣的新數(shù)組
slice 支持負(fù)數(shù)索引特恬,如果傳遞的索引為負(fù)數(shù),瀏覽器解析的時(shí)候是按照徐钠,總長(zhǎng)度+負(fù)數(shù)索引 來(lái)處理的
10.4 數(shù)組的拼接
concat:將多個(gè)數(shù)組拼接在一起<br />參數(shù):要拼接的內(nèi)容(把內(nèi)容放在原數(shù)組的后面),可以是一個(gè)數(shù)組鸵鸥,也可以是一些數(shù)據(jù)值<br />返回:拼接后的新數(shù)組<br />原有的數(shù)組不變
let arr = [0,100]
arr.concat([100,200],[200,300],12)
concat() 什么都沒(méi)有拼接,相當(dāng)于吧原有數(shù)組克隆一份一模一樣的出來(lái)<br />10.5 數(shù)組轉(zhuǎn)字符串
10.5.1 toString
實(shí)現(xiàn)吧數(shù)組轉(zhuǎn)化為字符串(轉(zhuǎn)換后的字符串逗號(hào)分隔每一項(xiàng))
參數(shù):無(wú)<br />返回值:轉(zhuǎn)換的字符串<br />原有數(shù)組不變
10.5.2 join
把數(shù)組按照指定的分隔符轉(zhuǎn)換為字符串丹皱,和字符串中的split相對(duì)應(yīng)
- 參數(shù):指定的鏈接符號(hào)
- 返回值:轉(zhuǎn)換后的字符串
- 原有數(shù)組不變
已知數(shù)組的每一項(xiàng)都是數(shù)字,想事先數(shù)組求和宋税,我們?nèi)绾螌?shí)現(xiàn)摊崭?
循環(huán)實(shí)現(xiàn)
var total = null;
for(var i=0;i<ary.length;i++){
total+=ary[i];
}
利用join
var total = eval(ary.join('+')) // evel:把字符串變?yōu)閖s表達(dá)式執(zhí)行
10.6 實(shí)現(xiàn)數(shù)組中每一項(xiàng)的排序和排列
10.6.1 reverse
把數(shù)組中每一項(xiàng)倒過(guò)來(lái)排序
參數(shù):無(wú)<br />返回值:排序后的數(shù)組<br />原有數(shù)組改變
10.6.2 sort
實(shí)現(xiàn)數(shù)組的排序
參數(shù):無(wú)或者回調(diào)函數(shù)<br />返回值:排序后的數(shù)組<br />原有數(shù)組改變<br /> 不傳遞參數(shù)的情況下:可以給10以內(nèi)的數(shù)字進(jìn)行升序排列,但是超過(guò)10的就無(wú)法處理(多位數(shù)值識(shí)別第一位)
ary.sort(function(a,b){
return a-b; //升序
return b-a; //降序
})
10.7 驗(yàn)證數(shù)組中是否包含某一項(xiàng)
10.7.1 indexOf / lastindexOf
獲取當(dāng)前現(xiàn)在數(shù)組中第一次或者最后一次出現(xiàn)的位置索引
- 數(shù)組的這兩個(gè)方法在IE6-IE8下不兼容
- 字符串的這兩個(gè)方法兼容所有的瀏覽器
if(ary.indexOf(12)>-1){
// 數(shù)組中包含12
}
10.7.2 原理
Array.prototype.myIndexOf = function myIndexOf(value){
var result = -1;
for(var i =0;i<this.length;i++){
if(value===this[i]){
result = i;
break;
}
}
return result;
}
10.8 遍歷數(shù)組每一項(xiàng)的方法
以下方法ie6-8下都不兼容
10.8.1 forEach
遍歷數(shù)組中的每一項(xiàng)
ary.forEach(function(value,index){
/* 數(shù)組中有多少項(xiàng)杰赛,當(dāng)前回調(diào)函數(shù)執(zhí)行多少次呢簸,妹妹一次傳進(jìn)來(lái)的value就是當(dāng)前遍歷數(shù)組這一項(xiàng)的值,index
就是遍歷這一項(xiàng)的索引
*/
})
10.8.2 map
遍歷數(shù)組中的每一項(xiàng),在forEach的基礎(chǔ)上根时,可以修改每一項(xiàng)的值
ary.map(function(value,index){
/* 數(shù)組中有多少項(xiàng)瘦赫,當(dāng)前回調(diào)函數(shù)執(zhí)行多少次,妹妹一次傳進(jìn)來(lái)的value就是當(dāng)前遍歷數(shù)組這一項(xiàng)的值蛤迎,index
就是遍歷這一項(xiàng)的索引
*/
return xxx;
// return 后面返回的結(jié)果就是當(dāng)前遍歷的這一項(xiàng)修改為xxx
})
filter<br />find<br />reduce<br />every<br />...
10.9 數(shù)組去重
var ary = [1,2,3,4,5,6,7,1,3,4,5];
方案一 最簡(jiǎn)單數(shù)組去重法
遍歷數(shù)組的每一項(xiàng)确虱,拿每一項(xiàng)和它后面的項(xiàng)依次比較,如果相同了,則把相同的這一項(xiàng)在原來(lái)數(shù)組中刪除即可
/*
* 新建一新數(shù)組替裆,遍歷傳入數(shù)組校辩,值不在新數(shù)組就push進(jìn)該新數(shù)組中
* IE8以下不支持?jǐn)?shù)組的indexOf方法
* */
function uniq(array){
var temp = []; //一個(gè)新的臨時(shí)數(shù)組
for(var i = 0; i < array.length; i++){
if(temp.indexOf(array[i]) == -1){
temp.push(array[i]);
}
}
return temp;
}
var aa = [1,2,2,4,9,6,7,5,2,3,5,6,5];
console.log(uniq(aa));
方案二 對(duì)象鍵值法去重
/*
* 速度最快, 占空間最多(空間換時(shí)間)
*
* 該方法執(zhí)行的速度比其他任何方法都快辆童, 就是占用的內(nèi)存大一些宜咒。
* 現(xiàn)思路:新建一js對(duì)象以及新數(shù)組,遍歷傳入數(shù)組時(shí)把鉴,判斷值是否為js對(duì)象的鍵故黑,
* 不是的話給對(duì)象新增該鍵并放入新數(shù)組。
* 注意點(diǎn):判斷是否為js對(duì)象鍵時(shí)庭砍,會(huì)自動(dòng)對(duì)傳入的鍵執(zhí)行“toString()”场晶,
* 不同的鍵可能會(huì)被誤認(rèn)為一樣,例如n[val]-- n[1]逗威、n["1"]峰搪;
* 解決上述問(wèn)題還是得調(diào)用“indexOf”。*/
function uniq(array){
var temp = {}, r = [], len = array.length, val, type;
for (var i = 0; i < len; i++) {
val = array[i];
type = typeof val;
if (!temp[val]) {
temp[val] = [type];
r.push(val);
} else if (temp[val].indexOf(type) < 0) {
temp[val].push(type);
r.push(val);
}
}
return r;
}
var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
方案三 排序后相鄰去除法
/*
* 給傳入數(shù)組排序凯旭,排序后相同值相鄰概耻,
* 然后遍歷時(shí),新數(shù)組只加入不與前一值重復(fù)的值。
* 會(huì)打亂原來(lái)數(shù)組的順序
* */
function uniq(array){
array.sort();
var temp=[array[0]];
for(var i = 1; i < array.length; i++){
if( array[i] !== temp[temp.length-1]){
temp.push(array[i]);
}
}
return temp;
}
var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
方案四 數(shù)組下標(biāo)法
/*
*
* 還是得調(diào)用“indexOf”性能跟方法1差不多罐呼,
* 實(shí)現(xiàn)思路:如果當(dāng)前數(shù)組的第i項(xiàng)在當(dāng)前數(shù)組中第一次出現(xiàn)的位置不是i鞠柄,
* 那么表示第i項(xiàng)是重復(fù)的,忽略掉嫉柴。否則存入結(jié)果數(shù)組厌杜。
* */
function uniq(array){
var temp = [];
for(var i = 0; i < array.length; i++) {
//如果當(dāng)前數(shù)組的第i項(xiàng)在當(dāng)前數(shù)組中第一次出現(xiàn)的位置是i,才存入數(shù)組计螺;否則代表是重復(fù)的
if(array.indexOf(array[i]) == i){
temp.push(array[i])
}
}
return temp;
}
var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
方案五 優(yōu)化遍歷數(shù)組法
// 思路:獲取沒(méi)重復(fù)的最右一值放入新數(shù)組
/*
* 推薦的方法
*
* 方法的實(shí)現(xiàn)代碼相當(dāng)酷炫夯尽,
* 實(shí)現(xiàn)思路:獲取沒(méi)重復(fù)的最右一值放入新數(shù)組。
* (檢測(cè)到有重復(fù)值時(shí)終止當(dāng)前循環(huán)同時(shí)進(jìn)入頂層循環(huán)的下一輪判斷)*/
function uniq(array){
var temp = [];
var index = [];
var l = array.length;
for(var i = 0; i < l; i++) {
for(var j = i + 1; j < l; j++){
if (array[i] === array[j]){
i++;
j = i;
}
}
temp.push(array[i]);
index.push(i);
}
console.log(index);
return temp;
}
var aa = [1,2,2,3,5,3,6,5];
console.log(uniq(aa));
11 函數(shù)基礎(chǔ)
- 函數(shù)是指一段在一起的登馒、可以做某一件事兒的程序匙握。也叫做子程序、(OOP中)方法
- 函數(shù)實(shí)現(xiàn)某一個(gè)功能的方法
11.1 創(chuàng)建函數(shù)
functoin [函數(shù)名](){
// => [函數(shù)體]
// 實(shí)現(xiàn)功能的具體js代碼
}
11.2 執(zhí)行函數(shù)
函數(shù)名(); // 創(chuàng)建的函數(shù)執(zhí)行陈轿,而且這個(gè)函數(shù)可以執(zhí)行很多次
函數(shù)名();
每一次執(zhí)行都相當(dāng)于把函數(shù)體重實(shí)現(xiàn)功能的js代碼重復(fù)執(zhí)行了一遍
在真實(shí)的項(xiàng)目中圈纺,我們一般都會(huì)把實(shí)現(xiàn)一個(gè)具體功能的代碼封裝到函數(shù)中
- 如果當(dāng)前這個(gè)功能需要在頁(yè)面中執(zhí)行多次秦忿,不封裝成為函數(shù),每一次實(shí)現(xiàn)這個(gè)功能蛾娶,都需要重新吧代碼寫(xiě)一遍灯谣,浪費(fèi)時(shí)間;而封裝在一個(gè)函數(shù)中蛔琅,以后想實(shí)現(xiàn)多次這個(gè)功能胎许,我們就沒(méi)有必要在重新寫(xiě)代碼,只需要把函數(shù)重新的執(zhí)行即可揍愁,提高了開(kāi)發(fā)效率
- 封裝在一個(gè)函數(shù)呐萨,頁(yè)面中就基本上很難重復(fù)一樣的代碼了,減少了頁(yè)面中代碼的冗余度莽囤,提高了代碼的重復(fù)利用率:
低耦合高內(nèi)聚
我們把以上的特點(diǎn)成為函數(shù)封裝 (OOP面向?qū)ο缶幊趟枷朊粒枰覀冋莆盏木褪穷惖睦^承、封裝朽缎、多態(tài))
11.3 JS中函數(shù)的核心原理
函數(shù)作為js中引用數(shù)據(jù)類型中的一種惨远,也是按照引用地址操作的
function sum(){
var total = 1+1;
total *= 20;
console.log(total.toFixed(2));
}
sum();
11.3.1 創(chuàng)建函數(shù)
- 首先會(huì)在當(dāng)前作用中聲明一個(gè)函數(shù)名(聲明的函數(shù)和使用var聲明變量是一樣的操作:var sum;function cum;這兩個(gè)名字算重復(fù)了)
- 瀏覽器首先會(huì)開(kāi)辟一個(gè)新的內(nèi)存空間(奉陪一個(gè)16進(jìn)制地址),把函數(shù)體重寫(xiě)好的代碼當(dāng)做普通字符串存儲(chǔ)在這個(gè)內(nèi)存空間(創(chuàng)建一個(gè)函數(shù)如果不執(zhí)行话肖,函數(shù)沒(méi)有意義)
- 把內(nèi)存空間的地址賦值給之前聲明的那個(gè)函數(shù)名
11.3.2 函數(shù)執(zhí)行
- 目的:把之前存儲(chǔ)的實(shí)現(xiàn)具體功能的js代碼執(zhí)行
- 函數(shù)執(zhí)行北秽,瀏覽器首先會(huì)為其開(kāi)辟新的
私有作用域
(只能執(zhí)行函數(shù)中之前編寫(xiě)的js代碼) - 形參賦值
- 私有作用中的變量升級(jí)
- 把之前穿件時(shí)間存儲(chǔ)的那些js代碼字符串,拿到自由作用域中最筒,然后把題目變成js表達(dá)式從上到下執(zhí)行
- 私有作用域是否銷毀的問(wèn)題
<br />
![image.png](https://upload-images.jianshu.io/upload_images/5757088-b9bc22a07a4b75ea.png&originHeight=406&originWidth=986&size=115231&status=done&width=493?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
<br />
11.3.3 閉包
函數(shù)執(zhí)行會(huì)形成一個(gè)私有的作用域贺氓,讓里面的私有變量和外界互不影響(相互干擾、外面的無(wú)法直接獲取里面的變量值)床蜘,此時(shí)我們可以理解為私有作用域把私有變量保護(hù)起來(lái)辙培,我們把這種保護(hù)機(jī)制稱為為
閉包
11.3.4 棧內(nèi)存
作用域(全局作用域/私有作用域):提供一個(gè)供js代碼執(zhí)行的環(huán)境
11.3.5 堆內(nèi)存
所有的引用數(shù)據(jù)類型,他們需要存儲(chǔ)的內(nèi)容都是堆內(nèi)存中(相當(dāng)于一個(gè)倉(cāng)庫(kù)邢锯,目的是存儲(chǔ)信息)
- 對(duì)象會(huì)吧鍵值隊(duì)存儲(chǔ)起來(lái)
- 函數(shù)會(huì)把代碼當(dāng)做字符串存儲(chǔ)起來(lái)
11.4 函數(shù)中形參和實(shí)參
- 形參:相當(dāng)于生成洗衣機(jī)的時(shí)候提供的入口扬蕊,需要用戶執(zhí)行函數(shù)的時(shí)候把需要的值傳遞進(jìn)來(lái),形參是個(gè)變量丹擎,用來(lái)春初和接口那些值
- 實(shí)參:用戶執(zhí)行的時(shí)候傳遞給形參的具體指
// 隨便求出兩個(gè)數(shù)的和
function sum(num1,num2){ //num1/num2就是形參變量(類似于var了一下)
var total = num1 + num2;
total*=10;
total=total.toFixed(2);
console.log(total);
}
sum(10,20);//10/20是實(shí)參 num1=10 num2=20
sum(10); // num1=10 num2=undefined 定義了形參但是執(zhí)行的時(shí)候尾抑,沒(méi)有傳遞實(shí)參,默認(rèn)實(shí)參就是undefined
11.5 arguments實(shí)參集合
當(dāng)我們不知道用戶具體要傳遞幾個(gè)值的時(shí)候(傳遞幾個(gè)值都行)蒂培,此時(shí)我們無(wú)法設(shè)置形參的個(gè)數(shù):遇到此類需要再愈,需要使用函數(shù)內(nèi)置的實(shí)參集合:arguments
- argument 只有函數(shù)才有
- 不管執(zhí)行函數(shù)的時(shí)候是否傳遞實(shí)參,arguments天生就純?cè)诨ご粒瑳](méi)有傳遞實(shí)參ARG是個(gè)空的集合傳遞了ARG中包含了所有傳遞的實(shí)參值
- 不管是否設(shè)置了形參践磅,ARG中始終存儲(chǔ)了所有的實(shí)參信息
function sum(){
console.log(arguments)
}
sum(10,20,'wjh',{name:'wjw'});
- arguments 是個(gè)類數(shù)組集合
- 以數(shù)字作為索引(屬性名),從0開(kāi)始
- arguments[0] 第一個(gè)實(shí)參信息
- arguments[2] 第三個(gè)實(shí)參信息
- arguments[n] 第n+1個(gè)實(shí)參信息
- 有一個(gè)length的屬性灸异,存儲(chǔ)的是當(dāng)前幾個(gè)的長(zhǎng)度(當(dāng)前傳遞實(shí)參的個(gè)數(shù))
- arguments.length
- arguments['length']
- arguments.calle 存儲(chǔ)的是當(dāng)前函數(shù)本身
- arguments.calle.caller 存儲(chǔ)的是當(dāng)前函數(shù)只在哪執(zhí)行的(宿主函數(shù))府适,在全局作用域下執(zhí)行的,結(jié)果是null
function sum(){
console.log(arguments.callee.caller);//f
}
function fn(){
sum(10,20,'wjh',{name:'wjw'});
}
fn();
// arguments.call或者arguments.call.caller一般真正項(xiàng)目中很少使用肺樟,因?yàn)槭窃趪?yán)格js模式下不允許我們直接使用這兩個(gè)屬性檐春,然而現(xiàn)有項(xiàng)目大部分都是基于嚴(yán)格模式來(lái)的
// 任意數(shù)求和
function sum(){
var total = null;
for(var i =0;i<arguments.length;i++){
var cur = Number(arguments[i]);
!isNaN(cur)?total += cur : null
}
consloe.log(total);
return total;
// return 后面跟著的都是值(返回的都是值):此處不少TOTAL變量返回,而是吧total存儲(chǔ)到值返回而已
// return 60;
}
sum(10,20,20);
sum();
sum(10,20,30,'wjw')
// console.log(total);
//=>Uncaught ReferenceError: total is not defined 閉包的保護(hù)機(jī)制導(dǎo)致作用域會(huì)保護(hù)里面的私有變量
11.6 JS中的返回值return
返回值是函數(shù)提供的一個(gè)出口:我們?nèi)绻朐谕饷媸褂煤瘮?shù)私有的一些信息么伯,那么就需要通過(guò)return疟暖,把這些信息返回出來(lái)供外面使用
sum:代表的是函數(shù)本身<br />sum() 讓函數(shù)先執(zhí)行,代表的是當(dāng)前函數(shù)返回的結(jié)果(return)后面是啥田柔,相當(dāng)于函數(shù)返回的是啥
function sum(){
var total = 0;
renturn
}
console.log(sum());
// 如果函數(shù)中沒(méi)有return或者return后面啥也沒(méi)有俐巴,默認(rèn)返回的結(jié)果是undefined
function sum(){
var total = 0;
renturn;
console.log(sum());
// 函數(shù)體重遇到return后,return后面的代碼都不在執(zhí)行了
}
11.7 js中匿名函數(shù)
沒(méi)有名字的函數(shù)
- 函數(shù)表達(dá)式
- 自執(zhí)行函數(shù)
oBox.onclick = function(){
// 把一個(gè)碼云名字的函數(shù)(有名字的也無(wú)所謂)作為值賦值給一個(gè)變量或者一個(gè)元素的某一個(gè)事件等,函數(shù)表達(dá)式
}
(function(n){
// 創(chuàng)建函數(shù)和執(zhí)行函數(shù)放在一起硬爆,穿件完成立馬之執(zhí)行:自執(zhí)行函數(shù)
// n 形參 n=10
})(10)
// 以下都是自執(zhí)行函數(shù)欣舵,符號(hào)只有控制語(yǔ)法規(guī)范
~function(){}(10)
-function(){}(10)
+function(){}(10)
!function(){}(10)