嘔心瀝血 JavaScript知識點梳理大全,超詳細 建議收藏!!!
??大家好,我是王同學,爆肝三天三夜王同學把JavaScript 知識點梳理了一遍,文章沒有一點套路,只有滿滿的干貨
??如果對你有幫助就給我點個贊吧,這樣我們就互不相欠了
??星光不負趕路人,所有的幸運都來自于堅持不懈的努力,大家一起沖沖沖~~~

一、語法和變數
(一)、前端三層

(二)、JS的書寫位置



(三)、輸出陳述句

(四)、變數宣告提升
變數的宣告提升:你可以提前使用一個稍后才宣告的變數,而不會引發例外
在執行所有代碼前,JS有預決議階段,會預讀所有變數的定義

二、基本資料型別
(一)、JavaScript中兩大類資料型別

(二)、typeof運算子
typeof運算子可以檢測值或者變數的型別

(三)、五種基本資料型別的typeof檢測結果

(四)、數字型別
所有數字不分大小、不分整浮、不分 正負、都是數字型別

較大數或者較小數(絕對值較小)可以寫成科學計數法

(五)、不同進制的數字

(六)、一個特殊的數字型值NaN
NaN是英語“not a number” 的意思,即不是一個數字,但它是一個數字型別的值

(七)、字串型別
- 字串就是人類的自然語言
- 字串要用引號包裹,雙引號或者單引號都可以

(八)、字串的拼接
加號可以拼接多個字串


(九)、字串和變數的拼接

空字串
一些時候需要用到空字串,直接書寫閉合的引號對即可

字串的length屬性
字串的length屬性表示字串的長度

(十)、字串常用的方法

(十一)、charAt()方法
作用:得到指定位置的字符



(十二)、substring()方法





(十三)、substr()方法



(十四)、slice()方法




(十五)、三者對比總結

(十六)、toUpperCase()和toLowerCase()

(十七)、indexOf()


(十八)、BOOlean(布爾型別)



(十九)、Undefined
一個沒有被賦值的變數的默認值是undefined,而undefined的型別也是undefined,即undefined又是值,又是一種型別,這種型別只有它自己一個值

變數提升的情況
在變數宣告提升時,變數的值也是undefined

(二十)、null型別
- null物件表示是空,它是空物件
- 當我們需要將物件銷毀,陣列銷毀或者洗掉事件監聽時,通常將他們設定為空



(二十一)、資料型別的轉換
使用Number()函式


使用parseInt()函式

使用parseFloat()函式





(二十二)、復雜資料型別簡介


3
true
NaN
Infinity

bcd
bc
''
bc
(二十三)、運算式和運算子

運算式的種類
算術、關系、邏輯、賦值、綜合
(二十四)、算術運算子
默認情況下,乘除法的優先級要高于加法和減法,必要時可以使用圓括號來改變運算的順序


加號的兩種作用


取余運算(求模運算)
- 取余運算也叫求模運算,用百分號來表示
- a%b表示 a除以b的余數,它不關心整數部分,只關心余數

(二十五)、隱式型別轉換
如果參與運算的某運算元不是數字型,那么JavaScript會自動將此運算子轉換為數字

隱式轉換的本質就是內部呼叫Number()函式




解決辦法:在進行小數運算的時候,要呼叫數字的toFixed ()方法保留指定的小數位

(二十六)、冪和開根號
JavaScript中沒有提供冪計算,開根號的運算子,需要使用Math物件相關的方法進行計算

(二十七)、向上取整和向下取整


(二十八)、關系運算式

(二十九)、判斷是否相等


(三十)、相等和全等



(三十一)、NaN不自等

如何判斷某變數的值為NaN?
- isNaN()函式可以用來判斷變數的值是否為NaN
- 但isNaN()也不好用,它的機理是:只要該變數傳入Number()的執行結果是NaN,則isNaN()函式都會得到true


不相等和不全等

JS中沒有連比
判斷變數 a是不是介于3到15之間,應該怎么寫呢?

(三十二)、非運算
置反運算的結果一定是布林值



(三十三)、與運算


(三十四)、或運算

(三十五)、短路計算






(三十六)、邏輯運算的順序

(三十七)、賦值運算子




(三十八)、快捷運算子
快捷運算子表示在原陣列基礎上進一步進行運算


(三十九)、自增和自減運算子


(四十)、綜合運算式
綜合運算式的運算順序:非運算—數學運算—關系運算—邏輯運算


變數的范圍表示

知識回顧

函式
(一)、函式的定義和呼叫


(二)、函式的呼叫
執行函式體中的所有陳述句,就稱為函式呼叫
呼叫函式十分簡單,只需要在函式名字后面書寫圓括號對即可

(三)、陳述句的執行順序


(四)、函式宣告的提升
和變數宣告提升類似,函式宣告也可以被提升

函式的運算式是不能被提升的,如果函式是用函式運算式的寫法定義的,則沒有提升的特性

(五)、函式的優先提升

<script>
//首先函式會優先提升
//變數的定義后提升 后提升并不會把先提升的覆寫掉
//變數提升只會先提升定義 不會提升值
fun();
var fun = function() {
alert('A');
}
function fun() {
alert('B')
}
fun();
</script>
(六)、函式的引數
引數是函式內的一些特定的值,在呼叫函式時,必須傳入這些引數的具體的值
函式的引數有多有少,函式可以沒有引數,也可以有多個引數,多個引數之間要用逗號隔開


(七)、arguments

<script>
function fun() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
console.log('所有的引數之和為:' + sum); //110
}
fun(33, 22, 55)
</script>
(八)、函式的回傳值
函式體內可以使用return關鍵字表示“函式的回傳值”

//函式的功能是回傳兩個引數的和
function sum(a, b) {
return a + b;
}
var result = sum(3, 4);
console.log(result);
(九)、函式的回傳值
呼叫一個有回傳值的函式,可以被當做一個普通值,從而可以出現在任何可以書寫的地方


(十)、遇見return即退出函式
呼叫函式時,一旦遇見return陳述句則會立即退出函式,將執行權交還給呼叫者

1
A
B
2
結合if陳述句 往往不需要寫else分支了
<script>
//書寫一個函式 函式的功能是判斷一個數字是否是偶數
function checkEven(n) {
if (n % 2 == 0) return true;
return false;
}
var result = checkEven(7);
console.log(result); //false
</script>
函式像一個小工廠

(十一)、練習題

<script>
//計算一個數字的階乘
function factorial(n) {
//累乘器
var result = 1;
for (var i = 1; i <= n; i++) {
result *= i;
}
return result;
}
//窮舉法
for (var i = 100; i <= 999; i++) {
// 把數字i變為字串
var i_str = i.toString();
var a = Number(i_str[0]);
var b = Number(i_str[1]);
var c = Number(i_str[2]);
// 根據喇叭花數來判斷
if (factorial(a) + factorial(b) + factorial(c) == i) {
console.log(i);//145
}
}
</script>
(十二)、JavaScript內置的sort()方法
這個函式中的a、b分別表示陣列中靠前和靠后的項,如果需要將他們交換位置,則回傳正數,否則就回傳負數


<script>
var arr = [3, 5, 6, 1, 2];
arr.sort(function(a, b) {
return a - b;
})
console.log(arr);
var arr = [99, 55, 66, 77];
arr.sort(function(a, b) {
return b - a;
})
console.log(arr);
</script>

(十三)、什么是遞回?
-
函式的內部陳述句可以呼叫這個函式自身,從而發起對函式的一次迭代,
-
在新的迭代中,又會執行呼叫函式自身的陳述句,從而又產生一次迭代,當函式執行到某一次時,不再進行新的迭代,函式被一層一層回傳,函式被遞回遞
-
歸是一種較為高級的編程技巧,它把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,

<script>
//書寫一個函式 函式會自己呼叫自己 從而形成遞回
//函式的功能就是計算某個階乘 n的階乘就是n*(n-1)的階乘
function factorial(n) {
//遞回的出口 如果計算1的階乘,可以不用遞回了 直接告訴你答案1
if (n == 1) return 1;
//如果詢問的不是1的階乘就回傳n*(n-1)!
return n * factorial(n - 1);
}
var result = factorial(6);
console.log(result); //720
</script>
遞回的要素
- 邊界條件:確定遞回到何時終止,也稱為遞回出口
- 遞回模式:大問題是如何分解為小問題的,也稱為遞回體
遞回的常見演算法題

<script>
// 撰寫一個函式 這個函式的功能就是回傳斐波那契數列中下標為n的那項的值
function fib(n) {
//出口 數列的小標為0和下標為1的項的值都是1
if (n == 0 || n == 1) return 1;
// 斐波那契數列的本質特征就是每一項都等于前面兩項的和
return fib(n - 1) + fib(n - 2);
}
//書寫一個回圈陳述句 計算斐波那契數列的前15項
for (var i = 0; i < 15; i++) {
console.log(fib(i));
}
</script>

(十四)、實作深克隆

<script>
//原陣列
var arr1 = [33, 44, 11, 22, [77, 88],
[11, 999]
];
//結果陣列 "每一個都有一個結果"
var result = [];
//函式 這個 函式會被遞回
function deepClone(arr) {
//遍歷陣列的每一項
for (var i = 0; i < arr.length; i++) {
//型別判斷 如果遍歷到的項是陣列
if (Array.isArray(arr[i])) {
//遞回
result.push(deepClone(arr[i]));
} else {
//如果遍歷到的項不是陣列,是基本型別,就直接推入到結果陣列中
//相當于是遞回的出口
result.push(arr[i])
}
}
//回傳結果陣列
return result;
}
//測驗一下
var arr2 = deepClone(arr1);
console.log(arr2);
//是否藕斷絲連
console.log(arr1[4] == arr2[4]);
arr1[4].push(99);
console.log(arr1)
console.log(arr2);
</script>
如何實作深克隆?
使用遞回的思想,整體思路和淺克隆相似,但稍微進行一些改動,如果遍歷到項是基本型別值,則直接推入結果陣列,如果遍歷到的項是又是陣列,則重復執行淺克隆的操作,
(十五)、淺克隆

<script>
//準備原陣列
var arr1 = [33, 44, 55, 66, [99, 22], 111];
//準備一個結果陣列
var result = [];
//遍歷原陣列
for (var i = 0; i < arr1.length; i++) {
result.push(arr1[i]);
}
//輸出結果陣列
console.log(result);
// 測驗是否實作了克隆 ,就是說本質上是記憶體中的不同陣列了
console.log(arr1 == result); // false
//測驗這樣的克隆是淺克隆“藕斷絲連”
arr1[4].push(100);
console.log(result);
</script>

(十六)、全域變數和區域變數
變數的作用域
JavaScript是函式級作用域編程語言:變數只在其定義時所在的function內部有意義

全域變數
如果不將函式定義在任何函式的內部,此時這個變數就是全域變數,它在任何函式內都可以被訪問和更改

(十七)、遮蔽效應
遮蔽效應:如果函式中也定義了和全域同名的變數,則函式內的變數會將全域的變數遮蔽


(十八)、考慮變數提升的情況


(十九)、形參也是區域變數

<script>
var a = 10;
function fun(a) {
a++;
console.log(a); //8
}
fun(7);
console.log(a); //10
</script>
(二十)、作用域鏈
一個函式內部也可以定義一個函式,和區域變數相似,定義在一個函式內部的函式是區域函式

作用域鏈:在函式嵌套中,變數會從內到外逐層尋找他的定義

<script>
var a = 10;
var b = 20;
function fun() {
var c = 30;
function inner() {
var a = 40;
var d = 50;
console.log(a, b, c, d); //40 20 30 50
}
inner();
}
fun();
</script>
不加var 將定義全域變數
在初次給變數賦值的時候,如果沒有加var, 則將定義全域變數

<script>
var a = 1;
var b = 2;
function fun() {
//字母c沒有加var 關鍵字 所以他為全域變數
c = 3;
var b = 4;
b++;
c++;
}
fun();
console.log(b); //2
//在函式的外部是可以訪問變數c的
console.log(c); //4
</script>
(二十一)、閉包

什么是閉包:閉包是函式本身和該函式宣告時所處的環境狀態的組合 ,函式能夠“記憶住”其定義所處的環境,即使函式不在其定義的環境中被呼叫,也能訪問定義時所處的環境變數
<script>
//創建一個函式
function fun() {
//定義區域變數
var name = '慕課網';
//回傳一個區域函式
return function() {
alert(name)
}
}
//呼叫外部函式就能得到內部函式
var inner = fun();
//定義一個全域變數
var name = 'ABC';
//執行inn函式 就相當于在 fun函式的外部執行了內部的函式
inner()
</script>
觀察閉包的現象
在JavaScript中,每次創建函式時都會創建閉包
但是,閉包往往需要將函式換一個地方執行,才能被觀察出來
閉包的用途
- 記憶性:當閉包產生時,函式所處壞境的狀態會始終保持在記憶體中,不會在外層函式呼叫后自動清除,這就是閉包的記憶性
<script>
function createCheckTemp(standardTemp) {
function checkTemp(n) {
if (n <= standardTemp) {
alert("你的體溫正常")
} else {
alert("你的體溫偏高")
}
}
return checkTemp;
}
//創建一個 checkTemp函式,它以37.1為標準線
var checkTemp_A = createCheckTemp(37.1);
//創建一個 checkTemp函式,它以37.3為標準線
var checkTemp_B = createCheckTemp(37.3);
checkTemp_A(37.2);
checkTemp_B(37.2);
</script>
閉包的用途—模擬私有變數

<script>
//封裝一個變數 這個函式的功能是私有化變數
function fun() {
// 定義一個區域變數 a
var a = 0;
return {
getA: function() {
return a;
},
add: function() {
a++;
},
pow: function() {
a *= 2;
}
}
}
var obj = fun();
//如果想在fun函式外面使用變數a唯一的辦法就是呼叫getA() 方法
console.log(obj.getA());
//想讓 a進行加一操作
obj.add();
console.log(obj.getA());
obj.pow();
console.log(obj.getA());
</script>
使用閉包的注意點
不能濫用閉包,否則會造成網頁的性能問題,嚴重時可能會導致記憶體泄漏,所謂記憶體泄漏是指程式中已動態分配的記憶體由于某種原因未釋放或者無法釋放

<script>
function addCount() {
var count = 0;
return function() {
count = count + 1;
console.log(count);
}
}
var fun1 = addCount();
var fun2 = addCount();
fun1(); //1
fun2(); //1
fun2(); //2
fun1(); //2
</script>
(二十二)、IIFE
IIFE(Immediately Invoked Function Expression立即呼叫函式運算式)是一種特殊的JavaScript函式寫法,一旦被定義,就立即被呼叫

形成IIFE 的方法
函式不能直接加圓括號被呼叫

函式必須轉為函式運算式才能被呼叫

IIFE的作用
為變數賦值:當給變數賦值需要一些較為復雜的計算的時候(如if陳述句)使用IIFE顯得語法更緊湊

IIFE可以在一些場合(如for回圈)將全域變數變為區域變數語法顯得更緊湊


(四十一)、流程控制陳述句
if陳述句的基本使用





//要求輸入三位數
var n = Number(prompt('請輸入三位數'));
//對用戶輸入的值進行合法驗證
if (!isNaN(n) && 100 <= n && n <= 999) {
var a = parseInt(n / 100);
var b = parseInt(n / 10) % 10;
var c = n % 10;
if (Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3)) {
alert('是水仙花數');
}
} else {
alert('您輸入的數字不合法')
}
(四十二)、switch陳述句
switch陳述句的用途:當一個變數被分類討論的情形


switch陳述句并不像if陳述句那樣當執行了某個分支后會自動跳出if陳述句,我們必須主動呼叫break陳述句來跳出break陳述句體,如果不書寫break,則后面的所有case都將被視為匹配,直到遇見break

<script>
//讓用戶輸入月份
var month = Number(prompt('請輸入月份'));
//分類討論
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
alert('這個月有31天');
break;
case 4:
case 6:
case 9:
case 11:
alert('這個月有28天');
break;
case 2:
alert('這個月有28天或者29天');
break;
default:
alert('你輸入的月份有誤')
}
</script>
(四十三)、三元運算子
三元運算子的用途:根據某個條件是否成立,在兩個不同值中選擇變數的值


(四十四)、for回圈

for回圈陳述句的執行機理


準確遍歷for回圈





<script>
//sum是累加器 初始值是0
for (var i = 1, sum = 0; i <= 100; i++) {
sum += i;
}
console.log(sum); //5050
</script>

//窮舉法
for (var i = 1; i < 100; i++) {
if (i % 3 == 1 && i % 4 == 2 && i % 5 == 3) {
console.log(i); //58
}
}
(四十五)、while回圈陳述句
-
while陳述句也是一種回圈陳述句,是一種不定范圍的回圈,和for回圈各有不同的用武之地,幾乎所有的回圈都同時提供for回圈和while回圈
-
while陳述句事先不指定回圈的開始,結束的范圍,只要測驗條件滿足,就一直執行回圈
-
while回圈沒有顯示定義回圈變數,必須自己在while回圈外先定義好回圈變數,有時候甚至沒有回圈變數
-
回圈體內的陳述句,必須使回圈測驗條件趨向不成立,否則會死回圈

var i = 1;
while (i <= 100) {
console.log(i);
i++;
}
//尋找滿足n的平方和大于456789的最小整數
//窮舉法 從1開始試驗
var n = 1;
while (n * n < 456789) {
n++;
}
console.log(n); //676

var n = 1;
var sum = 0;
while (sum < 500) {
sum += n;
n++;
}
//注意這里有個“出一錯誤”
console.log(n - 1); //32
(四十六)、break和continue
break表示立即終止這個回圈,他只能用在回圈陳述句中,在for回圈和while回圈中都可以使用


continue用于跳過回圈中的一個迭代,并繼續執行回圈中的下一個迭代,for回圈中經常使用continue

(四十七)、do while陳述句


<script>
//后判斷的一種形式 至少執行一次回圈體
do {
console.log('★');
} while (false); //★
</script>
var n = 1;
do {
console.log(n);
n++
} while (n <= 100);
(四十八)、亂數函式
亂數函式得到0到1之間的小數



(四十九)、do while 小案例

<script>
do {
var dx = parseInt(Math.random() * 9) - 4;
var dy = parseInt(Math.random() * 9) - 4;
}
while (dx == 0 && dy == 0);
console.log(dx, dy);
</script>
(五十)、猜數字小游戲

<script>
//隨機一個數字2-99
var answer = parseInt(Math.random() * 98) + 2;
//此時范圍的最大值和最小值這個數字是用來提示用戶的
var min = 1;
var max = 100;
//不斷的重復 就用死回圈
while (true) {
//詢問用戶猜測的數字
var n = Number(prompt('請猜猜數字' + min + '~' + max));
//驗證用戶輸入的數字是否在范圍內
if (n <= min || n >= max) {
alert('你輸入的數字不在范圍內')
//放棄這次回圈,就開啟下一次迭代
continue;
}
//判斷用戶輸入的數字和answer的關系
if (n > answer) {
alert('你輸入的數字太大了');
//因為用戶輸入的數字較大,所以可以讓此時的最大范圍的數字變為用戶輸入的值
max = n;
} else if (n < answer) {
alert('你輸入的數字太小了')
//因為用戶輸入的數字較小,所以可以讓此時的最小范圍的數字變為用戶輸入的值
min = n;
} else {
alert('猜對了');
//結束死回圈
break;
}
}
</script>
(五十一)、什么是演算法
-
演算法是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法描述解決問題的策略機制,也就是說,能夠對一定規范的輸入,在有限時間內獲得所要求的輸出
-
演算法就是把一個問題,拆解為計算機能夠一步一步執行的步驟
優秀演算法的要求
- 正確性
- 健壯性
- 可讀性
(五十二)、偽代碼

(五十三)、演算法如何培養
- 多敲、多練、多總結
- 經典的業務需求場景要熟記心間
(五十四)、累加器


//用戶輸入數字n
var n = Number(prompt('請輸入數字'));
//累加器
var sum = 0;
//遍歷分母
for (var i = 2; i <= n; i++) {
sum += (i + 1) / i
}
alert(sum.toFixed(2));
(五十五)、累乘器

<script>
//計算階乘
var n = Number(prompt('請輸入數字'));
//累乘器 從1開始 如果要從0開始 0乘以任何數字都為0
var result = 1;
//倒著遍歷 計算階乘
for (var i = n; i >= 1; i--) {
result *= i;
}
alert(result);
</script>
(五十六)、窮舉法
計算機最突出的能力就是計算,他沒有歸納總結,推理邏輯的能力,所以人們使用計算機解決問題的時候,要揚長避短,充分發揮計算機的優勢,而不要讓他們進行邏輯推理,窮舉法就是這樣一種演算法思想,
什么是窮舉法?
窮舉法,顧名思義,是指根據題目的條件確定答案的大致范圍,并在此范圍內對所有可能的情況逐一驗證,直到全部的情況驗證完畢,若某個情況符合題目的條件,則為本題的一個解,若全部情況驗證后都不符合條件,則本題無解,

//窮舉法
for (var i = 1; i <= 100; i++) {
if (i % 3 == 0 && i % 5 == 0) {
console.log(i);
}
}
//尋找約數
var n = Number(prompt('請輸入數字:'));
//窮舉法
for (var i = 1; i <= n; i++) {
if (n % i == 0) {
console.log(i);
}
}
//尋找水仙花數
for (var i = 100; i < 1000; i++) {
var i_str = i.toString();
var a = i_str.charAt(0);
var b = i_str.charAt(1);
var c = i_str.charAt(2);
if (Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3) == i) {
console.log(i);
}
}
(二十三)、DOM簡介


(二十四)、nodeType常用的屬性

(二十五)、訪問元素節點
所謂的訪問元素節點就是指得到,獲取頁面上的元素節點
對節點進行任何的操作,就是要得到節點,訪問節點主要依靠document物件
認識document物件

(二十六)、訪問元素節點常用的方法

(二十七)、getElementById ()
- 如果頁面上有相同的id元素 則只能得到第一個
- 不管元素藏得位置有多深,都能通過Id把它找到

延遲運行


(二十八)、getElementsByTagName()

注意事項:
- 陣列方便遍歷,從而可以批量操控元素節點
- 即使頁面上只有一個指定標簽名的節點,也得到長度為1的陣列
- 任何一個節點元素也可以呼叫getElementsByTagName()方法,從而得到內部的某種類的元素節點

(二十九)、getElementsByClassName()



(三十)、querySelector()



(三十一)、querySelectorAll()


(三十一)、節點的關系


文本節點也屬于節點
在標準的W3C規范中,空白文本節點也應該算作節點,但是在IE8以及以前的節點中也會有一定的兼容問題,他們不把空文本節點當位元組點


(三十二)、節點的操作
改變元素節點中的內容可以使用兩個相關的屬性

innerHTML屬性能夠以HTML語法設定節點中的內容
innerText屬性只能以純文本的形式設定節點中的內容

(三十三)、如何改變元素節點的CSS樣式


(三十四)、如何改變元素節點的HTML屬性

(三十五)、節點的創建


appendChild()

insertBefore()

<body>
<div id="box">
<p>我是原本的段落0</p>
<p>我是原本的段落1</p>
<p>我是原本的段落2</p>
</div>
<script>
var oBox = document.getElementById('box');
var oPs = oBox.getElementsByTagName('p');
//創建孤兒節點
var oP = document.createElement('p');
//設定內部文字
oP.innerHTML = '我是新來的'
//上樹
//oBox.appendChild(oP);
oBox.insertBefore(oP, oPs[0])
</script>
</body>

(三十六)、移動節點

(三十七)、洗掉節點



(三十八)、克隆節點



(三十九)、事件監聽
什么是事件:用戶與網頁的互動動作
比如:當用戶點擊元素時,當滑鼠移動到元素上時,當文本框的內容被改變時、當鍵盤在文本框中被按下時,當網頁加載完畢時……
什么是事件監聽?
監聽,顧名思義,就是讓計算機能夠發現這個事件發生了,從而執行程式員預先撰寫的一些程式


<style>
div {
width: 200px;
height: 200px;
background-color: #ccc;
}
</style>
</head>
<body>
<div id="box">
</div>
<script>
var oBox = document.getElementById('box');
//給這個盒子添加點擊事件監聽
oBox.onclick = function() {
alert('你好,我是點擊事件的函式');
}
</script>
(四十)、常見的滑鼠事件監聽


(四十一)、常見的鍵盤事件


(四十二)、常見的表單事件監聽

(三十九)、事件監聽
什么是事件:用戶與網頁的互動動作
比如:當用戶點擊元素時,當滑鼠移動到元素上時,當文本框的內容被改變時、當鍵盤在文本框中被按下時,當網頁加載完畢時……
什么是事件監聽?
監聽,顧名思義,就是讓計算機能夠發現這個事件發生了,從而執行程式員預先撰寫的一些程式


<style>
div {
width: 200px;
height: 200px;
background-color: #ccc;
}
</style>
</head>
<body>
<div id="box">
</div>
<script>
var oBox = document.getElementById('box');
//給這個盒子添加點擊事件監聽
oBox.onclick = function() {
alert('你好,我是點擊事件的函式');
}
</script>
(四十)、常見的滑鼠事件監聽


(四十一)、常見的鍵盤事件


(四十二)、常見的表單事件監聽

(四十五)、常見的頁面監聽事件

(四十六)、事件傳播




<script>
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");
// box1.onclick = function() {
// alert('A');
// }
// box1.onclick = function() {
// alert('B '); //B
// }
box2.addEventListener("click", function() {
alert('C ');
}, false)
box2.addEventListener("click", function() {
alert('D '); //先C再D
}, false)
</script>
(四十七)、事件物件
事件處理函式提供一個形式引數,它是一個物件,封裝了本次事件的細節,這個引數通常用單詞event或者字母e來表示

(四十八)、滑鼠位置




<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 200px;
height: 200px;
background-color: #333;
margin: 100px;
padding: 50px;
}
body {
height: 2000px;
}
#info {
font-size: 30px;
}
</style>
</head>
<body>
<div id="box">
</div>
<div id="info">
</div>
<script>
var oBox = document.getElementById('box');
var oInfo = document.getElementById('info');
oBox.onmouseover = function(e) {
oInfo.innerHTML = 'offsetX / Y: ' +
e.offsetX + ',' + e.offsetY + '<br/>' + 'clientX/Y:' + e.clientX + ',' + e.clientY;
}
</script>

(四十九)、字符碼

鍵碼

<script>
var oList = document.getElementById('list');
var lis = oList.getElementsByTagName('li');
// 書寫回圈陳述句 批量添加監聽
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function() {
this.style.color = ' red';
}
}
</script>

批量添加事件監聽的性能問題
每一個事件監聽注冊都會消耗一定的系統記憶體,而批量添加事件會導致監聽數量太多,記憶體消耗十分的大
實際上,每個li 的事件處理函式都是不同的函式,這些函式本身也會占用記憶體
(五十)、事件委托
利用事件冒泡機制,將后代元素事件委托給祖先元素




<button id="btn">按我創建一個新串列項</button>
<ul id="list">
<li>串列項</li>
<li>串列項</li>
<li>串列項</li>
</ul>
<script>
var oList = document.getElementById('list');
var oBtn = document.getElementById('btn')
oList.onclick = function(e) {
//e.target表示用戶真正點擊的那個元素
e.target.style.color = 'red';
// e.currentTarget表示整個串列項
// e.currentTarget.style.color = 'blue';
}
oBtn.onclick = function() {
//創建新的li元素
var oLi = document.createElement('li');
//寫內容
oLi.innerText = ' 我是新來的';
//上樹
oList.appendChild(oLi);
}
</script>


(五十一)、定時器和延時器

函式的引數

具名函式也可以傳入setInterval

什么是具名函式? 什么是匿名函式?
具名函式,故名思意就是有名字的函式,具名函式一般是我們定義的最多的一種
// 函式
function fn() {
console.log('我是具名函式')
console.log('看,我有名字')
console.log('我的名字叫 fn')
}
fn()
fn()
匿名函式
沒有名字的函式,匿名函式我們也隨處可見,我們來寫幾個匿名函式
setTimeout(function () {
console.log('我是匿名函式,我被用于定時器引數傳遞')
}, 1000)
let arr = [1, 2, 3]
arr.forEach(function (item) {
console.log('我是匿名函式,我被用于回呼函式引數')
})
let box = document.querySelector('#box')
box.onclick = function () {
console.log('我是匿名函式,我被用于系結事件')
}
(五十二)、清除定時器

<h1 id="info"></h1>
<button id="btn1">開始</button>
<button id="btn2">暫停</button>
<script>
var oInfo = document.getElementById('info')
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var a = 0;
//設定一個全域變數
var timer;
btn1.onclick = function() {
//為了防止定時器疊加 我們應該在設定定時器之前清除定時器
clearInterval(timer)
//更改全域變數的值為一個定時器物體
timer = setInterval(function() {
oInfo.innerText = ++a;
}, 1000)
}
btn2.onclick = function() {
clearInterval(timer)
}
</script>
延時器


<button id="btn1">2秒后彈出你好</button>
<button id="btn2">2秒后取消彈出</button>
<script>
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var timer;
btn1.onclick = function() {
timer = setTimeout(function() {
alert('你好,世界!');
}, 2000)
}
btn2.onclick = function() {
clearInterval(timer);
}
</script>
(五十三)、初識異步函式


(五十三)、什么是BOM?

- Window物件是當前JS腳本運行所處的視窗,而這個視窗中包含DOM物件,window. document屬性就是document物件
- 在有標簽頁的瀏覽器功能中,每個標簽都擁有自己的window物件,也就是說,同一個視窗的標簽頁之間不會共享一個window物件
全域變數是window的屬性

以上結果就意味著,多個JS檔案之間是共享作用域的,即JS檔案沒有作用域隔離的功能

內置函式普遍是window的方法

(五十四)、視窗尺寸相關的屬性



(五十五)、resize事件


(五十六)、已卷動的高度



(五十七)、scroll事件


(五十八)、Navigator物件




(五十九)、History物件
常用的操作就是模擬瀏覽器的回退按鈕

(六十)、Location物件

重新 加載當前頁面



(六十一)、BOM特效開發回傳頂部
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
height: 5000px;
background-image: linear-gradient(to bottom, blue, green, yellow);
}
.backtotop {
width: 60px;
height: 60px;
background-color: rgba(255, 255, 255, 0.6);
position: fixed;
bottom: 100px;
right: 100px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="backtotop" id="backtotopbtn">回傳頂部</div>
<script>
var backtotopbtn = document.getElementById("backtotopbtn");
var timer;
backtotopbtn.onclick = function() {
//設定表先關
clearInterval(timer);
//設定定時器
timer = setInterval(function() {
//讓scrollTop不斷減少
document.documentElement.scrollTop -= 80;
// 定時器停下來
if (document.documentElement.scrollTop <= 10) {
clearInterval(timer);
}
}, 20)
}
</script>
</body>
</html>
面向物件
(六十二)、認識物件
物件是鍵值對的集合,表示屬性和值的映射關系

(六十三)、物件的語法


屬性的訪問
可以使用“點語法”訪問物件中指定鍵的值

如果屬性不符合JS識別符號的命名規范,則必須使用方括號的寫法來訪問

如果屬性名以變數的形式存盤,則必須使用方括號的形式

屬性的更改
直接使用賦值運算子重新對某屬性賦值即可更改屬性

屬性的創建
如果物件本身沒有某個屬性值,則用點語法賦值時,這個屬性就會被創建出來

屬性的洗掉
如果要洗掉某個物件的屬性,需要使用delete運算子


(六十四)、物件的方法
如果某個屬性值是函式,則它也被稱為物件的方法
方法的呼叫:使用點語法可以呼叫物件的方法

方法和函式
方法和函式,只不過方法是物件的函式屬性,它需要用物件打點呼叫
物件的遍歷
和遍歷陣列類似,物件也可以被遍歷,遍歷物件需要使用for…in…回圈,使用for…in回圈需要可以遍歷物件的某個鍵

(六十五)、基本型別和參考型別的值

物件是參考型別值
物件是參考型別的值,這就意味著:





<script>
var obj1 = {
a: 1,
b: 2,
c: [33, 44, {
m: 55,
n: 66,
p: [77, 88]
}]
};
//實作深克隆
function deepClone(o) {
//要判斷o是物件還是陣列
if (Array.isArray(o)) {
//陣列
var result = [];
for (var i = 0; i < o.length; i++) {
result.push(deepClone(o[i]))
}
} else if (typeof o == "object") {
//物件
var result = {};
for (var k in o) {
//遞回之后的原來的值
result[k] = deepClone(o[k]);
}
} else {
//基本型別值
var result = o;
}
return result;
}
var obj2 = deepClone(obj1);
console.log(obj2);
//看是否有藕斷絲連的情況
//參考型別的值互不相等
console.log(obj1.c == obj2.c); //false
obj1.c.push(99);
console.log(obj2); //obj2不變 因為沒有藕斷絲連的現象
obj1.c[2].p.push(99);
console.log(obj1);
</script>
(六十六)、認識背景關系
什么是背景關系?


函式的背景關系
-
函式中可以使用this關鍵字,它表示函式的背景關系
-
與中文中的這類似,函式中的this具體指代什么必須通過呼叫函式時的前言后語來判斷
函式中的this



由以上可知,函式的背景關系是由函式的呼叫方式來決定的,也就是說同一個函式,用不同的形式來呼叫它,則函式的背景關系不同
以上兩個例子:
情形一:物件打點呼叫函式,函式中的this指代這個打點的物件

情形二:圓括號直接呼叫函式,函式中的this指代的是window物件

來個案例

這個題目中這兩個this指代的是啥:不知道!!因為函式只有被呼叫的時候它的背景關系才能被確定,因此 函式的背景關系是不能被確定的,

輸出3

輸出NaN




規則1題目舉例—第一小題

規則1題目舉例—第二小題


規則1題目舉例—第三小題


規則二
規則二:圓括號直接呼叫函式,則函式的背景關系是window物件

規則二—第一題


規則二—第二題


背景關系規則三
規則三:陣列(類陣列物件)列舉出函式進行呼叫,背景關系是這個陣列(類陣列物件)

規則三—第一題


什么是類陣列物件?
所有鍵名為自然數序列(從0開始),且有length屬性的物件
arguments物件是最常見的類陣列物件,它是函式的實參串列
規則三題目一

規則四
IIFE函式,背景關系是window物件



規則五
規則五:定時器,延時器呼叫函式,背景關系是window物件


輸出結果:7

背景關系規則六
規則六:事件處理函式的背景關系是系結事件的DOM元素


練習小demo


(六十七)、call和apply能夠指定函式的背景關系


(六十八)、 call和apply的區別


到底使用call還是apply?

(六十九)、背景關系規則總結

(七十)、用new運算子呼叫函式
JS規定,使用new運算子呼叫函式會進行四步走:
- 函式體內會自動創建出一個空白物件
- 函式的背景關系(this)會指向這個物件
- 函式體內的陳述句會執行
- 函式會自己回傳背景關系物件,即使函式沒有return陳述句

(七十一)、建構式
什么是建構式?
- 用new呼叫一個函式,這個函式就被稱為建構式,任何函式都可以是建構式,只需要用new呼叫它
- 顧名思義,建構式用來構造新物件,它內部的陳述句將為新物件添加若干屬性和方法,完成物件的初始化
- 建構式必須使用new關鍵字呼叫,否則不能正常作業,因此,開發者約定建構式命名時首字母要大寫



如果不用new呼叫建構式

建構式中的this不是函式本身

嘗試為物件添加方法


(七十二)、類與實體



建構式和類
-
Java、C++等是“面向物件”(object-oriented)的語言
-
JavaScript是“基于物件(object-based)的語言”
-
JavaScript中的建構式可以類比于OO語言中的類,寫法的確類似,但和真正OO語言還是有本質的不同
(七十三)、prototype和原型鏈查找
什么是prototype?
- 任何函式都有prototype屬性,prototype表示“原型”的意思
- prototype屬性值是一個物件,它默認擁有constructor屬性指回函式



原型鏈查找



(七十四)、hasOwnProperty方法

(七十五)、in
in運算子只能檢查某個屬性或者方法是否可以被物件訪問,不能檢查是否是自己的屬性或者方法



原型鏈的終點


關于陣列的原型鏈


(七十六)、繼承
兩個無關的類


People和Student的關系
- People類擁有的屬性和方法Student類都有,Student類還擴展了一些屬性和方法
- Student是一種People,兩類之間是“is a kind of”關系
- 這就是繼承關系,Student類繼承People類
- 繼承描述了 兩個類之間的關系,比如學生是一種人,所以人類和學生之間就構成繼承的關系
- People是“父類”(“超類”,“基類”);Student是“子類”(或者派生類)
更多的繼承關系舉例

(七十七)、JavaScript中如何實作繼承
實作繼承的關鍵在于:子類必須擁有父類的全部屬性和方法,同時還應該能定義自己特有的屬性和方法,使用特有的原型鏈特性來實作繼承,是普遍的做法
通過原型鏈來實作繼承



(七十八)、面向物件到底是什么
-
面向物件的本質:定義不同的類,讓類的實體作業
-
面向物件的優點:程式撰寫更清晰,代碼結構更加嚴密,使代碼更健壯易于維護
-
面向物件經常用到的場合,需要封裝和復用性的場合(組件思維)
(七十九)、包裝類




包裝類知識點總結

包裝類的目的就是為了讓基本型別值可以從他們的建構式的prototype上獲得方法
(八十)、Math物件的方法





(八十一)、Date()日期物件



時間戳
- 時間戳表示1970年1月1日零點距離某時刻的毫秒數
- 通過getTime()方法或則Date.parse()函式可以將日期物件變為時間戳
- 通過new Date(時間戳)的寫法,可以將時間戳變為日期物件


(八十二)、正則運算式知識點總結
一、什么是正則運算式
- 正則運算式也稱為規則運算式,就是普通字符和特殊字符構成的一個運算式
- 作用就是用來檢驗字串是否符合格式要求,或者在字串中查找是否有符合格式要求的字串,
二、如何創建正則運算式
- 利用構造方法創建:
var 正則運算式的名稱=new RegExp('正則運算式內容','修飾符');

- 利用字面量形式創建:
var 正則運算式的名稱=/ 正則運算式內容/修飾符;
三、正則運算式的常用方法—test方法
-
作用:驗證字串是否符合正則運算式的格式要求
-
格式:
正則運算式.test(字串) -
回傳值:true(符合要求)、false(不符合)

四、正則運算式的構成
(一)普通字符
- 如字母、數字0-9、a-z、A-Z、_
(二)、特殊字符(元字符)
(1)、定位符
^:表示以某個字符開頭,如/^a/表示字串以字母a開頭

$:表示以某個字符結尾,如/$a/表示字串以a結尾



(2)、表示數量的限定符
-
*:表示它前面的字符的個數為0到無窮多個,如/a*/表示a的個數最少0個,最多無限個 -
+:表示他前面的字符的個數為1到無窮多個,如/a+/表示 a的個數最少1個,最多無限個
-
?:表示他前面的字符為0到1個,如/a?/表示a的個數最少0個,最多一個
-
{n}:表示他前面的字符只能是n個.如/a{3}/表示字串中包含3個字符a
-
{n, }:表示他前面的字符為n到無窮多個,如/a{3, }/表示字串 a的個數大于等于3個
-
{n,m}:表示他前面的字符的個數為n-m個.如a{1,5}表示a的個數為1-5個
(3)、轉義字符
轉義字符:所謂轉義字符就是指在普通字符的前面加反斜線,使得他具有特定的功能和含義,也可以在具有特定的功能和含義的字符前面加反斜線,將他轉換為普通字符 如:\d表示任意一個數字/\表示將正則運算式中的斜線轉換為普通的斜線
-
\d:表示任意一個數字
-
\D:表示任意一個非數字
-
\w:表示任意一個字母、數字、下劃線
-
\W:任意一個非字母數字下劃線
-
\s:表示任意一個空白符,比如制表符、空格
-
\S:任意一個非空白符
(4)、備選字符集
-
[值1 值2 值3 值4]:中括號里面的值表示字串中可以匹配到的任意一個值 -
[值1-值n]:表示值1到值n間的任意一個值為備選選項 -
[^值1 值2 值3]:表示字串中不可以包含中括號里面的任意一個值 -
[\u4e00-\9fa5]:表示任意的一個漢字
四、正則運算式的匹配模式
1)貪婪模式:指正則運算式在對字串進行匹配時盡可能多的匹配字符,默認就是貪婪模式
2)懶惰模式:指正則運算式在對字串進行匹配時盡可能少的匹配字符,默認是貪婪模式,如果要將貪婪模式轉化為懶惰模式,需要在數量修飾符后面加問號



(五)、字串物件中和正則運算式結合使用的方法
(一)、split方法
- 作用:將字串轉化為陣列
- 格式:
字串名稱.splite('分隔符');



(二)、match方法
- 作用:從字串中查找到符合條件的
- 格式:字串.match(子串);
- 回傳值:由子串形成的陣列,默認只回傳找到符合條件的第一個子串,如果要找到符合條件的所有的子串需要使用正則運算式作為引數



(三)、repalce方法
-
作用:替換字串中指定的子串
-
格式:
字串.repalce.('要被替換的子串','新的子串'); -
回傳值:默認情況下,只替換符合條件的第一個子串,如果要將所有的子串替換掉,則需要使用正則運算式 且這個正則運算式需要使用修飾符g,如果要替換的子串不存在則回傳原串
(四)、search方法
- 作用:在字串從左向右查找子串位置,如果存在則回傳該子串對應的下標,否則回傳-1,功能類似于
indexOf方法 - 格式:
字串.search('子串'); - 注意:該方法可以和正則運算式結合使用,但是就算正則運算式中有修飾符g,在匹配的時候也只能回傳查找到的第一個子串

六、正則運算式常用的修飾符
- i:表示忽略大小寫
- g:表示全域匹配
- ig/gi:表示既忽略大小寫也全域匹配





轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/318008.html
標籤:其他
