JS常用知識點(一)
1.js資料型別
基本型別:String、Number、boolean、null、undefined、Symbol
引用型別:Object
null和undefined的區別:undefined表示定義但未賦值。null表示定義並賦值,但值為null,可用於物件的初始化或銷燬。
Symbol表示獨一無二的值,最大的用法是用來定義物件的唯一屬性名,也可使用 Symbol 定義常量,可以保證這一組常量的值都不相等。
2.判斷變數的型別
typeof:返回資料型別的字串表達(不能區分Object、null和Array,都會返回'Object')。
instanceof (例項於):不能區分基本型別string和boolean,除非是(使用new方法例項產生,如:var s = new string() )字串物件和布林物件。
constructor :除了undefined和null,其他型別的變數均能使用constructor判斷出型別。不過要注意,constructor屬性是可以被修改的,會導致檢測出的結果不正確。
Object.prototype.toString.call() : 目前最好用
首先在Object.prototype.toString方法被呼叫時,會執行下面的操作步驟:
1. 獲取this物件的[[Class]]屬性的值.
2. 計算出三個字串"[object ", 第一步的操作結果Result(1), 以及 "]"連線後的新字串.
3. 返回第二步的操作結果Result(2).
[[Class]]是一個內部屬性,所有的物件(原生物件和宿主物件)都擁有該屬性。
判斷空物件的方法:①將物件轉化為字串,再判斷該字串是否為"{}"。②for in 迴圈判斷。③jquery的isEmptyObject方法。
④Object.getOwnPropertyNames()方法,獲取到物件中的屬性名,存到一個數組中,返回陣列物件,我們可以通過判斷陣列的length來判斷此物件是否為空(此方法不相容ie8)
⑤使用ES6的Object.keys()方法,與④方法類似,是ES6的新方法, 返回值也是物件中屬性名組成的陣列
3.資料型別轉換
全等和相等的區別:
相等 ==: 先隱式轉換型別再比較。
全等 ===:直接比較,不轉換型別,只要是型別不同就不相等,型別相同的看值是否相等。
Object.is(value1,value2):ES6 提出“Same-value equality”(同值相等)演算法,它用來比較兩個值是否嚴格相等,與嚴格比較運算子(===)的行為基本一致。Object.is與“===”不同之處只有兩個:一是+0
不等於-0
,二是NaN
等於自身。
強制轉換和隱式轉換:
使用String(),Number(),Boolean()函式強制轉換。
隱式轉換:字串加數字,數字就會轉成字串。數字減字串,字串轉成數字。如果字串不是純數字就會轉成NaN。字串減數字也一樣。兩個字串相減也先轉成數字。乘,除,大於,小於跟減的轉換也是一樣。
== 時候也會進行隱式轉換 ①undefined == null。 ②字串和數字比較時,字串轉數字。 ③數字為布林比較時,布林轉數字。 ④字串和布林比較時,兩者轉數字。
基本包裝型別:Boolean,Number,String 這三個基本型別都有自己對應的包裝物件。包裝物件,其實就是物件,有相應的屬性和方法。呼叫方法的過程,是在後臺偷偷發生的。
引用型別和基本包裝物件的區別在於:生存期。引用型別所建立的物件,在執行的期間一直在記憶體中,而基本包裝物件只是存在了一瞬間,所以我們無法直接給基本型別新增方法。
4.原型和原型鏈
每一個JavaScript物件(除了 null )都具有的一個屬性,叫proto,這個屬性會指向該物件的原型,也就是該物件建構函式的prototype屬性。
每個原型本質上還是一個物件,它也有自己的原型,這樣就形成了原型鏈。
5.閉包
在JavaScript高階程式設計(第3版)中是這樣描述:閉包是指有權訪問另一個函式作用域中的變數的函式。
或簡單理解為定義在一個函式內部的函式,內部函式持有外部函式內變數的引用。
用途:① 封裝變數和方法 ② 快取 ③ 實現類和繼承 ④ 匿名自執行函式
優點:① 希望一個變數長期儲存在記憶體中。② 避免全域性變數的汙染。③ 私有成員的存在。
缺點:① 常駐記憶體,增加記憶體使用量。② 使用不當會很容易造成記憶體洩露。
6.call、apply和bind
call、apply、bind的作用是改變函式執行時this的指向,第一個引數都是this要指向的物件,然後用其他引數來傳參。
區別:
call 的引數是直接放進去的,第二第三第 n 個引數全都用逗號分隔,直接放到後面。
apply 的所有引數都必須放在一個數組裡面傳進去。
bind 除了返回是函式以外,它 的引數和 call 一樣。
7.DOM事件流和事件委託
事件流又稱為事件傳播,DOM2級事件規定的事件流包括三個階段:事件捕獲階段(capture phase)、處於目標階段(target phase)和事件冒泡階段(bubbling phase)。
你可以選擇是在捕獲階段還是冒泡階段繫結事件處理函式,這是通過addEventListener()方法實現的,如果這個函式的最後一個引數是true,則在捕獲階段繫結函式,反之false(預設),在冒泡階段繫結函式。
在整個事件流的任何位置通過呼叫事件的 stopPropagation()
方法可以停止事件的傳播過程。
事件委託顧名思義:將事件委託給另外的元素。其實就是利用DOM的事件冒泡原理,將事件繫結到目標元素的父節點。
如果要為大量的元素節點繫結事件,完美可以用事件委託完美解決,直接將事件繫結在這些元素的父節點上,只需要繫結一次,就可以在所有子節點觸發事件。
最適合使用事件委託技術的事件包括click、mousedown、mouseup、keydown、keyup和keypress。
事件委託的好處: ① 提高JavaScript效能。事件委託可以顯著的提高事件的處理速度,減少記憶體的佔用。② 動態的新增DOM元素,不需要因為元素的改動而修改事件繫結。
8.Cookie和Storage
Cookie: ① 是設計用來在服務端和客戶端進行資訊傳遞的。
②cookie是以小的文字檔案(<4k)形式(即純文字),完全存在於客戶端;cookie儲存了登入的憑證,有了它,只需要在下次請求時帶著cookie傳送,就不必再重新輸入使用者名稱、密碼等重新登入了。
Cookie的HttpOnly限制js通過document.cookie來訪問Cookie,從而防止XSS(Cross-Site Scripting)攻擊。
在RFC2109中定義的SET-COOKIE響應報頭的格式為:Set-Cookie: Name = Value; Comment = value; Domain = value; Max-Age = value; Path = Value;Secure; Version = 1 * DIGIT;
Storage即瀏覽器本地儲存(5M或更大),在較高版本的瀏覽器中,js提供了兩種儲存方式:sessionStorage和globalStorage。在H5中,用localStorage取代了globalStorage。
sessionStorage用於本地儲存一個會話中的資料,這些資料只有在同一個會話中的頁面才能訪問,並且當會話結束後,資料也隨之銷燬。所以sessionStorage僅僅是會話級別的儲存,而不是一種持久化的本地儲存。
localStorage是持久化的本地儲存,除非是通過js刪除,或者清除瀏覽器快取,否則資料是永遠不會過期的。
瀏覽器的支援情況:IE7及以下版本不支援web storage,其他都支援。不過在IE5、IE6、IE7中有個userData,其實也是用於本地儲存。這個持久化資料放在快取中,只有不清理快取,就會一直存在。
Cookie和Storage的區別:
(1) web storages和cookie的作用不同,web storage是用於本地大容量儲存資料(web storage的儲存量大到5MB);而cookie是用於客戶端和服務端間的資訊傳遞;
(2) web storage有setItem、getItem、removeItem、clear等方法,cookie需要我們自己來封裝setCookie、getCookie、removeCookie
9.陣列和物件常見的方法
陣列常用方法:
1. join (原陣列不受影響)
該方法可以將數組裡的元素,通過指定的分隔符,以字串的形式連線起來。
返回值:返回一個新的字串
2. split (原陣列不受影響)
該方法是用過指定的分隔符,將字串分割成陣列。
返回值:返回一個新的陣列
陣列的增刪操作(直接改變原陣列):
3. push
該方法可以在陣列的最後面,新增一個或者多個元素。
返回值:返回的是新增元素後陣列的長度。
4. pop
該方法可以在陣列的最後面,刪除一個元素。
返回值:返回的是剛才刪除的元素。
5. unshift
該方法可以在陣列的最前面,新增一個或者幾個元素。
返回值: 返回的是新增元素後陣列的長度
6. shift
該方法可以在陣列的最前面,刪除一個元素。
返回值: 返回的是剛才刪除的元素。
陣列的翻轉和排序(改變陣列)
7. reverse
翻轉陣列
8. sort
該方法可以對陣列進行排序.
陣列的拼接與擷取(原陣列不受影響)
9. concat
該方法可以把兩個數組裡的元素拼接成一個新的陣列
返回值: 返回拼接後的新陣列
1 // concat與push的區別 2 let arr1 = [1,2,3]; 3 let arr2 = [4,5,6]; 4 let arr = arr1.concat(arr2);//arr = [1,2,3,4,5,6]; 5 arr1.push(arr2);//arr1 = [1,2,3,[4,5,6]];
10. slice([start],[end])(左閉右開)
該方法可以從陣列中擷取指定的欄位,返回出來。
返回值:返回截取出來的欄位,放到新的陣列中,不改變原陣列。
刪除或增加元素(任意在任何位置,直接改變原陣列,沒有返回值)
11. splice(start,count,[element,...])
從start(從0開始)下標開始,刪除count個,並在該位置新增element,start開始全部往後移動。
查詢元素在陣列中出現的位置
12. indexOf
該方法用來查詢元素在陣列中第一次出現的位置,無則返回-1。
結構:
arr.indexOf(元素)
13. lastIndexOf
該方法用來查詢元素最後一次在陣列中出現的位置
ES5新增的遍歷陣列方法
1. forEach( function(item,index,arr){} )
該方法等同於for迴圈,沒有返回值
2.map( )
對映,該方法使用和forEach大致相同,但是該方法有返回值,返回一個新陣列,新陣列的長度和原陣列長度相等。
let arr = [1,32,54,6,543]; let res = arr.map(function(item,index,arr){ //裡面的function是一個回撥函式, //item: 陣列中的每一項; //index:item 對應的下標索引值 //arr: 就是呼叫該方法的陣列本身 return item*2; }) //res=[2, 64, 108, 12, 1086]
3. filter( function(item, index) {return item;} )
filter方法: 有返回值(過濾後的陣列), 過濾出符合條件(回撥函式返回值為true)的元素。
4. some( function(item) { return item.done; } )
判斷陣列中有沒有符合條件的項(只要有,就返回true),如果一個都沒有,才返回false。
5. every( function(item) { return item.done; } )
判斷陣列中所有的項是否滿足要求,如果全都滿足,才返回true,否則返回false。
6. find( function(item) { return item.done; } )
找到符合條件的項,並且返回第一項。
7. findIndex( function(item) { return item.done; } )
到符合條件的項的下標,並且返回第一個。
8.reduce( function(total,currentValue,[currentIndex],[arr] ){} , [initialValue] )
求和計算:
var arr1 = [1,2,3,4,5] ; var new1 = arr1.reduce(function(pre,next,index){ return pre+next ; //pre+next=10+5=15 })
扁平化陣列(拼接陣列):
var arr2 = [[1,2,3],[4,5],[6,7]] ; var new2 = arr2.reduce(function(pre,next,index){ return pre.concat(next); //前陣列拼接後陣列 .concat() })
物件陣列疊加計算:
var arr3 = [ {price:10,count:1}, {price:15,count:2}, {price:10,count:3} ]; var new3 = arr3.reduce(function(pre,next,index){ return pre+next.price*next.count; },0) //在原陣列第一項新增為0,不改變原陣列,則可不操作第一項
ES6新增的陣列方法
物件常用方法
Object.assign(target,...sources)
用於將所有可列舉屬性的值從一個或者多個源物件複製到目標物件,將返回目標物件,引數target是目標物件,引數sources是源物件。
此方法實現的是深拷貝,但是這種情況只能進行第一層的深拷貝,更深層次的拷貝還是傳址的。
//第一層為深拷貝 var obj1 = { a: 1, b: 2 }; var obj2 = {}; Object.assign(obj2, obj1); obj2.a = 3; console.log(obj1, obj2); //輸出結果是: {a:1,b:2} {a:3,b:2}
//第二層為淺拷貝 var obj1 = [{ a: 1, b: 2 }, 2, 3]; var obj2 = []; Object.assign(obj2, obj1); obj2[0].a = 3; console.log(obj1, obj2); // 輸出的結果是:[{ a: 3, b: 2 }, 2, 3] 和 [{ a: 3, b: 2 }, 2, 3]
var obj1 = JSON.parse(JSON.stringify(obj)); //可用此方法實現深拷貝
Object.entries()
返回一個給定物件自身課列舉屬性的鍵值對陣列,其排列方式與使用for···in迴圈遍歷該物件時返回的順序一致(區別在於for···in迴圈列舉原型鏈中的屬性)。
Objection.is(value1,value2)
判斷兩個值是不是相同的值。兩個引數是兩個需要比較的值。返回一個布林值表示是不是相同。
Object.freeze()
方法可以凍結一個物件,一個被凍結的物件再也不能被修改,凍結了一個物件則不能向這個物件新增新的屬性,不能刪除該物件以有屬性的可列舉性、可配置性、可寫性,
以及不能修改已有屬性的值,此外凍結一個物件後該物件的原型也不能被修改。返回和傳入的引數相同的物件。
prototypeObj.isPrototypeOf()
用於測試一個物件是不是存在在另一個物件的原型鏈上。
10.new物件時內部做了什麼?
(1) 建立一個新物件;
(2) 將建構函式的作用域賦給新物件(因此 this 就指向了這個新物件) ;
(3) 執行建構函式中的程式碼(為這個新物件新增屬性) ;
(4) 返回新物件。
var obj = {}; //建立了一個空物件obj obj.__proto__ = Base.prototype; //我們將這個空物件的__proto__成員指向了Base函式物件prototype成員物件 Base.call(obj);//我們將Base函式物件的this指標替換成obj,然後再呼叫Base函式,於是我們就給obj物件賦值了一個id成員變數,這個成員變數的值是”base”