前端面試必備基本知識點--JS篇

JS篇

js中的裝箱和拆箱操作

裝箱:把基本數據轉換成對應的引用類型操作; 拆箱:把引用類型轉換成基本類型。
裝箱步驟:

  1. 運算符 . 提供裝箱操作,根據基礎類型構造一個臨時對象,這樣能夠讓我們在基礎類型上調用對應對象方法。

裝箱機制會頻繁的產生臨時對象,在一些性能要求比較高的場景下,我們應該盡量避免對基本類型做裝箱轉換。
拆箱

toString() //返回文本值
valueOf() //返回原始值
  1. 這兩個方式一般由js隱式的去調用,在數值運算中,會優先valueOf(),在字符運算中優先調用toString()

js的冒泡和捕獲事件,以及在不同瀏覽器怎么阻止冒泡、捕獲事件以及默認事件

答案解析:

DOM2級事件規定的事件流包括:事件捕獲、目標階段、事件冒泡

事件冒泡: 從實際操作的元素(事件)向上級元素一級一級執行下去,直到到達根元素

事件捕獲: 瀏覽器檢測元素的最外層祖先<html>一級一級向下執行事件,直到到底目標元素

事件委托: 利用的是事件冒泡機制實現的,通俗來說就是將元素的事件委托給它的父級或者是更外級元素處理

適合采用事件委托機制的事件有:clickmousedownkeyup 等,而 mouseovermouseout不適合

事件委托優點:

  • 動態新增的子元素無需重新綁定事件
  • 只需要將同類元素的事件委托給父級或者更外級的元素,不需要給所有同類的元素都綁定事件,這樣可以減少內存空間占用,提示性能

js的冒泡和捕獲事件都是描述事件觸發的時序問題,冒泡指的是由子節點向父節點的順序觸發事件,捕獲則是由父節點向子節點的順序觸發事件;默認事件是當我們在頁面執行一些動作時,瀏覽器觸發的默認事件,比如點擊a標簽跳轉頁面的時候,自動觸發click事件、鼠標右擊的時候 執行的oncontextmenu 事件、以及鼠標滾動的時候、表單的提交行為等等。

冒泡、捕獲事件的阻止

  • w3c中使用e.stopPropagation() IE使用e.cancelBubble = true

默認行為的阻止

  • w3c使用e.preventDefault()阻止默認行為,IE使用 e.returnValue = false 或者是return false來阻止

對作用域的理解,let和var的區別

答案解析:

作用域是分有函數作用域、塊級作用域,可以理解為變量可使用的范圍、區域。

let和var的區別在于:

  • let是塊級作用域,不存在變量提升(存在暫存性死區)、不能重復聲明、聲明變量不可作為window屬性
  • var是函數作用域、存在變量提升、能重復聲明、聲明變量可以作為window屬性

對閉包的理解

答案解析:

官方解釋指一個擁有很多變量和綁定了這些變量的環境的表達式為閉包。通俗理解為是指有權訪問另一個函數作用域中的變量函數。

js允許使用內部函數--即函數定義和函數表達式位于另一個函數的函數體內,而且這些內部函數可以訪問它們所在的外部函數中所聲明的所有局部變量、參數和聲明的其他內部函數。當其中一個這樣的內部函數在包含它們的外部函數之外被調用時,就會形成閉包

閉包特性

  • 封閉性:如果不是閉包函數自動暴露內部的私有變量的情況下,外部變量是無法直接訪問到閉包內部的函數
  • 持久性:因為js的垃圾回收機制所以在函數使用完后,js會自動銷毀函數,但是閉包函數不會立即被銷毀

可使用場景

  • 設置私有變量的特權訪問方法
  • 應用寫防抖和節流函數

閉包的產生來自于js的變量作用域。在js中,變量的作用域屬于函數作用域,當函數執行完全之后,作用域就會被清理,內存也會隨之被回收。而封包因為是父函數內部的子函數,可以訪問到父函數變量,以至于父函數執行完成,但是作用域也不會銷毀,而一直保存在內存中直至閉包函數被銷毀。而利用這個特性就可以將定時器保存在內存中,但我們執行用戶操作的時候,判斷定時器的執行情況決定是否執行接下來的操作

  • 因為閉包的可以直接訪問到函數的變量,且執行完不會立即被銷毀,所以函數的局部變量可以當成全局范圍的函數使用
  • 采用函數引用方式的setTimeout的調用,可通過閉包形式方法傳入的參數
function calllater(A,B,C){
    return (function(){
        A[B] = C
    })
}
var p = new callater('style','diplay','none');
setTimeout(p,200);//此時會執行p指向函數的內部函數

參考文章

對原型鏈、原型對象的認識

答案解析:

原型: 每個js對象在創建時,會自動關聯到另一個對象,這個對象就是我們所說的原型,而每一個對象都會從這個原型中去繼承屬性 。 每一個函數都有prototype屬性,這個屬性指向函數的原型對象。

原型鏈:每個對象都有一個屬性(除null外),即為原型鏈,這個屬性指向該對象創建的構造函數的原型屬性。

constructor:每個原型都有一個constructor屬性,這個屬性指向該原型關聯的構造函數

Person === Person.prototype.construtor

Function、Object原型鏈之間的關系

  1. Function 是一個函數(函數是Function的實例對象)
Function.__proto__ === Function.prototype
  1. Object 是一個函數(函數是Function的實例對象)
Object.__proto__ === Function.prototype
  1. Object是原型鏈的頂層
Object.prototype === null
  1. Function.prototype是普通對象
 Function.prototype.__proto__ === Object.prototype

js的繼承有那些方式、分別有什么優缺點

答案解析:

  • 原型鏈繼承
function A(name){
    this.name = name
}
A.prototype.age = 10;
function B(){
    this.sex = 'ss'
}
B.prototype = new A()  // B的原型對象指向A的實例,那么B的實例對象的原型鏈就會指向A的實例

var b = new B();
console.log(b.age) // 10

特點:1、可繼承屬性:實例構造函數屬性、父類構造函數、父類原型屬性

缺點:1、共享父類實例屬性(共享原型屬性)2、 新實例無法向父類構造函數傳參

  • 借用構造函數繼承
function B(){
    A.call(this,'qiqiq') // 將this對象指向A對象 
    this.sex = 'ss'
}
var b = new B();
console.log(b.age) // 10

特點:1、可繼承屬性:父級構造函數屬性 2、可向父實例傳參

缺點:1、無法實現父級構造函數復用 2、每個實例都有父類構造函數復本 3、只能繼承構造函數的屬性

  • 組合繼承
function B(){
    A.call(this,'qiqiq') // 將this對象指向A對象 
    this.sex = 'ss'
}
B.prototype = new A() 
//修復構造函數的指向,因為有需要指向兩個構造函數
B.prototype.constrcutor  = B
var b = new B();
console.log(b.age) // 10

特點:1、結合兩者優點:傳參、復用 2、可繼承屬性:父級構造屬性、父級原型屬性、實例構造函數屬性

缺點:1、需要調用兩次父類構造函數

  • 寄生式繼承
function box(obj){
    function F(){}
    F.prototype = obj;
    return new F(){}  
}
var a = new A();
var b = box(a); //返回父級的實例,每次都是新的,可以自定義去添加屬性和方法
  • 寄生式組合繼承
(function(){
     //創建一個無屬性的函數,將它原型指向父級原型
     var super = function(){};
     super.prototype =  A.prototype;
     //將其實例作為子類原型對象
     B.prototype = new super();
 })()
 
 function B(){
    A.call(this,'qiqiq') // 將this對象指向A對象 
    this.sex = 'ss'
 }
 B.prototype.constrcutor  = B

特點:1、通過寄生方式,砍掉父類實例屬性,不必在調用兩次父類構造函數

語術表達

  • 原型鏈繼承

將子類的原型對象指向父類的實例對象,可以實現繼承父類的屬性、構造函數屬性、父類原型對象屬性,但是所有子類實例回公用這些屬性,一旦其中一個子類實例改變父類屬性,則會影響到其他子類繼承的信息。

  • 構造函數繼承

在子類的構造函數調用call函數,將子類的構造函數的內置對象this指向父類,則在子類通過new實例化對象的時候會將父類構造函數

  • 組合繼承
  • 寄生式組合繼承

js的箭頭函數和普通函數的區別

答案解析:

  1. 不能改變函數this對象的指向
  2. this的指向的是箭頭函數在定義時的父級上下文
  3. 不可以使用new操作
  4. 不能使用arguements對象(可以使用rest參數代替)
  5. 不是使用yield命令,不能作為Generator函數
  6. 箭頭函數沒有prototype原型對象。

執行new操作發生了什么

答案解析:

var a = new A()

  • 創建一個Object實例
    var a = new Object()
  • 將實例的原型鏈執行類的原型對象
    a[[Prototype]] = A.prototype 等價于 a.__proto__ = A.prototype
  • 調用call函數改this 指向,執行對應的構造函數

promise對象的理解以及asyns、await的理解

答案解析:

promise是異步回調的一種解決方法,可以理解為一個容器,里面保存著異步操作在不同狀態下可能執行的事件。異步操作的待執行、執行成功、執行失敗分別對應著promise對象的pending、fullfilled、rejected.只有異步操作的結果能決定這些狀態,且這些狀態均為不可逆。

asyns、await著兩個關鍵詞一定要和promise對象配套使用才能體現價值所在,asyns這個關鍵詞可以將普通函數轉換成異步函數,await則為異步函數的提供串行執行的方案,await跟隨的promise對象的狀態變化之后才能執行下一步操作。

  • promise.all的使用

promise.all可以將多個promise實例包裝成新的promise實例

  1. 接收一個對象數組作為參數,可以是其他值,只有是promise會等待其狀態變化
  2. 當所有的子promise的狀態完成,則返回值是全部值的數組
  3. 如果有任意一個失敗,則promise失敗,返回值是第一個失敗的子promise的結果
  • promise.race的使用
  1. 任意一個返回結果后,無論結果是成功還是失敗,但是進程不會立即停止

ES迭代的特性

答案解析:

  • let和const關鍵詞
  • 解構賦值
  • 使用...展開運算符
  • 添加class、super、extends關鍵詞
  • 箭頭函數
  • 增加Set(集合)、Map(字典)數據類型,可用于去重和存儲,Set可用于數據去重、map可以用鍵值對形式存儲數據,查詢速度極快
  • generators生成器

是一個能返回一個迭代器的函數,實現惰性加載數據。在普通函數多加*,在函數體可以使用yield關鍵詞,讓我們的代碼進行等待,也可以運用在異步編程中,解決異步陷阱。讓異步操作可控

  • promise對象
  • async/await關鍵字

使用ES6遍歷數組的方法、以及不同方法的區別

答案解析:

  • for(var i = 0 ; i < arr.length; i++) 無限制,break、continue均可選
  • arr.forEach(function(val){ }) , 不可以使用break,也不能使用return 函數
  • for(var index in arr) 效率較低,并且index是字符,不是數字,這個需要注意到,同時會遍歷原型鏈上的可枚舉的屬性,可以結合obj.hasOwnProperty()來過濾掉
  • for(var item of arr) item是arr每次遍歷所對應的value(目前最優方案,也支持字符串的遍歷)
  • some() 用于檢測數組中是否存在一些滿足條件元素, 返回值為true 或 false ,如果有一個滿足條件的則函數返回true,否則返回false
arr.some((item,index,arr)=>{return item % 2==0 })
  • every() 和some相反,如果數組中全部元素滿足條件,則返回true,有一個不滿足條件則返回false
  • filter()是用來過濾篩選出符合條件的元素,返回內容為新的數組
 arr.filter((item)=>{
     return item%2 == 0
 })
  • map是一個數組的映射函數,對數組中的每個元素按照映射返回新的數組
arr.map(item=>{
    return item*2
})
  • reduce函數累加器,可以為數組中的每一個元素依次執行回調函數(不包括未被賦值或者被刪除的元素)
 arr.reduce(callback, [initValue]);
 //其中callback包含四個參數
 1. previousValue (上一次回調返回值或者初始值)
 2. currentValue (數組中當前被處理的值)
 3. index (當前元素在數組中索引)
 4. arr(調用的數組)
 // iniValue 表示初始值

事件循環機制

答案解析:

事件循環機制是用來解決js單線程執行機制,而導致一些簡單執行操作會因為等待一些耗時間的請求、涉及I/O執行事件 而無法延遲執行的情況。從廣義角度上講,事件循環機制將任務分為同步任務和異步任務
其執行的機制是如下:

  • 所以同步任務都在主線程中執行,形成一個任務棧
  • 除了主線程之外,還存在一個任務隊列,一旦異步任務執行完成,就在任務隊列壓入一個事件
  • 等待任務棧中的所有任務執行完成,從任務隊列中取出事件的回調函數放入任務棧中執行
  • 循環以此,直至任務完成
# 任務執行的優先級
同步任務 > promise.nextTick() > promise > setTimeout(fn) > setInterval(fn) > setImmediate(fn) > setTimeout(fn,time) > setInterval(fn,time) > setImmediate(fn,time)

js事件循環機制的執行順序如下:

  1. 執行完全部的同步任務,以及promise的構造函數
  2. 將所有promise的構造函數后的第一個then函數壓入異步隊列
  3. 再將所有的promise的第二個then函數壓力異步隊列,依次壓入全部的then函數
  4. 執行異步隊列中的then()函數
  5. 最后執行setTimeout()這些延遲函數

js的深淺拷貝

答案解析:

js的深、淺拷貝主要是針對于引用類型而言,淺拷貝就是復制了對象的引用,拷貝對象發生變化,原對象也會變化。深拷貝是申請新的空間 復制了對象的屬性,拷貝對象與原對象之間不存在關聯。

淺拷貝

  • Object.assign()、利用 = 賦值操作符 、{...obj} 展開運算符

深拷貝

  • JSON.stringify、JSON.parse 轉換拷貝,但是不足時如果對象值存在undefined、null、正則表達式、函數時,則無法拷貝,會置空。
  • 遞歸的方式判斷對象的每個元素類型,依次深挖,逐一進行拷貝
  function deep(obj){
     if(!obj) return obj;
     var objClone = Array.isArray(obj)?[]:{};
     if(obj && typeof obj == 'object'){  // obj為null或者是 object或者array都是返回 object
         for(var key in obj){
             if(obj.hasOwnPrpety(key)){  //該函數會返回一個布爾值,指示對象自身屬性中是否具有的該指定的屬性
                 objClone[key] = deep(obj[key]); // 采用遞歸深層遍歷
             }else{
                  objClone[key] = obj[key];  //基本數據類型直接拷貝即可
             }
         }
     }
     return objClone;
  }

要知道js的數據類型有那些方法,這些方法有什么差異

答案解析:

js的基本數據類型:String、Number、Boolean、undefined、Symbol、NaN、null,引用類型有:Object、Aarray.

null和undefined的區別

  • null:Null類型,可以認為對象類型,代表是一個空對象指針。
  • undefined:Undefined類型

區別:

  • 基本類型存儲在棧中(棧內存是由程序自動向操作系統請求分配的內存,其回收速度快、使用方便);賦值傳遞
  • 引用類型存儲在堆中(堆內存是由開發者向操作系統申請的,分配速度慢、不連續);引用傳遞

判斷數據類型

  • typeof 可以用來判斷基本數據類型。使用方式是 typeof + 變量,返回的內容是變量的數據類型
typeof [] //object
typeof function(){} //'function'
  • instanceof用來判斷某個對象是否屬于另個對象的實例。使用方式是A instanof B,返回內容為true或者false.

但是只能判斷的是復雜的數據類型,對于基本數據類型如果是通過字面量的方式創建是基本數據類型,而通過實例方式創建的是對象數據類型。instanceof判斷原理是通過尋找實例的原型鏈中是否存在類型的原型。實現方式如下:

 var _instanceof = function (left,right){
     let prototype = right.
 }
  • constructor從原型鏈的角度,構造函數就是新對象的類型,而construtor屬性是新建對象的構造函數中原型對象的屬性,指向構造函數。
''.constructor == String
  • Object.prototype.toString()利用對象的原型方法,再通過call、apply調用返回正確類型信息
Object.prototype.toString().call(window) //'[object global]' 
Object.prototype.toString().call(document) //'[object HTMLDocument]' 

參考文檔

js的垃圾回收機制和內存管理

答案解析:

內存泄漏 :不再用到的內存,沒有及時釋放,就是內存泄漏。
造成影響: 對于持續運行的服務進程,必須及時釋放不再用到的內存,否則內存占用越來越高,輕則影響系統性能,重則導致進程崩潰。

參考文檔

js的垃圾回收機制:是指js的變量或者函數在使用完成以后自動回收內存的機制。垃圾是指沒有引用的對象或者是幾個對象之間相互引用但是根部訪問不到的對象。 常用的方式有兩種:

標記清除

垃圾收集器會把在內存中存儲的變量加上標記,當執行流離開該環境,會去除環境中的變量以及被環境所引用的變量的標記。之后會給環境變量無法訪問到的內存變量再次加上標記,加上標記的也就是需要去除的變量。最后,垃圾收集器完成內存清除功能,銷毀那些帶標記的值并且回收內存。

引用計數

跟蹤記錄每個值被引用的次數。當聲明一個變量并且將一個引用變量賦給該值時,該值的引用次數加1,相反如果一個已經引用了該值的變量被賦給其他值,則該值的引用次數減1,如果引用次數為0,則垃圾收集器下次再運行時會釋放引用次數為0的內存。

存在相互引用的情況,導致雙方引用次數為2,則會陷入循環無法釋放內存的情況

js的字符串/數組 常用函數

答案解析:

字符串(原來這些函數都不會改變字符串本身,返回的都是新的字符串內容)

  • indexOf()/lastIndexOf 尋找某個字符在字符串的 第一個/最后一個 下標位置
  • slice(x,y) 截斷函數內容是[x,y) ,y可以為負數 y + s.length
  • substring() 截斷函數內容是[x,y) ,y 可以為負數 y + s.length,與上不同的是,當x>y 自動互換位置
  • substr(x,len),截斷內容是[x,x+len] ,其第二個參數是截斷的個數
  • split() 字符轉數組函數
  var s ='asfg'
  s.split()  //['asfg']
  s.split('') //['a','s','f','g']
  • s.charAt(index) 根據下標數返回對應的value值
  • s.replace(x,y) 找到第一個x子字符串

數組

  • contract() 連接數組 ,返回連接后的新數組
  a = [(1,2,3),4]
  a.contract([5,6]) // 3,4,5,6 因為逗號字符串的原因 則之后取最后一個元素
  • join()數組轉字符
var a = ['a','s','v']
a.join() // a,s,v
a.join('') //asv
a.join('-') // a-s-v
  • splice(index,howmany,element) 截取、刪除、插入函數(根據參數來定義) 改變原數組
var a = [1,2,3,4,5]
s.splice(1)  // 刪除index后的所以元素 
s.splice(2,3) // 刪除 index后3個元素
s.splice(1,0,5) //homemany為0時 則可插入元素 ,不為0時則替換內容

js遍歷對象的方法

  • for..in 最常規的遍歷方式,但是會得到在原型鏈上的屬性 ,使用obh.hasOwnProperty(key)篩選
  • Object.keys(obj) 返回的是對象中所有可以枚舉的屬性的數組,不會走原型鏈, 通過foreach()遍歷
 var obj ={"a":1,"b":3};
 Object.keys(obj).foreach((key)=>{
     console.log(obj[key])
 })
  • Object.getOwnPropertyNames() 返回自身對象的屬性名所組成的數組,包括不可枚舉對象
  • Reflect.ownKeys() 返回自身對象屬性名以及原型鏈上的所有屬性名所組成的數組

delete的使用場景

答案解析:

使用delete刪除無效的情況

  • 使用let、var、const聲明的變量或者是函數聲明刪除均無效
  • 刪除數組時,元素會被刪除、但是length值不變化
  • Map、Object、Array的內置變量不可刪除
  • 原型對象的屬性不可刪除

this對象的指向

答案解析:

this對象表示是一個函數對象在運行的過程中,內部生成的一個內置函數,只能在函數內部使用。記住一點是this是和函數執行的環境有關,與聲明環境無關(僅代表在普通函數,箭頭函數并非如此)

  • 方法調用模式
//案例:
var obj = {
  name:'ssss',
  sayName:function(){
      console.log(this.name)  //ssss
  }
}

解析:當函數作為對象的一個屬性,則可成為該函數的方法,當該函數被調用時,方法的this的對象被綁定在該對象中。

  • 函數調用模式
//案例
var name ='ddd'
function obj(){
    console.log(this.name) //dddd
}
obj()

解析:當函數并非一個對象屬性,而是正常的函數被調用的情況下則有,該this對象被綁定在window對象上

  • 構造函數模式
function obj(){
  this.name= 'dddd'
}
var s = new obj();
console.log(s.name)

解析: 在一個函數前面加上new時,此時會創建一個綁定到該函數的prototype的對象,并且該函數會作為該對象的構造函數,this此時指向該對象

  • apply/bind/call調用模式

解析:主要是改變this所綁定的對象

Map和object的區別

map對象保存鍵值對,任何值都可以作為一個鍵或者一個值,用for...of循環為每次迭代返回一個[key,value]的數組

區別:

  1. 每一個對象通常都有自己的原型,每一個對象都有prototype的屬性
  2. 一個對象的鍵只能是字符串或者是Sysmbols,但是map的鍵可以是任意值
  3. map的鍵值對個數可以通過size屬性獲取,而對象的元素個數可能只能通過遍歷手動確認

字符串是基本數據類型為什么可以調用數組的方法

js的裝箱機制,當我們訪問str時,訪問過程從內存中讀取這個字符串的值時,后臺會執行以下處理:

  • 創建String這個實例,生成一個基本包裝類型對象
  • 在實例中調用指定的方法
  • 銷毀實例

為什么0.2+0.1不等于0.3呢?

原因在于在js采用IEEE 754的雙精度標準,計算機內部存儲數據的編碼的時候,0.1在計算機內部根本不是精確0.1,而是有舍入誤差的,在代碼編譯過程中已經被四舍五入成一個與之很接近的計算機內部數字,這樣誤差也就產生了。

$(document).ready()和window.onload()有什么區別?

dom文檔的加載步驟

  1. 解析HTML結構
  2. 加載外部腳本和樣式表文件
  3. 解析并執行腳本
  4. dom樹構建完成(DOMContentLoaded)
  5. 加載圖片等外部文件
  6. 頁面加載完畢
  • window.onload方法是在網頁中所有元素(包括元素所有關聯文件)完全加載到瀏覽器后才執行的。
  • $(document).ready()方法可以在dom載入j就緒時對其進行操縱、并調用執行綁定的函數。

js/jQuery的常見的dom操作

dom的節點分為三大類:元素節點、屬性節點、文本節點,其中文本節點和屬性節點屬于元素節點的子節點,操作時需要先取到元素節點。

獲取元素節點的常用方法:

getElementId()  //返回帶有指定ID元素
getElementsClassName() //返回帶有指定類 的數組
getElementsTagName() // 返回帶有指定標簽的數組
createAttribute()  //創建屬性節點
createElement()  //創建元素節點
createTextNode() //創建文本節點

查看、設置屬性節點

  1. getAttribute(屬性名) //查看屬性節點
  2. setAttribute('屬性名','屬性值') //設置屬性節點
 div.style.backgroundColor = 'red'; //需要采用駝峰式寫法
 div.style = "backgorundcolor:red"

查看、設置文本節點

.innerText:取到或者設置節點里面的文字內容
.innerHTML:取到或者設置節點中的HTML代碼 

根據層次查看節點

.childNode() //獲取元素的所有子節點
.firstChild() //獲取元素的第一個子節點
.lastChild() // 獲取元素的最后一個子節點
.previousSibling() // 獲取當前節點的前一個兄弟節點
.nextSibling() //獲取當前節點的后一個兄弟節點

克隆節點

cloneNode(true) //克隆當前節點,以及當前節點的子節點
cloneNode(false) //克隆當前節點,不包括當前節點的子節點

js的常見函數操作

  • 對小數的相關操作
    1. 截取小數部分,取整數parseInt()
    2. 向上取整,有小數則加1 Math.ceil()
    3. 向下取整,有小數則去掉Math.floor()
    4. 小數部分四舍五入 Math.round()
    5. 四舍五入為指定小數位數的數字num.toFixed()
  • js的字符串相關函數操作
    1. 字符串分割 返回成數組 str.split(' ')
    2. 字符串切割 str.substr[start,length)
    3. 字符串切割 str.substring[start, end)
    4. 字符串去前后空格:str.trim()
    5. 字符串大寫轉小寫轉換:str.toLowerCase()
    6. 字符串小寫轉小寫轉換:str.toUpperCase()

var 和 let 、const的區別

  • var 聲明的變量會掛載到window ,而let和const聲明的變量不會
  • var 聲明變量存在變量提升,let和const不存在變量提升(存在一個暫存性死區)
  • let和const聲明形成塊作用域
  • 同一作用域下,let和const不能聲明同名變量,而var變量可以
  • const一旦聲明必須賦值,不能用null占位,基本數據類型聲明后不能在修改,如果是復合類型,可以修改其屬性

暫存性死區:ES6對作用域的新的語義,可以理解為程序的控制流程在新的作用域進行實例化時,在作用域中let、const聲明的變量會在該作用域先創建,但是沒有進行語法綁定和聲明語句的賦值運算,所以是不能訪問,訪問會拋出錯誤。所以在這運行流程一進入作用域創建變量,到變量開始可以被訪問的一段時間叫做TDZ(暫存性死區)

js的數據類型隱式轉換情況

運行環境對隱式轉換的影響

很多內置函數期望傳入的值的數據類型是固定的,如:alert(value)的方法,它期望傳入的是string類型,但是我們傳入的是number類型或者是其他非string類型,則h會發生類型的隱式轉換

操作符對數據類型轉換的影響
  1. 當+ 作為一元操作符操作數的時候,會將數轉換為數字類型
  2. 當+ 作為二元操作符操作數的時候,如果有一個操作數是字符則會,那么另一個操數也會轉換為字符類型;如果兩個都不是字符或者數字,則能轉換的轉換成數字,不能轉換的變成NaN
  3. 當算數運算符除了是+號以外的其他操作數,則兩個操作數都會轉換成數字類型進行數字運算

數字轉換的時候遵循:如果是簡單數據類型,則直接轉換成字符串或者數字,如果是復雜數據類型,則通過固定方法(valueOf、toString)轉換成簡單類型,再轉換成數字或者字符串

  • 轉換為Boolean類型
數據類型 轉換后的值
數字0 false
NaN false
'' false
null/undefined false

注意:如果是使用new操作符創建的對象隱式轉換成Boolean對象時,即使是new String('') 也是true

  • 轉換為number類型
數據類型 轉換后的值
非空字符串 如果全部為數字符合則轉換成數組,如果有其他符號則轉為NaN
null 0
'' 0
NaN/undefined NaN

參考文章

js的設計模式

可復用的解決方案,用于解決軟件設計中遇到的常見問題

優點

  • 模式都是有自己的結構和j解決方案的一系列詞匯,在向其他人描述時,表達更加清晰
  • 容易復用,可以通過改動一些信息去解決自己的問題
  • 在代碼結構上花費的時間比較少,可以有更多時間關注整體質量,且減少代碼重構的風險
  1. 單例模式

js中最基本最有用的模式,可以用來劃分命名空間,減少網頁中全局變量的數量,在多人開發時避免代碼的沖突。

  1. 工廠模式

提供一個創建一系列相關或相互依賴對象的接口,而無需指定他們具體的類。 把成員對象的創建工作轉交給一個外部對象,消除對象之間耦合。

  1. 裝飾者模式

為對象增加功能或者方法,動態給一個對象添加一些額外的職責,能夠在不改變現有對象或從派生子類的前提下為其添加方法。

  1. 代理模式

此模式最基本的形式是對訪問進行控制。代理對象和另一個對象(本體)實現是同樣的接口,實際工作也是本體在做,代理對象只是負責執行所分派的任務的,不會在對象的基礎上修改任何方法,也不會簡化對象的接口。

  1. 觀察者模式

定義對象間的一種一對多的依賴關系,以便當一個對象的狀態發生變化的時候,所有依賴于它的對象都得到通知并且刷新。

參考文章

正則表達式

正則表達圖
  • 修飾符(修辭符的使用是并集)
    1. i 忽略大小寫匹配
    2. g 全局匹配
  • 元字符
    1. 代表次數的量詞元字符
      1. :一次或0次
      2. + :1到多次
      3. *: 0到多次
    2. 代表特殊含義的元字符
      1. \d:0-9任意一個字符
      2. \D:表示非\d
      3. \w:表示數字、字母、下劃線
      4. \s:空格或者空白
      5. .:除了\n之外的任意一個字符
  • 常用方法
  1. test:驗證字符串是否符合正則,符合則返回true,否則返回false
  2. exec:捕捉符合規則的字符串
  3. match:匹配成功返回成功數組,否則返回null
  4. replace:把正則匹配成功的字符串替換成新的字符串

js函數的四種調用方式

函數基本概念

  • 函數的名字只是一個指向函數的指針,所以在不同執行環境、不同對象調用這個函數,函數指向的是同一個函數。
  • 函數內部的兩個特殊屬性arguments和this,其中argument主要是用來保存函數參數,this是與函數運行環境相關聯,不同運行環境指向也會不同。
    函數調用方式
  1. 直接調用函數,this指向全局對象window
  2. 函數作為對象的方法調用,this指向調用的當前對象
  3. 通過new調用構造函數的方式,this指向當前構造函數原型
  4. 上下文調用模式(通過call或者apply的方式),可以實現函數模式與方法模式

Object.defineProperty的使用

可以理解為屬性攔截器,專門監控對象的屬性變化。

 //接收三個參數定義屬性的對象、定義或修改屬性的名稱、定義或修改屬性的值 , 返回值修改完的obj對象
 Object.defineProperty(obj, prop, descriptor)

數據描述符和存取描述符可選鍵值

  • configurable:為true時,該屬性描述符才能夠改變,也能被刪除
  • enumerable:為true時,才能夠出現在對象的枚舉屬性,默認為false
  • value:為屬性對應的值,可以是任意有效js值,默認為undefined
  • writable: 為true時,該屬性可以被賦值運算符改變
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容