1. 程式人生 > >JS常用知識點(一)

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”