console.log (a); // 先使用變數var a = 12; // 後定義變數
基本資料型別
Number
3e8
就是3^8
0b
開頭,八進制以0
開頭,十六進制以0x
開頭NaN
,not a number,即“不是一個數”,但它是一個數字類型的值(數學運算中,若結果不能得到數字,結果往往都是NaN,NaN == NaN結果為false)String
方法 | 功能 |
---|---|
charAt() | 得到指定位置字元(越界為空字串) |
substring() | 提取子字串 |
substr() | 提取字符串 |
slice() | 提取子字串 |
toUpperCase() | 將字串變為大寫 |
toLowerCase() | 將字串變為小寫 |
indexOf() | 檢索字串(模式匹配) |
Boolean
Undefined
Null
複雜資料型別
可以用來偵測值或變數的類型
typeof 5; // numbertypeof 'niubi'; // string
類型名稱 | typeof 偵測結果 | 值 |
---|---|---|
範例數字類型 | number | 5 |
字串型別 | string | 'niubi' |
布林型別 | boolean | true |
undefined | undefined | undefined |
null型 | 別object | null |
使用**Number ()**函數
// 字串--> 數字Number('123'); // 123Number('123.4'); // 123.4Number('123年'); // NaNNumber('2e3'); / / 2000Number(''); // 0Number('1 + 1'); // NaN// 布林值--> 數字Number(true); // 1Number(false); // 0// undefined 與null - -> 數字Number(undefined); // NaNNumber(null); // 0
**parseInt()**函數將字串轉為整數
將自動截掉第一個非數字字元之後的所有字元
parseInt('3.14 '); // 3parseInt('3.14是圓周率'); // 3parseInt('圓周率是3.14'); // NaNparseInt('3.99'); // 3
**parseFloat()**函數將字串轉為浮點數
自動截掉第一個非數字字元、非小數點之後的所有字元
parseFloat('3.14'); // 3.14parseFloat('3.14是圓周率'); // 3.14parseFloat('圓周率是3.14'); / / NaNparseFloat('3.99'); // 3.99// 會自動將true和false轉為字串,結果為NaN
**String()**函數
變成「長得相同」的字串。科學計數法與非10進位數字會轉為10進位的值
String(123); // '123'String(123.4); // '123.4'String(2e3); // '2000'String(NaN ); // 'NaN'String(Infinity); // 'Infinity'String(0xf); // '15'String(true); // 'true'String(false); // 'false'String(undefined ); // 'undefined'String(null); // 'null'
**Boolean()**函數
// 數字--> 布林值0和NaN轉為false,其他轉為trueBoolean(123); // trueBoolean(0); // falseBoolean(NaN); // falseBoolean(Infinity); // trueBoolean(-Infinity); // true// 布林值--> 布林值空串轉為false,其他轉為true; Boolean(''); // falseBoolean('abc'); // trueBoolean('false'); // true// undefined 和null --> 布林值轉為falseBoolean(undefined); // falseBoolean(null) ; // false
**prompt()**函數函數彈出輸入框
var num = prompt('請輸入第一個數字'); // 傳回值為string
如果參與數學運算的某運算元不是數字型,那麼JavaScript會自動將此運算元轉換位元數位型
隱含轉換的本質就是內部呼叫Number()函數
3 * '4' // 12true + true // 2false + 2 // 23 * '2天' // NaN
Math.pow(2, 3) // 2^3Math.sqrt(81) // 9Math.ceil() // 向上取整Math.floor () // 向下取整
=== // 全等於!== // 不全等於// 兩個等號== 運算子不比較值的型別,它會進行隱式轉換後比較值是否相等1 == true // true1===true // false0 == false // true0 === false // false0 == undefined // false0 === undefined // falseundefined == null // trueundefined == = null // false
**isNaN()**函數判斷變數值是否為NaN
但isNaN()也不好用,它的機理是:只要變數傳入Number()的執行結果是NaN,則isNaN( )函數都會得到true
a && ba真,值為b;a假,值為a
a||ba真,值為a,a假,值為b
邏輯運算優先權:非--> 與- -> 或
綜合運算運算順序:非--> 數學運算--> 關係運算--> 邏輯運算
隨機數函數Math.random()
得到[a, b]區間的整數,公式為parseInt(Math .random() * (b - a + 1)) + a;
var arr = ['A', 'B', 'C', 'D']; var arr = new Array('A', 'B ', 'C', 'D');var arr = new Array(4); 長度為4的數組,每一項都是undefined
下標訪問越界時返回undefined
var arr = [2, 6, 7, 3 ];arr[6] = 4;console.log(arr);此時下標越界,不會報錯,而是會將數組擴展,下標6處為4,中間為emptyArray.isArray()方法可以用來檢測數組
函數定義
// 常規function fun() { // 函數體語句}// 匿名函數var fun = function () { // 函數體語句}
函數宣告的提升
fun();function fun() { // 在預解析階段會被提升alert("函數被執行");}// 如果函數時用函數表達式的寫法定義的,則沒有提升特性fun(); // 引發錯誤var fun = function () { alert("函數執行");}
函數優先提升
// 函數優先提升// 函數表達式後提升;變數宣告提升,無法覆蓋提升的函數fun(); // 彈出Bvar fun = function () { alert('A');}function fun() { alert('B');}fun(); // 彈出A
實參與形參個數不同
undefined
arguments類數組物件
var聲明與省略
在函數外,用var聲明的變量為全局變量,不用var聲明的變量為全局變量
在函數中,用var宣告的變數為局部變量,不用var宣告的變數為全域變數
同為全域變量,同為window物件的其中一個屬性,用var宣告的變數不可以刪除,不用var宣告的變數可以刪除!
回傳值
function sum(a, b) { return a + b;}var result = sum(3, 5); // 傳回值可被變數接收
若函數沒有回傳值,則對它印出的結果是undefined
sort(a, b)方法
這個函數中的a 、b分別表示數組中靠前和靠後的項,如果需要將它們交換位置,則返回任意正數;否則就返回負數
var arr = [33, 22, 11, 55];arr.sort(function ( a, b) { if (a > b) { return 1; } return -1;});
變數賦值
舉例 | 當var a = b變數傳值時 | 當用== 比較時 | |
---|---|---|---|
基本型別值 | 數字型、字串型、布林型、undefined型 | 記憶體中產生新的副本 | 比較值是否相等 |
引用型別值 | 物件、陣列記憶 | 體中不產生新的副本,而是讓新變數指向同一個物件 | 比較記憶體位址是否相同,即比較是否為同一個物件陣列 |
深度克隆
var arr1 = [1, 2, 3, [4, 5]];function deepClone( arr) { var result = []; 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;}
局部函數
定義在一個函數內部的函數是局部函數
只能在函數內部呼叫
function fun() { function inner() { console.log('你好'); } inner(); // 呼叫inner函數}fun();
作用域鏈
在函數嵌套中,變數會從內到外逐層尋找它的定義
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); // 使用變數時,js會從目前層開始,逐層向外尋找定義} inner();}fun();
閉包
閉包是函數本身和該函數宣告時所處的環境狀態的組合
函數能夠」記憶住「其定義時所處的環境,即使函數不在其定義的環境中被調用,也能存取定義時所處環境的變數
在js中,每次創建函數時都會創建閉包,但是閉包特性往往需要將函數」換一個地方「執行,才能被觀察出來
閉包的功能:
記憶性:當閉包產生時,函數所處環境的狀態會始終保持在記憶體中,不會在外層函數呼叫後自動清除。
function fun() { var name = 'niubi'; function innerFun() { alert(name); } return innerFun;}var inn = fun();inn(); // 內部函數被移到了外部執行模擬私有變數
function fun() { var a = 0; return function() { alert(a); }}var getA = fun();getA();function fun() { var a = 0; return { getA: function () { return a; }, add: function () { a++; }, pow: function () { a *= 2; } };}var obj = fun();console.log(obj.getA());obj.add();注意:不能濫用閉包,否則會造成網頁的效能問題,嚴重時可能導致記憶體洩漏。
立即呼叫函數IIFE
特殊寫法,一旦被定義,就立即被呼叫
函數必須轉為函數表達式才能被呼叫
(function () { // 透過圓括號將函數變成表達式// statements})();+ function() { alert(1);}();-function() { alert(1);}();
可以用來給變數賦值
var age = 12;var sex = '男';var title = (function () { if (age < 18) { return '小朋友'; } else { if (sex == '男') { return '先生'; } else { return '女士'; } }})();
在某些場合(如for迴圈中)將全域變數變成局部變量,語法更緊湊
var arr = [];for (var i = 0; i < 5; i++) { arr.push(function () { alert(i); });}arr[2](); // 彈出5
解決方法:
var arr = [];for (var i = 0; i < 5; i++) { (function (i) { arr.push(function() { alert(i); }); })(i);}arr[2](); // 彈出2
nodeType常用屬性值
節點的nodeType屬性可以顯示這個節點具體的型別
nodeType值 | 節點類型 |
---|---|
1 | 元素節點,例如 和 |
3個 | 文字節點 |
8 | 註解節點 |
9 | document節點 |
10 | DTD節點 |
document物件
存取元素節點主要依靠document物件
幾乎所有DOM的功能都被封裝到了document物件中
document物件也表示整個HTML文檔,它是DOM節點樹的根
存取元素節點的常用方法
方法 | 功能 |
---|---|
document.getElementById() | 透過id得到元素 |
document.getElementsByTagName() | 透過標籤名稱得到元素數組 |
document.getElementsByClassName() | 透過類別名稱得到元素數組 |
document.querySelector() | 透過選擇器得到元素 |
document.querySelectorAll() | 透過選擇器得到選擇器元素數組 |
document.getElementById()
如果頁面上有相同id的元素,則只能得到第一個
<p id = "box">我是一個盒子</p><p id = "para">我是一個段落</p>
var box = document.getElementById('box');var para = document.getElementById('para');
getElementsByTagName()
數組方便遍歷,從而可以批量操控元素節點
即使頁面上只有一個指定標籤名的節點,也會得到長度為1的陣列
任何一個節點元素也可以呼叫getElementsByTagName()方法,從而的到其內部的某種類別的元素節點
<p>段落</p><p>段落</p> <p>段落</p><p>段落</p>
var ps = document.getElementsByTagName('p');
getElementsByClassName()
<p class = "spec">盒子</p><p class = "spec ">盒子</p><p class = "spec">盒子</p><p class = "spec">盒子</p>
var spec_ps = document.getElementsByClassName('spec');
querySelector()
此方法只能得到頁面上一個元素,如果有多個元素符合條件,則只能得到第一個元素
<p id = "box1"> <p>段落</p> <p class = "spec">段落</p> <p>段落</p> <p>段落</p></p>
var the_p = document.querySelector('#box1 .spec');
querySelectAll()
即使頁面上只有一個符合選擇器的節點,也會得到長度為1的陣列
延遲執行
使用window.onload = function() {}事件(為window物件新增事件監聽,onload表示頁面都載入完畢了),使頁面載入完畢後,再執行指定的程式碼
節點的關係
關係 | 考慮所有節點 | 只考慮元素節點 |
---|---|---|
子節點 | childNodes | children |
父節點 | parentNode | 同 |
第一個子節點 | firstChild | firstElementChild |
最後一個子節點 | lastChild | lastElementChild |
前一個兄弟節點 | previousSibling | previousElementSibling |
後一個兄弟節點 | nextSibling | nextElementSibling |
注意:文本節點也屬於節點,所以我們一般情況下會排除文本節點的干擾(用只考慮元素節點)
書寫常見節點關係函數
<body> <p id = "box1"> <p>段落</p> <p class = "spec">段落</p> <p>段落</p> <p>段落</p> </p> <script> var box = document.getElementById('box1'); var spec = document.getElementsByClassName('spec'); // 封裝一個函數,傳回元素的所有子元素節點,類似children的功能function getChildren(node) { var children = []; // 遍歷node這個節點的所有子節點,判斷每個位元組的nodeType屬性是不是1 // 如果是1, 就推入結果數組for (var i = 0; i < node.childNodes.length; i++) { if (node.childNodes[i] == 1) { children.push(node.childNodes[i]); } } return children; } // 封裝一個函數,這個函數可以傳回元素的前一個元素兄弟節點,類似previousElementSibling的功能function getElementPrevSibling(node) { var o = node; while (o.previousSibling != null) { if (o.prebiousSibling.nodeType == 1) { // 結束循環,找到了return o.previousSibling; } o = o.previousSibling; } return null; } // 封裝一個函數,函數可以傳回元素的所有元素兄弟節點function getAllElementSibling(node) { var prevs = []; var nexts = []; var o = node; while (o.previousSibling != null) { if (o.previousSibling.nodeType == 1) { prevs.unshift(o.previousSibling); } o = o.previousSibling; } o = node; while (o.nextSibling != null) { if (o.nextSibling.nodeType == 1) { nexts.push(o.nextSibling); } o = o.nextSibling; } return prevs.concat(nexts); } </script></body>
改變元素節點中的內容
改變元素節點中的內容可以使用兩個相關屬性
innerHTML
能以HTML語法設定節點中的內容
innerText
只能以純文字的形式設定節點中的內容
<body > <p id = "box"></p> <script> var oBox = document.getElementById('box'); oBox.innerHTML = '<ul><li>牛奶</li><li>咖啡</li></ul>'; // 可以解析HTML語法// oBox.innerText = 'niub'; // 裡面只能是純文字</script></body>
改變元素節點的CSS樣式
相當於在設定行內style屬性
oBox.style.backgroundColor = 'red'; // CSS 屬性要寫成駝峰形式oBox.style.backgroundImage = ' url(images/1.jpg)';oBox.style.fontSize = '32px';
改變元素節點的HTML屬性
標準的W3C屬性,如src、href等,只需直接打點進行更改即可
oImg.src = ' images/2.jpg';
不符合W3C標準的屬性,要使用setAttribute()和getAttribute()來設定、讀取
<body> <p id = "box"></p> <script> var box = document.getElementById('box'); box.setAttribute('data-n', 10); // 新增data-n屬性,值為10 var n = box.getAttribute('date-n'); alert(n); </script></body>
節點的創建
document.createElement()方法用於創建一個指定tagname的HTML元素
var op = document.createElement('p');
新創建出的節點是”孤兒節點“,並沒有被掛載到DOM樹上,無法看見他
必須繼續使用appendChild() 或insertBefore() 方法將孤兒節點插入到DOM樹上
任何已經在DOM樹上的節點,都可以呼叫appendChild() 方法,它可以將孤兒節點掛載到他的內部,成為它的最後一個子節點
父節點.appendChild(孤兒節點);任何已經在DOM樹上的節點,都可以呼叫insertBefore() 方法,它可以將孤兒節點掛載到它的內部,成為它的」標竿子節點「之前的節點
父節點.insertBefore(孤兒節點, 標竿節點);
移動節點
如果將已經掛載到DOM樹上的節點成為appendChild()或insertBefore()的參數,這個節點將會被移動
新父節點.appendChild(已經有父親的節點);新父節點.insertBefore(已經有父親的節點, 標桿子節點);// 這表示一個節點不能同時位於DOM樹的兩個位置
刪除節點
removeChild() 方法從DOM中刪除一個子節點
父節點.removeChild(要刪除子節點);
克隆節點
cloneNode()方法可以克隆節點,克隆出的節點是”孤兒節點“
參數是boolean類型,表示是否採用深度克隆,若為true,則該節點的所有後代節點也都會被克隆,若為false,則只克隆該節點本身
var 孤兒節點= 老節點.cloneNode();var 孤兒節點= 老節點.cloneNode(true);
事件
事件名 | 事件描述 |
---|---|
onclick | 當滑鼠單機某個物件 |
ondbclick | 當滑鼠雙擊某個 | 物件
onmousedown | 當某個滑鼠按鍵在某個物件上被按下 |
onmouseup | 當某個滑鼠按鍵在某個物件上被放開 |
onmousemove | 當某個滑鼠按鍵在某個物件上被移動 |
onmouseenter | 當滑鼠進入某個物件(相似事件onmouseover) |
onmouseleave | 當滑鼠離開某個物件(相似事件 onmouseout) |
onmouseenter不冒泡,onmouseover冒泡
事件名 | 事件描述 |
---|---|
onkeypress | 當某個鍵盤的鍵被按下(系統按鈕如箭頭鍵和功能鍵無法被識別) |
onkeydown | 當某個鍵盤的鍵被按下(系統按鈕可是識別,並且會優先於onkeypress發生) |
onkeyup | 當某個鍵盤的鍵被鬆開 |
事件名 | 事件描述 |
---|---|
onchange | 用戶改變域的內容之後 |
oninput | 正在修改域的內容(輸入內容) |
onfocus | 當某元素獲得焦點(如tab鍵或滑鼠點選) |
onblur | 當某元素失去焦點 |
onsubmit | 當表單被提交 |
onreset | 當表單被重置 |
事件名稱 | 事件描述 |
---|---|
onload | 當頁面或圖像被完成載入 |
onunload | 當使用者退出頁面 |
當盒子巢狀時事件監聽的執行順序
<p id = "box1"> <p id = "box2"> <p id = "box3"></p> </p></p><script> var oBox1 = document.getElementById('box1'); var oBox2 = document.getElementById('box2'); var oBox3 = document.getElementById('box3'); oBox1.onclick = function () { console.log('box1'); }; oBox2.onclick = function () { console.log('box2'); }; oBox3.onclick = function () { console.log('box3'); }; // 點擊最裡面的盒子,傳播方向是從內到外</script>
事件傳播
事件的傳播是:先從外到內,然後再從內到外(最內層不是先捕獲再冒泡,而是根據書寫代碼順序決定。同名盒子同階段與順序有關。如果給元素設置相同的兩個或多個同名事件,則DOM0級寫法後面寫的會覆蓋先寫的;而DOM2級會按順序執行)
onxxxx(DOM0級事件監聽)只能監聽冒泡階段,所以觀察出來的結果是從內到外
addEventListener()方法(DOM2級事件監聽)
oBox.addEventListener('click',function() { // 這裡是事件處理函數}, true); // 第三個參數若為true,監聽捕獲階段,為false,監聽冒泡階段
事件對象
事件處理函數提供一個形式參數,它是一個對象,封裝了本次事件的細節
這個參數通常用單字event或字母e來表示
oBox.onmousemove = function (e) { // 物件e就是這次事件的「事件物件」};
物件相關屬性滑鼠
觸發這次事件時滑鼠的位置的屬性
屬性 | 屬性描述 |
---|---|
clientX | 滑鼠指標相對於瀏覽器的水平座標 |
clientY | 滑鼠指標相對於瀏覽器的垂直座標 |
pageX | 滑鼠指標相對於 |
pageY | 滑鼠指標相對於整張網頁的垂直座標 |
offsetX | 滑鼠指標相對於事件來源元素的水平座標 |
offsetY | 滑鼠指標相對於事件來源元素的垂直座標 |
e.charCode屬性通常用於onkeypress事件中,表示使用者輸入的字元的「字元碼」
字元 字元碼 數字0 ~ 數字9 48 ~ 57 大寫字母A ~ Z 65 ~ 90 小寫字母a ~ z 97 ~ 122 e.keyCode屬性通常用於onkeydown和onkeyup事件中,表示使用者按下的按鍵的「鍵碼」
按鍵 鍵碼 數字0 ~ 數字9 48 ~ 57 字母部分大小寫a ~ z 65 ~ 90 四個方向鍵← ↑ → ↓ 37、38、39、40 回車鍵 13 空白鍵 32
阻止預設事件
e.preventDefault()方法用來阻止事件產生的「預設動作」
e.stopPropagation()方法用來阻止事件繼續傳播
批量添加事件監聽性能問題
,而批量添加事件會導致監聽數量太多,內存消耗會很大每一個事件監聽註冊都會消耗一定的系統內存
事件委託
,而批量添加事件會導致監聽數量太多,記憶體消耗會很大(當有大量類似元素需要批量添加事件監聽時,使用事件委託可以減少記憶體開銷)
利用事件冒泡機制,將後代元素事件委託給祖先元素
注意:不能委託不冒泡的事件給祖先元素
當有動態元素節點上樹時,使用事件委託可以讓新上樹的元素具有事件監聽
相關
屬性
屬性 | 屬性描述 |
---|---|
target | 觸發此事件的最早元素,即」事件來源元素「 |
currentTarget | 事件處理程序附加到的元素(this) |
定時器
setInterval()函數可以重複呼叫一個函數,在每次呼叫之間具有固定的時間間隔
setInterval(function () { // 這個函數會自動被以固定間隔時間呼叫}, 2000); // 第二個參數為間隔時間,單位為毫秒// 此函數可以接收第3、4…個參數,他們會依序傳入函數setInterval(function (a, b) { // 形式參數a 的值是88,形參b的值是66}, 2000, 88, 66); // 從第三個參數開始,表示傳入函數內的參數// 具名函數也可以傳入setIntervalvar a = 0;function fun() { console.log(++a);};setInterval(fun, 1000);
清除定時器
clearInterval() 函數可以清除一個定時器
// 設定定時器,並用timer變數接收這個定時器var timer = setInterval(function (function ) { }, 2000);// 點選按鈕時,清除定時器oBtn.onclick = function () { clearInterval(timer); };
延時器
setTimeout() 函數可以設定一個延時器,當指定時間到了之後,會執行函數一次,不再重複執行
var timer = setTimeout(function () { // 這個函數會在2 秒後執行一次}, 2000);clearTimeout(timer); // 清除延時器
異步
異步: 不會阻塞CPU繼續執行其他語句,當異步完成時,會執行」回呼函數“ (callback)
setInterval() 和setTimeout() 是兩個非同步語句
setTimeout(function () { console.log('A');}, 2000); // 非同步語句console.log('B'); // 非同步語句不會阻塞程式的正常執行// 執行結果BA
函數節流
一個函數執行一次之後,只有在大於設定的執行週期後才允許執行第二次
var lock = true;function 需要節流的函數() { // 如果鎖定時關閉狀態,則不執行if(!lock) return; // 函數核心語句// 關鎖lock = false; // 指定毫秒數後將鎖開啟setTimeout(function () { lock = true; }, 2000);}
BOM(Browser Object Model,瀏覽器物件模型)是JS與瀏覽器視窗互動的介面
window物件
window物件是目前js 腳本執行所處的窗口,而這個視窗中包含DOM結構,window .document屬性就是document物件
在有標籤頁功能的瀏覽器中,每個標籤都有自己的window物件;也就是說,同一個視窗的標籤頁之間不會共用一個window物件
全域
變數會成為window對象的屬性
var a = 10;console.log(window.a == a); // true
這意味著多個js檔案之間是共享全域作用域的,即js檔案沒有作用域隔離功能
內建函數普遍是window的方法
如setInterval()、alert()等內建函數,普遍是window的方法
視窗尺寸相關屬性
屬性 | 意義 |
---|---|
innerHeight | 瀏覽器視窗的內容區域的高度,包含水平捲軸(如果有的話) |
innerWidth | 瀏覽器窗口的內容區域的寬度,包含垂直滾動條(如果有的話) |
outerHeight | 瀏覽器視窗的外部高度 |
outerWidth | 瀏覽器視窗的外部寬度 |
獲得不包含滾動條的視窗寬度,要用document.documentElement.clientWidth
resize事件
在視窗大小改變之後,就會觸發resize事件,可以使用window.onresize或window.addEventListener('resize')來綁定事件處理函數
已捲動高度
window.scrollY屬性表示在垂直方向已滾動的像素值
document.documentElement .scrollTop屬性也表示視窗捲動高度
為了更好的瀏覽器相容行,通常將兩個一起寫入
var scrollTop = window.scrollY || document.documentElement.scrollTop;document.documentElement.scrollTop不是唯讀的,而window .scrollY是唯讀的
scroll事件
在視窗被捲動之後,就會觸發scroll事件,可以使用window.onscroll或window.addEventListener('scroll')來綁定事件處理函數
Navigator物件
window.navigator屬性可以檢索navigator對象,它內部含有用戶此次活動的瀏覽器的相關屬性和標識
屬性 | 意義 |
---|---|
appName | 瀏覽器官方名稱 |
appVersion | 瀏覽器版本 |
userAgent | 瀏覽器的用戶代理(含有內核資訊和封裝殼資訊) |
platform | 用戶作業系統 |
History對象
window .history 物件提供了操作瀏覽器會話歷史的介面
常用的操作就是模擬瀏覽器回退按鈕
history.back(); // 等同於點擊瀏覽器的回退按鈕history.go(-1); // 等同於history.back();
Location物件
window.location 標識目前所在網址,可以透過給這個屬性賦值指令瀏覽器進行頁面跳轉
window.location = 'http://www.baidu.com';window.location. href = 'http://www.baidu.com';
重新載入目前頁面
可以呼叫location的reload方法以重新載入目前頁面,參數true表示從伺服器強制載入
window.location.reload(true);
GET 請求查詢參數
window.location.search 屬性即為目前瀏覽器的GET 請求查詢參數
offsetTops屬性
該屬性表示此元素到定位祖先元素的垂直距離
定位祖先元素:在祖先中,離自己最近的且擁有定位屬性的元素
使用這個屬性的時候,所有祖先元素不要有定位物件
物件(object)是」鍵值對「的集合,表示屬性和值的映射關係
var obj = { name: '小明', age: 12, sex: '男', hobbies: ['足球', '程式設計']}; // js中花括號表示物件
注意:
如果物件的屬性鍵名不符合js識別碼命名規範,則這個鍵名必須用引號包裹
如果屬性名稱不符合js標識符命名規範,則必須用方括號的寫法來存取
如果屬性名以變數形式存儲,則必須使用方括號形式
var obj = { a: 1, b: 2, c: 3};var key = 'b';console.log(obj.key); // undefinedconsole.log(obj[key]); // 2
物件的建立
var obj = { a: 10};obj.b = 40;
刪除屬性
使用delete運算子刪除某個物件的屬性
var obj = { a: 1, b: 2};delete obj.a;
物件的方法
如果某個屬性值是函數,則它被稱為物件的方法
var xiaoming = { name: '小明', age: 12, sex: '男', hobbys: ['足球','游泳','程式設計'], 'favorite-book': '舒克和貝塔', sayHello: function () { console.log('hello'); }};
物件的遍歷
物件的遍歷需要使用for…in…循環,可是遍歷物件的每個鍵
for (var k in obj) { console.log('屬性' + k + '的值是' + obj[k]);}
物件的深克隆
var obj1 = { a: 1, b: 2, c: [33, 44, { m: 55, n: 66, p: [77, 88] }]};function DeepClone(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;}
函數的上下文
函數中可以使用this關鍵字,它表示函數的上下文
同一個函數,用不同的形式調用它,則函數的上下文不同
函數只有被調用,他的上下文才能被確定
相關規則
規則 | 上下文 |
---|---|
物件.函數()物件 | 函數 |
() | window |
陣列[下标]() | 陣列 |
IIFE | window |
計時器 | window |
DOM事件處理函數 | 綁定DOM的元素 |
call和apply | 任意指定 |
函數.call(上下文);函數.apply(上下文);
區別:
function sum(b1, b2) { alert(this.c + this.m + this.e + b1 + b2);}sum.call(xiaoming, 5, 3); // call要用逗號羅列參數sum.apply(xiaoming, [5, 3] ); // apply要把參數寫到陣列中
new操作符號呼叫函數
new 函數()
js規定,使用new運算元呼叫函數會進行「四步驟」:
function fun() { // {} this指向這個空對象this.a = 3; this.b = 5; // {a: 3, b: 5} // 自動補充return this;}var obj = new fun();console.log(obj);
建構子
將先前的函數進行一小步改進
function People(name, age, sex) { this.name = name; this.age = age; this.sex = sex;}var xiaoming = new People('小明', 12, '男');var xiaoming = new People('小紅', 10, '女');var xiaogang = new People('小剛', 13, '男');
為物件添加方法
function People(name, age, sex) { this.name = name; this.age = age; this.sex = sex; this.sayHello = function () { console.log('我是' + this.name); };}var xiaoming = new People('小明', 12, '男');xiaoming.sayHello();
prototype
任何函數都有prototype屬性,prototype是英語」原型「的意思,prototype屬性值是個對象,它預設擁有constructor屬性指回函數
建構函式的prototype是實例的原型
原型鏈查找
實例可以打點存取它的原型的屬性和方法,這被成為」原型鏈查找「
function People(name, age, sex) { this.name = name; this.age = age; this.sex = sex;}People.prototype.nationality = '中國'; // 在建構子的prototype上加上nationality屬性var xiaoming = new People('小明', 12, '男');console.log(xiaoming .nationality);
hasOwnProperty()
這個方法可以檢查物件是否真正」自己擁有「某屬性或方法
xiaoming.hasOwnProperty('name'); // truexiaoming.hasOwnProperty('age'); // truexiaoming.hasOwnProperty('sex'); / / truexiaoming.hasOwnProperty('nationality'); // false
in
in運算子只能檢查某個屬性或方法是否可以被物件訪問,不能檢查是否是自己的屬性或方法
'name' in xiaoming // true'age ' in xiaoming // true'sex' in xiaoming // true'nationality' in xiaoming // true
在prototype上添加方法
將方法直接添加到實例身上的缺點:每個實例和每個實例的方法函數都是內存中不同的函數,造成了記憶體的浪費,可以透過將方法寫道prototype上來解決。
function People(name, age, sex) { this.name = name; this.age = age; this.sex = sex;}People.prototype.sayHello = function () { console.log('我是' + this.name);};var xiaoming = new People('小明', 12, '男');xiaoming.sayHello();
原型鏈的終點
數組的原型鏈
繼承
讓Student的prototype屬性指向父類別的實例,然後在Student的prototype中加入Student的方法
透過原型鏈實現繼承的問題
為了解決原型中包含引用型別值所帶來問題和子類別建構函式不優雅的問題,通常使用一種叫做「借助建構函式」 的技術,也被稱為「偽造物件」 或「經典繼承」
在子類別建構子的內部呼叫超類別的建構函數,但要注意使用call()綁定上下文
function People(name, sex, age) { this.name = name; this.sex = sex; this.age = age; this.arr = [1, 2, 3];}function Student(name, sex, age, school, sid) { People.call(this, name, sex, age); this.school = school'; this.sid = sid;}var xiaoming = new Student('小明', '男', 12, '學校', 123456);
將借用原型鍊和借用構造函數的技術組合到一起,叫做組合繼承,也叫做偽經典繼承
缺點:
組合繼承最大的問題就是無論在什麼情況下,都會呼叫兩次超類別的建構子:一次是在創建子類別原型的時候,另一個是在子類別建構子的內部。
原型式繼承
Object.create()方法,可以根據指定的物件為原型建立出新物件(IE9)
var obj2 = Object.create(obj1);// 寫法2var obj2 = Object.create(obj1, { // 第二個參數為一個對象,將要補充的屬性寫在裡面d: { // 屬性的值仍然是一個對象value : 99 // 值為99 } // 可以遮蔽原型上的同名屬性});
在沒有必要「興師動眾」 的建立建構函數,而只是想讓新物件與現有物件「類似」 的情況下,使用Object.create() 即可勝任,稱為原型式繼承
Object.create() 的相容性寫法
在低版瀏覽器中實作Object.create()
// 道格拉斯·克羅克福德寫的一個函數// 函數功能就是以o 為原型,建立新物件function object(o) { // 建立一個暫時建構子function F() {} // 讓這個臨時建構子的prototype指向o, 這樣它new出來的對象,__proto__指向了o F.prototype = o; return new F();}
寄生式繼承
編寫一個函數,它可以“增強對象”,只要把對象傳入這個函數,這個函數將以此對象為“基礎” 創建出新對象,並為新對象賦予新的預置方法
function f(o) { var p = Object.create(o); p.display = function () { console.log(111); } return p;}
缺點:
由於無法做到函數復用而降低效率(方法沒有寫到prototype上)
寄生組合式繼承
藉由借用建構函式來繼承屬性,透過原型鏈的混成形式來繼承方法
function inheritPrototype(subType, superType) { var prototype = Object.create(superType.prototype); subType.prototype = prototype; } // 父類別function People(name, sex, age) { this.name = name; this.sex = sex; this.age = age; } People.prototype.sayHello = function() { console.log("hello"); } People.prototype.sleep = function () { console.log("sleep"); } // 子類別function Student(name, sex, age, school, sid) { People.call(this, name, sex, age); this.school = school; this.sid = sid; } inheritPrototype(Student, People); // 讓Student類別的Prototype指向以People.prototype為原型的一個新物件Student.prototype.exam = function () { console.log("exam"); }; var xiaoming = new Student('小明', '男', 12, '學校', 123456);
instanceof運算子
用來偵測」某物件是不是某個類別的實例「
xiaoming instanceof Student// 底層機理:檢查Student.prototype屬性是否在xiaoming的原型鏈上(多少層都行,只要在就行)
內建建構函數
JavaScript有很多內建建構函數,例如Array就是數組類型的建構函數,Function就是函數類型的建構函數,Object就是物件類型的建構子內建建構
函數非常有用,所有該類型的方法都是定義在它的內建建構函數的prototype上的,我們可以為這個物件添加新的方法,從而拓展某些類型的功能
內建建構函數的關係
Object.prototype是萬物原型鏈的終點,JavaScript中函數數組皆為物件。
任何函數都可以看做是Function “new出來的”,Object是函數,所以它也是Function類別的對象
包裝類別
包裝類別的目的就是為了讓基本型別值可以從它們的建構子的prototype上得到方法
Math物件
Math.pow() Math.sqrt() Math.ceil() // 向上取整Math.floor() // 向下取整Math.round() // 四捨五入Math.max() // 參數列表的最大值Math.min() // 計算arr數組的最大值var arr = [3, 6, 9, 2]; var max = Math.max.apply(null, arr);
Date物件
new Date() // 取得目前時間的日期物件newDate(2020, 11, 1) // 第二個參數從0開始算new Date(' 2020-12-01')
常見方法
方法 | 功能 |
---|---|
getDate() | 得到日期1 ~ 31 |
getDay() | 得到星期0 ~ 6 |
getMonth() | 得到月份0 ~ 11 |
getFullYear() | 得到年份 |
getHours() | 得到小時數0 ~ 23 |
getMinutes () | 得到分鐘數0 ~ 59 |
getSeconds() | 得到秒數0 ~ 59 |
時間戳
通過getTime()方法或Date.parse()函數可以將日期物件變為時間戳
通過new Date(時間戳)的寫法,可以將時間戳變成日期物件
var d = new Date();var timestamp1 = d.getTime();var timestamp2 = Date.parse(d);
正規表示式
正規表示式(regular expression)描述了字串的“構成模式”,經常被用來檢查字串是否符合預定的格式要求創建正則表達式
/内容/
的語法形式var str = '123456';var regxp = /^d{6}$/;if ( regxp.text(str)) { alert('符合規則');} else { alert('不符合規則');}
var regxp2 = new RegExp('^\d{6}$')
元字元
字元 | 函數 |
---|---|
d | 符合一個數字 |
D | 符合一個非數字字符 |
w | 匹配一個單字字符(字母、數字或下劃線) |
W | 匹配非單字字符 |
s | 匹配一個空白字符,包括空格、製表符和換行符 |
. | 任意字符 |
^ | 匹配開頭 |
$ | 匹配結尾 |
不管一個符號有沒有特殊意義,都可以在其之前加上一個
以確保它表達的是這個符號本身
方括號表示法
使用方括號,如[xyz],可以創建一個字符集,表示匹配方括號中的任意字符
/^[by]d{7}$/
使用短橫-
來指定一個字元範圍, ^
表示否定
元字元 | 等價的方括號表示法 |
---|---|
d | [0-9] |
D | [^0-9] |
w | [AZ-z0-9_] |
W | [^AZ-z0-9_] |
量詞
量詞 | 意義 |
---|---|
* | 符合前一個表達式0次或多次。等價於{0,} |
+ | 匹配前一個表達式1次或多次。等價於{1,} |
? | 匹配前面一個表達式0次或1次。等價於{0,1} |
{n} | 匹配了前面一個字元剛好出現了n次 |
{n,} | 匹配前一個字元至少出現了n次 |
{n,m} | 匹配前面的字元至少n次,最多m次 |
修飾符
也叫標誌(flags),用於使用正規表示式實現高級搜尋
修飾符 | 意義 |
---|---|
i | 不區分大小寫搜尋 |
g | 全域搜尋 |
var re = /m/gi;var re = new RegExp('m', 'gi ');
正規表示式相關方法
方法 | 簡介 |
---|---|
test() | 測試某字串是否符合正規表示式,傳回布林值 |
exec() | 根據正規表示式,在字串中進行查找,傳回結果陣列或null |
字串的相關正規方法
方法 | 簡介 | |
---|---|---|
search() | 在字串中根據正則表達式進行查找匹配,返回首次匹配到的位置索引,測試不到則返回-1 | |
match | () | 在字符串中根據正則表達式進行查找匹配,返回一個數組,找不到則返回null |
replace() | 使用替換字串替換掉匹配到的子字串,可以使用正則表達式 | |
split() | 分隔字串為數組,可以使用正則表達式 |
var str = 'abc123def4567ghi89' ; // search()方法,很像indexOf(),回傳找到的第一個下標,如果找不到就是-1 var result1 = str.search(/d+/g); var result2 = str.search(/m/g); console.log(result1); // 3 console.log(result2); // -1 // match()方法,回傳查找到的數組,找不到是null var result3 = str.match(/d+/g); console.log(result3); // ["123", "4567", "89"] // replace()方法,進行替換var result4 = str.replace(/[az]+/g, '*'); // 注意+表示貪婪的,盡可能多的連續匹配小寫字母console.log(result4 ); // *123*4567*89 // split()方法,進行字串拆為陣列var result5 = str.split(/d+/g); console.log(result5); // ["abc", "def", "ghi", ""]