<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>

          前端面試資料整理【javascript篇】

          共 11474字,需瀏覽 23分鐘

           ·

          2022-05-16 15:54

          作者:donggg

          來源:SegmentFault  思否社區(qū) 


          塊級作用域(執(zhí)行結(jié)果題)



          塊級作用域:https://blog.poetries.top/browser-working-principle/guide/part2/lesson09.html


          阮一峰 塊級作用域:https://www.bookstack.cn/read/es6-3rd/spilt.2.docs-let.md


          var a = 1999;
          {
              console.log(a); // function a(){}
              a = 2020;
              function a() {}
              a = 2021;
          }
          console.log(a); // 2020


          我的理解:(原理可能錯(cuò)誤,但是便于理解,錯(cuò)誤點(diǎn)在于塊級不能聲明函數(shù),瀏覽器會(huì)有自己的支持行為,類似于函數(shù)表達(dá)式聲明——參考阮一峰。聲明也不要用函數(shù)聲明的方式,用函數(shù)表達(dá)式的方式。)


          在塊級中,編譯過程,函數(shù)聲明變量提升,執(zhí)行過程無影響。因此是 function a(){}在塊級外部,編譯過程,外部有a,無影響。執(zhí)行過程時(shí),開始查找,由于 a 的查找順序是從詞法環(huán)境({})到變量環(huán)境(var),查找到最近的,因此是 2020(注意此處是執(zhí)行階段,function a(){} 的變量提升是編譯階段)


          ps.函數(shù)和變量相比,會(huì)被優(yōu)先提升。(我的理解:這意味著函數(shù)會(huì)替換掉變量提升)


          事件冒泡、事件捕獲、事件代理(事件委托)



          事件冒泡:略


          事件捕獲:略


          事件代理:利用事件冒泡,將事件綁定在父元素中

          target.addEventListener(type, listener, useCapture); ,其中useCapture 為 false 時(shí),為事件冒泡,默認(rèn)是 false


          Object



          常見的方法:


          • Object.defineProperty 定義的 description: { value, writable, configurable, emunable },或者 { set, get, configurable, emunable }

          • Object.create 、Object.keys、Object.values、Object.entries、Object.toString

          • Object.preventExtensions 組織擴(kuò)展對象


          作用域、作用域鏈和上下文



          作用域是指在函數(shù)定義時(shí),聲明變量的空間。


          作用域鏈?zhǔn)侵冈谧兞坎檎疫^程中,從當(dāng)前上下文查找,逐層往父級,直至全局。
          函數(shù)聲明時(shí),會(huì)有個(gè) scope 屬性,包含所有父級的變量。此時(shí) VO對象,包含內(nèi)部函數(shù)、變量、形參,存儲(chǔ)在上下文中。

          函數(shù)執(zhí)行時(shí),AO對象,包含內(nèi)部函數(shù)、變量、形參、內(nèi)部this,掛載到作用域鏈上,

          作用域、作用域鏈與執(zhí)行上下文棧入門了解:https://blog.csdn.net/star66666651/article/details/107168254


          原形鏈



          待補(bǔ)充


          Promise 與異步



          常見的異步請求:


          var request = new HttpXMLRequest()
          request.open('GET', url);
          request.responseType = 'json'
          request.onload = function(){}
          request.send()


          原生

          實(shí)現(xiàn)Promise

          待補(bǔ)充

          // Promise

          // Promise.prototype.then

          // Promise.prototype.all

          // Promise.prototype.resolve

          // Promise.prototype.race

          事件循環(huán)與事件隊(duì)列



          事件循環(huán)

          組成:

          • 事件隊(duì)列(單位是消息,消息關(guān)聯(lián)著回調(diào)函數(shù),從消息隊(duì)列中彈出后會(huì)調(diào)用回調(diào)函數(shù),形成執(zhí)行幀)

          • 執(zhí)行棧(單位是幀,包含函數(shù)中的變量與參數(shù))

          • 堆(保存對象結(jié)構(gòu))


          同步任務(wù)與異步任務(wù)
          window.requestAnimationFrame() 既不是宏任務(wù)也不是微任務(wù),而是在瀏覽器下次重繪的時(shí)候執(zhí)行


          閉包



          兩個(gè)主要的特點(diǎn):

          • 通過函數(shù)阻止外部函數(shù)對內(nèi)部變量的引用
          • 函數(shù)可以使用外部的變量

          參考:http://jartto.wang/2017/12/18/reflective-closure/

          閉包中的this

          由于閉包是執(zhí)行在內(nèi)存中,所以 this 通常指向全局,可以通過 call 改變。

          閉包的作用

          • 通過立即執(zhí)行函數(shù),模擬塊級作用域,減少向全局作用域聲明變量,另外由于立即執(zhí)行函數(shù)在執(zhí)行完后外部沒有引用,那么內(nèi)存會(huì)立即釋放

          • 使用 var 聲明時(shí),利用立即執(zhí)行函數(shù)遍歷時(shí) i 能準(zhǔn)確獲取

          • 實(shí)現(xiàn)面向?qū)ο缶幊蹋ú皇峭ㄟ^ new 構(gòu)造)


          function Person(){
            var name = 'default';
            return {
              getName : function(){
                return name;
              },
              setName : function(newName){
                name = newName;
              }
            }
          };
          var p1 = Person();
          console.log(p1.getName()); // default
          p1.setName('wang');
          console.log(p1.getName()); // wang

          閉包的問題

          • 在閉包中引用 dom 會(huì)導(dǎo)致循環(huán)引用,無法 GC(引用計(jì)數(shù))

          // IE9 之前甚至無法銷毀 dom
          function closure(){
            var element = document.getElementById(ID);
            element.onclick = function(){
              console.log(element.id);
            }
            // 銷毀 element
            // element = null
          }

          • this 指向
          • 閉包返回局部作用域變量時(shí),內(nèi)存不會(huì)立即釋放


          宏任務(wù) 和 微任務(wù)



          常見異步考題:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7


          es5/es6/es7/es8



          待補(bǔ)充


          class 中的 super



          super 既可以當(dāng)函數(shù)也可以當(dāng)對象使用。


          當(dāng)函數(shù)時(shí),相當(dāng)于是父類的構(gòu)造函數(shù),只能用在子類的構(gòu)造函數(shù)中,this 指向子類實(shí)例。

          class A {
            constructor() {
              this.show();
            }
            show(){
              console.log('A 實(shí)例');
            }
          }
          class B extends A {
            constructor() {
              super();
            }
            show(){
              console.log('B 實(shí)例');
            }
          }
          new B() // B 實(shí)例

          當(dāng)對象時(shí),在一般函數(shù)使用時(shí),super 相當(dāng)于父類原型對象,this 指向子類實(shí)例 。

          class A {
            constructor() {  
              this.x = 'A';
            }
            say() {
              console.log(this.x)
            }
          }
          class B extends A {
            constructor() {
              super();
              this.x = 'B'
            }
          }
          let b = new B();
          console.log(b.say()) // B

          ps. 注意該提醒

          class A {
            constructor() {  // 在構(gòu)造函數(shù)上定義的屬性和方法相當(dāng)于定義在父類實(shí)例上的,而不是原型對象上
              this.p = 2;
            }
          }
          class B extends A {
            get m() {
              return super.p;
            }
          }
          let b = new B();
          console.log(b.m) // undefined

          // 引申題
          function A(x) {
              this.p = x
          }
          A.prototype.p = 2
          // 此時(shí)的 p 通過構(gòu)造函數(shù)已經(jīng)聲明
          new A().p // undefined

          super 在靜態(tài)方法 this 指向父類


          常見的代碼



          防抖與節(jié)流


          防抖是指,在一段時(shí)間內(nèi)累計(jì)后觸發(fā),例如輸入框輸入文字時(shí),監(jiān)聽 onChange。

          function debounce(fn, delay) {
              let timer
              return function () {
                  const self = this;
                  const args = arguments;
                  if (timer) {
                      clearTimeout(timer);
                  }

                  timer = setTimeout(function(){
                      fn.apply(self, args);
                  }, delay)
              }
          }

          let log = debounce(function(){ console.log('!')}, 5000)

          window.addEventListener('resize',log)

          節(jié)流是指,在一段時(shí)間內(nèi)多次重復(fù)觸發(fā)僅執(zhí)行一次,例如重復(fù)點(diǎn)擊。

          function throttle(fn, delay) {

              let timer
              
              return function () {
                  const self = this;
                  const args = arguments;
                  if (timer) {
                      return;
                  }

                  timer = setTimeout(function() {
                      self.apply(fn, args)
                      timer = null;
                  }, delay)
              }
          }

          let log = throttle(function(){ console.log('!')}, 3000)

          window.addEventListener('click',log)

          形成這種區(qū)別的原因:

          節(jié)流當(dāng)?shù)谝淮螆?zhí)行是 arg 就固定了,也就是說如果用節(jié)流放到輸入框 onChange 場景時(shí),值將是第一個(gè)輸入的數(shù)字。

          防抖,通過不斷的 clearTimeout,來更新要執(zhí)行的函數(shù),直到不觸發(fā)后,等待 delay 后執(zhí)行,delay 的作用是在此期間如果再次觸發(fā),則會(huì)再次 clearTimeout

          手寫new



          // Object.create 會(huì)更新 __proto__,也就是 [[Prototype]],維持原形鏈
          function create (proto) {
              if (typeof proto !== 'object' && typeof proto !== 'function' ) {
                  throw new TypeError("原型只能是對象")
              }
              if (proto === null) {
                  throw new TypeError("不能為空")
              }

                  // function F() {}
                  //F.prototype = proto;
                  // return new F();
              proto.constructor.prototype = proto
              return new proto.constructor()
          }

          function newOperator(ctor) {
              if (typeof ctor !== 'function') {
                  throw '構(gòu)造函數(shù)必須是方法'
              }

              newOperator.target = ctor;

              // es6 可以直接使用 Object.create
              // const instance = Object.create(ctor.prototype)
              const instance = create(ctor.prototype)
              const args = [].slice.call(arguments, 1)
              // 綁定 this,并執(zhí)行構(gòu)造函數(shù)
              const r = ctor.apply(instance, args);
              // 如果構(gòu)造函數(shù)有返回,則返回構(gòu)造函數(shù)
              if (r) {
                  return r;
              }

              // 實(shí)例
              return instance;
          }

          function Person (name) {
              this.name = name
          }


          const w = newOperator(Person, "zs")

          console.log(w)


          手寫bind



          function bind(fn, obj) {
              const args = [].slice.call(arguments, 1);
              const selef = this;
              return function bound() {
                  return fn.call(obj, [].slice.call(arguments, 1).concat(args))
              }
          }

          const h = {
              name: 'zs',
          }

          function say() {
              console.log(this.name)
          }

          const bound = bind(say, h)
          bound()


          Object.is Polyfill



          if (!Object.is) {
            Object.defineProperty(Object, "is", {
              value: function (x, y) {
                  if (x === y) {
                      // 1. 如果 x === y,且均不為0時(shí)
                      // 2. 如果 x,y 均為 0 ,判斷符號是否相等
                      return x !== 0 || 1 / x === 1 / y; 
                  } else {
                      // NaN 與自己比較。包含:Number.NaN, 0/0, NaN
                      return x != x && y != y;
                  }
              }
            })
          }


          如何實(shí)現(xiàn) Array.reduce()



          待補(bǔ)充


          curry 與 compose



          待補(bǔ)充


          Object.assign()



          待補(bǔ)充


          實(shí)現(xiàn)字符串 repeat



          // 原生repeat 'ni'.repeat(3); 
          // 'ninini' 
          // 實(shí)現(xiàn)一 
          String.prototype.repeatString1 = function (n) { 
              return Array(n + 1).join(this); 

          console.log('ni'.repeatString1(3)); 
          // 實(shí)現(xiàn)二 
          String.prototype.repeatString2 = function (n) { 
              return Array(n).fill(this).join('');
          }
          console.log('ni'.repeatString2(3));


          js 模板引擎



          Function('let a = 1');


          其他



          https://juejin.cn/post/6844903575559077895#heading-16



          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動(dòng)和交流,掃描下方”二維碼“或在“公眾號后臺回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -


          瀏覽 25
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  天天撸夜夜操 | 久久久久极品 | 成人呦呦 | 久久久福利视频 | 波多野结衣网站视频 |