<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          字節(jié)跳動最愛考的前端面試題:JavaScript 基礎

          共 18279字,需瀏覽 37分鐘

           ·

          2021-02-26 12:48

          注意:每道題前面出現(xiàn)的 (xx) 數(shù)字代表這道題出現(xiàn)的頻次,此 JS 基礎是基于 30+ 篇前端面經整理出的問題和對應的回答、參考鏈接等。

          (2)問:0.1 + 0.2 === 0.3 嘛?為什么?

          JavaScirpt 使用 Number 類型來表示數(shù)字(整數(shù)或浮點數(shù)),遵循 IEEE 754 標準,通過 64 位來表示一個數(shù)字(1 + 11 + 52)

          • 1 符號位,0 表示正數(shù),1 表示負數(shù) s
          • 11 指數(shù)位(e)
          • 52 尾數(shù),小數(shù)部分(即有效數(shù)字)

          最大安全數(shù)字:Number.MAX_SAFE_INTEGER = Math.pow(2, 53) - 1,轉換成整數(shù)就是 16 位,所以 0.1 === 0.1,是因為通過 toPrecision(16) 去有效位之后,兩者是相等的。

          在兩數(shù)相加時,會先轉換成二進制,0.1 和 0.2 轉換成二進制的時候尾數(shù)會發(fā)生無限循環(huán),然后進行對階運算,JS 引擎對二進制進行截斷,所以造成精度丟失。

          所以總結:精度丟失可能出現(xiàn)在進制轉換和對階運算中

          參考鏈接

          • https://juejin.im/post/5b90e00e6fb9a05cf9080dff

          (4)問:JS 數(shù)據(jù)類型

          基本類型:Number、Boolean、String、null、undefined、symbol(ES6 新增的),BigInt(ES2020) 引用類型:Object,對象子類型(Array,F(xiàn)unction)

          參考鏈接

          • https://juejin.im/post/5b2b0a6051882574de4f3d96
          • https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Data_structures

          問:JS 整數(shù)是怎么表示的?

          • 通過 Number 類型來表示,遵循 IEEE754 標準,通過 64 位來表示一個數(shù)字,(1 + 11 + 52),最大安全數(shù)字是 Math.pow(2, 53) - 1,對于 16 位十進制。(符號位 + 指數(shù)位 + 小數(shù)部分有效位)

          問:Number() 的存儲空間是多大?如果后臺發(fā)送了一個超過最大自己的數(shù)字怎么辦

          Math.pow(2, 53) ,53 為有效數(shù)字,會發(fā)生截斷,等于 JS 能支持的最大數(shù)字。

          (4)寫代碼:實現(xiàn)函數(shù)能夠深度克隆基本類型

          淺克隆:

          function shallowClone(obj{
            let cloneObj = {};
            
            for (let i in obj) {
              cloneObj[i] = obj[i];
            }
            
            return cloneObj;
          }

          深克隆:

          • 考慮基礎類型
          • 引用類型
            • RegExp、Date、函數(shù) 不是 JSON 安全的
            • 會丟失 constructor,所有的構造函數(shù)都指向 Object
            • 破解循環(huán)引用
          function deepCopy(obj{
            if (typeof obj === 'object') {
              var result = obj.constructor === Array ? [] : {};
              
              for (var i in obj) {
                result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];
              }
            } else {
              var result = obj;
            }
            
            return result;
          }

          問:事件流

          事件流是網(wǎng)頁元素接收事件的順序,"DOM2級事件"規(guī)定的事件流包括三個階段:事件捕獲階段、處于目標階段、事件冒泡階段。首先發(fā)生的事件捕獲,為截獲事件提供機會。然后是實際的目標接受事件。最后一個階段是時間冒泡階段,可以在這個階段對事件做出響應。雖然捕獲階段在規(guī)范中規(guī)定不允許響應事件,但是實際上還是會執(zhí)行,所以有兩次機會獲取到目標對象。

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>事件冒泡</title>
          </head>
          <body>
              <div>
                  <p id="parEle">我是父元素    <span id="sonEle">我是子元素</span></p>
              </div>
          </body>
          </html>
          <script type="text/javascript">
          var sonEle = document.getElementById('sonEle');
          var parEle = document.getElementById('parEle');

          parEle.addEventListener('click'function ({
              alert('父級 冒泡');
          }, false);
          parEle.addEventListener('click'function ({
              alert('父級 捕獲');
          }, true);

          sonEle.addEventListener('click'function ({
              alert('子級冒泡');
          }, false);
          sonEle.addEventListener('click'function ({
              alert('子級捕獲');
          }, true);

          </script>

          當容器元素及嵌套元素,即在捕獲階段又在冒泡階段調用事件處理程序時:事件按DOM事件流的順序執(zhí)行事件處理程序:

          • 父級捕獲
          • 子級冒泡
          • 子級捕獲
          • 父級冒泡

          且當事件處于目標階段時,事件調用順序決定于綁定事件的書寫順序,按上面的例子為,先調用冒泡階段的事件處理程序,再調用捕獲階段的事件處理程序。依次alert出“子集冒泡”,“子集捕獲”。

          IE 兼容

          • attchEvent('on' + type, handler)
          • detachEvent('on' + type, handler)

          參考鏈接

          • https://juejin.im/entry/5826ba9d0ce4630056f85e07

          問:事件是如何實現(xiàn)的?

          基于發(fā)布訂閱模式,就是在瀏覽器加載的時候會讀取事件相關的代碼,但是只有實際等到具體的事件觸發(fā)的時候才會執(zhí)行。

          比如點擊按鈕,這是個事件(Event),而負責處理事件的代碼段通常被稱為事件處理程序(Event Handler),也就是「啟動對話框的顯示」這個動作。

          在 Web 端,我們常見的就是 DOM 事件:

          • DOM0 級事件,直接在 html 元素上綁定 on-event,比如 onclick,取消的話,dom.onclick = null,同一個事件只能有一個處理程序,后面的會覆蓋前面的。
          • DOM2 級事件,通過 addEventListener 注冊事件,通過 removeEventListener 來刪除事件,一個事件可以有多個事件處理程序,按順序執(zhí)行,捕獲事件和冒泡事件
          • DOM3級事件,增加了事件類型,比如 UI 事件,焦點事件,鼠標事件

          參考鏈接

          • https://zhuanlan.zhihu.com/p/73091706

          問:new 一個函數(shù)發(fā)生了什么

          構造調用:

          • 創(chuàng)造一個全新的對象
          • 這個對象會被執(zhí)行 [[Prototype]] 連接,將這個新對象的 [[Prototype]] 鏈接到這個構造函數(shù).prototype 所指向的對象
          • 這個新對象會綁定到函數(shù)調用的 this
          • 如果函數(shù)沒有返回其他對象,那么 new 表達式中的函數(shù)調用會自動返回這個新對象

          問:new 一個構造函數(shù),如果函數(shù)返回 return {}return nullreturn 1return true 會發(fā)生什么情況?

          如果函數(shù)返回一個對象,那么new 這個函數(shù)調用返回這個函數(shù)的返回對象,否則返回 new 創(chuàng)建的新對象

          問:symbol 有什么用處

          可以用來表示一個獨一無二的變量防止命名沖突。但是面試官問還有嗎?我沒想出其他的用處就直接答我不知道了,還可以利用 symbol 不會被常規(guī)的方法(除了 Object.getOwnPropertySymbols 外)遍歷到,所以可以用來模擬私有變量。

          主要用來提供遍歷接口,布置了 symbol.iterator 的對象才可以使用 for···of 循環(huán),可以統(tǒng)一處理數(shù)據(jù)結構。調用之后回返回一個遍歷器對象,包含有一個 next 方法,使用 next 方法后有兩個返回值 value 和 done 分別表示函數(shù)當前執(zhí)行位置的值和是否遍歷完畢。

          Symbol.for() 可以在全局訪問 symbol

          (3)問:閉包是什么?

          閉包是指有權訪問另外一個函數(shù)作用域中的變量的函數(shù)

          JavaScript代碼的整個執(zhí)行過程,分為兩個階段,代碼編譯階段與代碼執(zhí)行階段。編譯階段由編譯器完成,將代碼翻譯成可執(zhí)行代碼,這個階段作用域規(guī)則會確定。執(zhí)行階段由引擎完成,主要任務是執(zhí)行可執(zhí)行代碼,執(zhí)行上下文在這個階段創(chuàng)建。

          image.png

          什么是作業(yè)域?

          ES5 中只存在兩種作用域:全局作用域和函數(shù)作用域。在 JavaScript 中,我們將作用域定義為一套規(guī)則,這套規(guī)則用來管理引擎如何在當前作用域以及嵌套子作用域中根據(jù)標識符名稱進行變量(變量名或者函數(shù)名)查找

          什么是作用域鏈?

          首先要了解作用域鏈,當訪問一個變量時,編譯器在執(zhí)行這段代碼時,會首先從當前的作用域中查找是否有這個標識符,如果沒有找到,就會去父作用域查找,如果父作用域還沒找到繼續(xù)向上查找,直到全局作用域為止,,而作用域鏈,就是有當前作用域與上層作用域的一系列變量對象組成,它保證了當前執(zhí)行的作用域對符合訪問權限的變量和函數(shù)的有序訪問。

          閉包產生的本質

          當前環(huán)境中存在指向父級作用域的引用

          什么是閉包

          閉包是一種特殊的對象,它由兩部分組成:執(zhí)行上下文(代號 A),以及在該執(zhí)行上下文中創(chuàng)建的函數(shù) (代號 B),當 B 執(zhí)行時,如果訪問了 A 中變量對象的值,那么閉包就會產生,且在 Chrome 中使用這個執(zhí)行上下文 A 的函數(shù)名代指閉包。

          一般如何產生閉包

          • 返回函數(shù)
          • 函數(shù)當做參數(shù)傳遞

          閉包的應用場景

          • 柯里化 bind
          • 模塊

          參考文章

          • https://segmentfault.com/a/1190000012646221

          問:NaN 是什么,用 typeof 會輸出什么?

          Not a Number,表示非數(shù)字,typeof NaN === 'number'

          (2)問:JS 隱式轉換,顯示轉換

          一般非基礎類型進行轉換時會先調用 valueOf,如果 valueOf 無法返回基本類型值,就會調用 toString

          字符串和數(shù)字

          • "+" 操作符,如果有一個為字符串,那么都轉化到字符串然后執(zhí)行字符串拼接
          • "-" 操作符,轉換為數(shù)字,相減 (-a, a * 1 a/1) 都能進行隱式強制類型轉換
          [] + {} 和 {} + []

          布爾值到數(shù)字

          • 1 + true = 2
          • 1 + false = 1

          轉換為布爾值

          • for 中第二個
          • while
          • if
          • 三元表達式
          • || (邏輯或) && (邏輯與)左邊的操作數(shù)

          符號

          • 不能被轉換為數(shù)字
          • 能被轉換為布爾值(都是 true)
          • 可以被轉換成字符串 "Symbol(cool)"

          寬松相等和嚴格相等

          寬松相等允許進行強制類型轉換,而嚴格相等不允許

          字符串與數(shù)字

          轉換為數(shù)字然后比較

          其他類型與布爾類型

          • 先把布爾類型轉換為數(shù)字,然后繼續(xù)進行比較

          對象與非對象

          • 執(zhí)行對象的 ToPrimitive(對象)然后繼續(xù)進行比較

          假值列表

          • undefined
          • null
          • false
          • +0, -0, NaN
          • ""

          (2)問:了解 this 嘛,bind,call,apply 具體指什么

          它們都是函數(shù)的方法

          call: Array.prototype.call(this, args1, args2])apply: Array.prototype.apply(this, [args1, args2]) :ES6 之前用來展開數(shù)組調用, foo.appy(null, []),ES6 之后使用 ... 操作符

          • New 綁定 > 顯示綁定 > 隱式綁定 > 默認綁定
          • 如果需要使用 bind 的柯里化和 apply 的數(shù)組解構,綁定到 null,盡可能使用 Object.create(null) 創(chuàng)建一個 DMZ 對象

          四條規(guī)則:

          • 默認綁定,沒有其他修飾(bind、apply、call),在非嚴格模式下定義指向全局對象,在嚴格模式下定義指向 undefined
          function foo({
            console.log(this.a); 
          }

          var a = 2;
          foo();
          • 隱式綁定:調用位置是否有上下文對象,或者是否被某個對象擁有或者包含,那么隱式綁定規(guī)則會把函數(shù)調用中的 this 綁定到這個上下文對象。而且,對象屬性鏈只有上一層或者說最后一層在調用位置中起作用
          function foo({
            console.log(this.a);
          }

          var obj = {
            a2,
            foo: foo,
          }

          obj.foo(); // 2
          • 顯示綁定:通過在函數(shù)上運行 call 和 apply ,來顯示的綁定 this
          function foo({
            console.log(this.a);
          }

          var obj = {
            a2
          };

          foo.call(obj);

          顯示綁定之硬綁定

          function foo(something{
            console.log(this.a, something);
            
            return this.a + something;
          }

          function bind(fn, obj{
            return function({
              return fn.apply(obj, arguments);
            };
          }

          var obj = {
            a2
          }

          var bar = bind(foo, obj);

          New 綁定,new 調用函數(shù)會創(chuàng)建一個全新的對象,并將這個對象綁定到函數(shù)調用的 this。

          • New 綁定時,如果是 new 一個硬綁定函數(shù),那么會用 new 新建的對象替換這個硬綁定 this,
          function foo(a{
            this.a = a;
          }

          var bar = new foo(2);
          console.log(bar.a)

          (4)問:手寫 bind、apply、call

          // call

          Function.prototype.call = function (context, ...args{
            context = context || window;
            
            const fnSymbol = Symbol("fn");
            context[fnSymbol] = this;
            
            context[fnSymbol](...args);
            delete context[fnSymbol];
          }
          // apply

          Function.prototype.apply = function (context, argsArr{
            context = context || window;
            
            const fnSymbol = Symbol("fn");
            context[fnSymbol] = this;
            
            context[fnSymbol](...argsArr);
            delete context[fnSymbol];
          }
          // bind

          Function.prototype.bind = function (context, ...args{
            context = context || window;
            const fnSymbol = Symbol("fn");
            context[fnSymbol] = this;
            
            return function (..._args{
              args = args.concat(_args);
              
              context[fnSymbol](...args);
              delete context[fnSymbol];   
            }
          }
              

          (3)問:setTimeout(fn, 0)多久才執(zhí)行,Event Loop

          setTimeout 按照順序放到隊列里面,然后等待函數(shù)調用棧清空之后才開始執(zhí)行,而這些操作進入隊列的順序,則由設定的延遲時間來決定

          手寫題:Promise 原理

          class MyPromise {
            constructor(fn) {
              this.resolvedCallbacks = [];
              this.rejectedCallbacks = [];
              
              this.state = 'PENDING';
              this.value = '';
              
              fn(this.resolve.bind(this), this.reject.bind(this));
              
            }
            
            resolve(value) {
              if (this.state === 'PENDING') {
                this.state = 'RESOLVED';
                this.value = value;
                
                this.resolvedCallbacks.map(cb => cb(value));   
              }
            }
            
            reject(value) {
              if (this.state === 'PENDING') {
                this.state = 'REJECTED';
                this.value = value;
                
                this.rejectedCallbacks.map(cb => cb(value));
              }
            }
            
            then(onFulfilled, onRejected) {
              if (this.state === 'PENDING') {
                this.resolvedCallbacks.push(onFulfilled);
                this.rejectedCallbacks.push(onRejected);
                
              }
              
              if (this.state === 'RESOLVED') {
                onFulfilled(this.value);
              }
              
              if (this.state === 'REJECTED') {
                onRejected(this.value);
              }
            }
          }
                

          問:js腳本加載問題,async、defer問題

          • 如果依賴其他腳本和 DOM 結果,使用 defer
          • 如果與 DOM 和其他腳本依賴不強時,使用 async

          參考資料

          問:如何判斷一個對象是不是空對象?

          Object.keys(obj).length === 0

          問: <script src=’xxx’ ’xxx’/>外部js文件先加載還是onload先執(zhí)行,為什么?

          onload 是所以加載完成之后執(zhí)行的

          問:怎么加事件監(jiān)聽,兩種

          onclick 和 addEventListener

          問:事件傳播機制(事件流)

          冒泡和捕獲

          (4)問:說一下原型鏈和原型鏈的繼承吧

          • 所有普通的 [[Prototype]] 鏈最終都會指向內置的 Object.prototype,其包含了 JavaScript 中許多通用的功能
          • 為什么能創(chuàng)建 “類”,借助一種特殊的屬性:所有的函數(shù)默認都會擁有一個名為 prototype 的共有且不可枚舉的屬性,它會指向另外一個對象,這個對象通常被稱為函數(shù)的原型
          function Person(name{
            this.name = name;
          }

          Person.prototype.constructor = Person
          • 在發(fā)生 new 構造函數(shù)調用時,會將創(chuàng)建的新對象的 [[Prototype]] 鏈接到 Person.prototype 指向的對象,這個機制就被稱為原型鏈繼承

          • 方法定義在原型上,屬性定義在構造函數(shù)上

          • 首先要說一下 JS 原型和實例的關系:每個構造函數(shù) (constructor)都有一個原型對象(prototype),這個原型對象包含一個指向此構造函數(shù)的指針屬性,通過 new 進行構造函數(shù)調用生成的實例,此實例包含一個指向原型對象的指針,也就是通過 [[Prototype]] 鏈接到了這個原型對象

          • 然后說一下 JS 中屬性的查找:當我們試圖引用實例對象的某個屬性時,是按照這樣的方式去查找的,首先查找實例對象上是否有這個屬性,如果沒有找到,就去構造這個實例對象的構造函數(shù)的 prototype 所指向的對象上去查找,如果還找不到,就從這個 prototype 對象所指向的構造函數(shù)的 prototype 原型對象上去查找

          • 什么是原型鏈:這樣逐級查找形似一個鏈條,且通過  [[Prototype]] 屬性鏈接,所以被稱為原型鏈

          • 什么是原型鏈繼承,類比類的繼承:當有兩個構造函數(shù) A 和 B,將一個構造函數(shù) A 的原型對象的,通過其 [[Prototype]] 屬性鏈接到另外一個 B 構造函數(shù)的原型對象時,這個過程被稱之為原型繼承。

          標準答案更正確的解釋

          什么是原型鏈?

          當對象查找一個屬性的時候,如果沒有在自身找到,那么就會查找自身的原型,如果原型還沒有找到,那么會繼續(xù)查找原型的原型,直到找到 Object.prototype 的原型時,此時原型為 null,查找停止。這種通過 通過原型鏈接的逐級向上的查找鏈被稱為原型鏈

          什么是原型繼承?

          一個對象可以使用另外一個對象的屬性或者方法,就稱之為繼承。具體是通過將這個對象的原型設置為另外一個對象,這樣根據(jù)原型鏈的規(guī)則,如果查找一個對象屬性且在自身不存在時,就會查找另外一個對象,相當于一個對象可以使用另外一個對象的屬性和方法了。

          參考鏈接

          • https://zhuanlan.zhihu.com/p/35790971

          問:說下對 JS 的了解吧

          是基于原型的動態(tài)語言,主要獨特特性有 this、原型和原型鏈。

          JS 嚴格意義上來說分為:語言標準部分(ECMAScript)+ 宿主環(huán)境部分

          語言標準部分

          2015 年發(fā)布 ES6,引入諸多新特性使得能夠編寫大型項目變成可能,標準自 2015 之后以年號代號,每年一更

          宿主環(huán)境部分

          • 在瀏覽器宿主環(huán)境包括 DOM + BOM 等
          • 在 Node,宿主環(huán)境包括一些文件、數(shù)據(jù)庫、網(wǎng)絡、與操作系統(tǒng)的交互等

          問:數(shù)組能夠調用的函數(shù)有那些?

          • push
          • pop
          • splice
          • slice
          • shift
          • unshift
          • sort
          • find
          • findIndex
          • map/filter/reduce 等函數(shù)式編程方法
          • 還有一些原型鏈上的方法:toString/valudOf

          問:如何判斷數(shù)組類型

          Array.isArray

          問: 函數(shù)中的arguments是數(shù)組嗎?類數(shù)組轉數(shù)組的方法了解一下?

          是類數(shù)組,是屬于鴨子類型的范疇,長得像數(shù)組,

          • ... 運算符
          • Array.from
          • Array.prototype.slice.apply(arguments)

          問:用過 TypeScript 嗎?它的作用是什么?

          為 JS 添加類型支持,以及提供最新版的 ES 語法的支持,是的利于團隊協(xié)作和排錯,開發(fā)大型項目

          問:PWA使用過嗎?serviceWorker的使用原理是啥?

          漸進式網(wǎng)絡應用(PWA)是谷歌在2015年底提出的概念。基本上算是web應用程序,但在外觀和感覺上與原生app類似。支持PWA的網(wǎng)站可以提供脫機工作、推送通知和設備硬件訪問等功能。

          Service Worker是瀏覽器在后臺獨立于網(wǎng)頁運行的腳本,它打開了通向不需要網(wǎng)頁或用戶交互的功能的大門。現(xiàn)在,它們已包括如推送通知和后臺同步等功能。將來,Service Worker將會支持如定期同步或地理圍欄等其他功能。本教程討論的核心功能是攔截和處理網(wǎng)絡請求,包括通過程序來管理緩存中的響應。

          參考鏈接

          • https://juejin.im/post/5e26aa785188254c257c462d#heading-8

          問:ES6 之前使用 prototype 實現(xiàn)繼承

          Object.create() 會創(chuàng)建一個 “新” 對象,然后將此對象內部的 [[Prototype]] 關聯(lián)到你指定的對象(Foo.prototype)。Object.create(null) 創(chuàng)建一個空 [[Prototype]] 鏈接的對象,這個對象無法進行委托。

          function Foo(name{
            this.name = name;
          }

          Foo.prototype.myName = function ({
            return this.name;
          }

          // 繼承屬性,通過借用構造函數(shù)調用
          function Bar(name, label{
            Foo.call(this, name);
            this.label = label;
          }

          // 繼承方法,創(chuàng)建備份
          Bar.prototype = Object.create(Foo.prototype);

          // 必須設置回正確的構造函數(shù),要不然在會發(fā)生判斷類型出錯
          Bar.prototype.constructor = Bar;

           // 必須在上一步之后
          Bar.prototype.myLabel = function ({
            return this.label;
          }

          var a = new Bar("a""obj a");

          a.myName(); // "a"
          a.myLabel(); // "obj a"

          問:如果一個構造函數(shù),bind了一個對象,用這個構造函數(shù)創(chuàng)建出的實例會繼承這個對象的屬性嗎?為什么?

          不會繼承,因為根據(jù) this 綁定四大規(guī)則,new 綁定的優(yōu)先級高于 bind 顯示綁定,通過 new 進行構造函數(shù)調用時,會創(chuàng)建一個新對象,這個新對象會代替 bind 的對象綁定,作為此函數(shù)的 this,并且在此函數(shù)沒有返回對象的情況下,返回這個新建的對象

          (3)箭頭函數(shù)和普通函數(shù)有啥區(qū)別?箭頭函數(shù)能當構造函數(shù)嗎?

          • 普通函數(shù)通過 function 關鍵字定義, this 無法結合詞法作用域使用,在運行時綁定,只取決于函數(shù)的調用方式,在哪里被調用,調用位置。(取決于調用者,和是否獨立運行)
          • 箭頭函數(shù)使用被稱為 “胖箭頭” 的操作 => 定義,箭頭函數(shù)不應用普通函數(shù) this 綁定的四種規(guī)則,而是根據(jù)外層(函數(shù)或全局)的作用域來決定 this,且箭頭函數(shù)的綁定無法被修改(new 也不行)。
            • 一個函數(shù)內部有兩個方法:[[Call]] 和 [[Construct]],在通過 new 進行函數(shù)調用時,會執(zhí)行 [[construct]] 方法,創(chuàng)建一個實例對象,然后再執(zhí)行這個函數(shù)體,將函數(shù)的 this 綁定在這個實例對象上
            • 當直接調用時,執(zhí)行 [[Call]] 方法,直接執(zhí)行函數(shù)體
            • 箭頭函數(shù)沒有 [[Construct]] 方法,不能被用作構造函數(shù)調用,當使用 new 進行函數(shù)調用時會報錯。
            • 箭頭函數(shù)常用于回調函數(shù)中,包括事件處理器或定時器
            • 箭頭函數(shù)和 var self = this,都試圖取代傳統(tǒng)的 this 運行機制,將 this 的綁定拉回到詞法作用域
            • 沒有原型、沒有 this、沒有 super,沒有 arguments,沒有 new.target
            • 不能通過 new 關鍵字調用
          function foo({
            return (a) => {
              console.log(this.a);
            }
          }

          var obj1 = {
            a2
          }

          var obj2 = {
            a3 
          }

          var bar = foo.call(obj1);
          bar.call(obj2);

          參考資料

          • https://segmentfault.com/a/1190000015162781

          問:知道 ES6 的 Class 嘛?Static 關鍵字有了解嘛

          為這個類的函數(shù)對象直接添加方法,而不是加在這個函數(shù)對象的原型對象上

          (3)問:事件循環(huán)機制 (Event Loop)

          事件循環(huán)機制從整體上告訴了我們 JavaScript 代碼的執(zhí)行順序Event Loop即事件循環(huán),是指瀏覽器或Node的一種解決javaScript單線程運行時不會阻塞的一種機制,也就是我們經常使用異步的原理。

          先執(zhí)行宏任務隊列,然后執(zhí)行微任務隊列,然后開始下一輪事件循環(huán),繼續(xù)先執(zhí)行宏任務隊列,再執(zhí)行微任務隊列。

          • 宏任務:script/setTimeout/setInterval/setImmediate/ I/O / UI Rendering
          • 微任務:process.nextTick()/Promise

          上訴的 setTimeout 和 setInterval 等都是任務源,真正進入任務隊列的是他們分發(fā)的任務。

          優(yōu)先級

          • setTimeout = setInterval 一個隊列
          • setTimeout > setImmediate
          • process.nextTick > Promise
          for (const macroTask of macroTaskQueue) {  
            handleMacroTask();    
            for (const microTask of microTaskQueue) {    
             handleMicroTask(microTask);  
            }
          }

          參考鏈接

          • https://juejin.im/post/59e85eebf265da430d571f89

          (2)手寫題:數(shù)組扁平化

          function flatten(arr{
            let result = [];

            for (let i = 0; i < arr.length; i++) {
              if (Array.isArray(arr[i])) {
                result = result.concat(flatten(arr[i]));
              } else {
                result = result.concat(arr[i]);
              }
            }

            return result;
          }

          const a = [1, [2, [34]]];
          console.log(flatten(a));

          手寫題:實現(xiàn)柯里化

          預先設置一些參數(shù)

          柯里化是什么:是指這樣一個函數(shù),它接收函數(shù) A,并且能返回一個新的函數(shù),這個新的函數(shù)能夠處理函數(shù) A 的剩余參數(shù)

          function createCurry(func, args{
            var argity = func.length;
            var args = args || [];
            
            return function ({
              var _args = [].slice.apply(arguments);
              args.push(..._args);
              
              if (args.length < argity) {
                return createCurry.call(this, func, args);
              }
              
              return func.apply(this, args);
            }
          }

          手寫題:數(shù)組去重

          Array.from(new Set([1122]))

          問:let 閉包

          let 會產生臨時性死區(qū),在當前的執(zhí)行上下文中,會進行變量提升,但是未被初始化,所以在執(zhí)行上下文執(zhí)行階段,執(zhí)行代碼如果還沒有執(zhí)行到變量賦值,就引用此變量就會報錯,此變量未初始化。

          問:變量提升

          函數(shù)在運行的時候,會首先創(chuàng)建執(zhí)行上下文,然后將執(zhí)行上下文入棧,然后當此執(zhí)行上下文處于棧頂時,開始運行執(zhí)行上下文。

          在創(chuàng)建執(zhí)行上下文的過程中會做三件事:創(chuàng)建變量對象,創(chuàng)建作用域鏈,確定 this 指向,其中創(chuàng)建變量對象的過程中,首先會為 arguments 創(chuàng)建一個屬性,值為 arguments,然后會掃碼 function 函數(shù)聲明,創(chuàng)建一個同名屬性,值為函數(shù)的引用,接著會掃碼 var 變量聲明,創(chuàng)建一個同名屬性,值為 undefined,這就是變量提升。

          instance 如何使用

          左邊可以是任意值,右邊只能是函數(shù)

          'hello tuture' instanceof String // false

          參考資料


          ??愛心三連擊

          1.看到這里了就點個在看支持下吧,你的點贊在看是我創(chuàng)作的動力。

          2.關注公眾號程序員成長指北,回復「1」加入高級前端交流群!「在這里有好多 前端 開發(fā)者,會討論 前端 Node 知識,互相學習」!

          3.也可添加微信【ikoala520】,一起成長。

          “在看轉發(fā)”是最大的支持

          瀏覽 21
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  特黄aaaaaaaa真人毛片 | 俺来也俺也射 | www.俺来也.com | 逼特逼视频在线 | www.91爱爱,com |