<dl id="opymh"></dl>

<div id="opymh"></div>
      <div id="opymh"><tr id="opymh"></tr></div>

        <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

        <em id="opymh"></em>

        <em id="opymh"><ol id="opymh"></ol></em>

              頻道欄目
              首頁 > 程序開發 > web前端 > HTML/CSS > 正文
              2019面試筆記個人文章
              2019-03-08 15:19:16           
              收藏   我要投稿

              一.js原始類型:

              在js中,存在著6種原始值:

              * boolean 
              * number 
              * string 
              * undefined 
              * null 
              * symbol 

              注意: 雖然typeof null輸出的是object,但是null并不是object類型,因為早期的bug;

              number類型是浮點數類型,所以才會有js精度問題出現。0.1+0.2 !== 0.3。 原始類型存儲的都是值,是沒有函數可以調用的。 
              symbol類型: symbol類型的對象永遠不相等,即便創建他們的時候傳入了相同的值,可以借助此特性解決屬性名的沖突問題。
              for...in..拿不到symbol類型的屬性值,而且要用[]的方式來讀取symbol類型的屬性值,用點的方式讀不到。

              二.對象(Object)類型:

              在js中,除了原始類型其他的就是對象類型了。
              Q1:對象類型和原始類型的不同之處?

              答:對象類型和原始類型不同的是,原始類型存貯的是值,對象那個類型存儲的是地址(指針)。當創建了一個對象類型的時候,計算機回在內存
              中開辟一個空間賴存放值,但是我們需要找到這個空間,這個控件會擁有一個地址(指針)。當我們將變量賦值給另外一個變量時,復制的是原本變量的地址(指針)。 

              Q2:函數參數是對象會發生什么?

              答:函數參數是對象的話,在函數內部可能會改變這個參數對象,生成新對象。

              三.typeof VS instanceof

              Q1:typeof是否能正確判斷類型?

              答:對于原始類型來說,typeof除了null都可以正確顯示類型,typeof null顯示的是object是錯誤的。對于其他的,除了function會返回function,其他都會返回object。

              Q2. instanceof能正確判斷對象的原理是什么?

              答:instanceof內部機制是通過原型鏈來判斷對象類型的。 
                eg: const Person = function () {} 
                    const p1 = new Person() p1
                    instanceof Person // true 
                    var str = 'hello world' str instanceof String // false 

              四.類型轉換:

              1.轉Boolean: 在條件判斷時,除了undefined,null,0,-0,NaN,'',false,其他所有值都轉化為true,包括所有對象。
              2.對象轉原始類型: 對象在轉換類型的時候,會調用內置的[[ToPrimitive]]函數,對于該函數來說,

              算法邏輯一般來說如下:
                * 如果已經是原始類型了,就不需要換磚了
                * 調用x.valueof(),如果轉換為基礎類型,就返回轉換的值
                * 調用x.toString(),如果轉化為基礎類型,就返回轉換的值 
                * 如果都沒有返回原始類型,就會報錯 1)四則運算符: 加法運算符特點: 
                *運算中如果一方為字符串,那么就會把另一方葉轉換為字符串,1 + '1' // '11' 
                *如果一方不是字符串或者數字,那么會將它轉化為數字或者字符串:true+ true // 2 ; 4 + [1,2,3] // '41,2,3' 
              注意: + 'a'是快速將'a'轉化成number類型的寫法;'a' + + 'b' // 'aNaN' 那么對于除了加法運算符其他運算符來說,只要一方是數字,那么另一方就會被轉化為數字。反正最終都是要轉化為數字來運算。
                    4 * '3' // 12 4 * [] // 0 4 * [1,2] // NaN 2)比較運算符 大于小于運算都會轉化為數字進行運算。 
              關于 ==: 
              *undefined 等于 null 
              *字符串和數字比較時,字符串轉數字 
              *數字和布爾類型比較時,布爾轉數字
              *字符串和布爾比較時,兩者轉數字 

              五.this

              this永遠指向最后調用它的那個對象。
              1.改變this指向:

              * 使用es6箭頭函數 
              * 在函數內部使用 _this = this 
              * 使用 apply,call,bind 
              * new 實例化一個對象

              2.箭頭函數: 箭頭函數的this始終指向函數定義時的this,而非執行時(意味著如果箭頭函數被非箭頭函數包含,this綁定的就是最近一層非箭頭函數的this)。

              箭頭函數中沒有this綁定,必須通過查找作用域鏈來決定其值。 

              3.apply,call,bind區別
              apply和call只是傳入的參數不同。call接受的是若干個參數列表,而apply接受的是一個包含多個參數的數組。
              bind和apply,call區別:

              bind創建了一個新的函數,需要手動去調用它; 

              六.new的過程:

              創建一個空對象obj; 將新創建的空對象的隱式原型指向其構造函數的顯示原型; 使用call改變this的指向; 如果無返回值或者返回一個非對象值,則將obj返回作為新對象;如果返回值時一個新對象的華那么直接返回該對象。

              七. == VS ===

              Q1: ==和 === 有什么區別?

              答: 對于 == 來說,如果雙方的類型不一樣的華,就會進行類型轉換。
                  流程: 
                    * 首先判斷兩者類型是否相同 
                    * 判斷是否為 undefined == null //true 
                    * string轉number比較 * boolean轉number比較
                    * object轉原始類型比較 但是,=== 的比較只需要判斷兩者類型和值是否相同。 

              八.閉包:

              Q1: 什么是閉包?

              答:函數A內部有一個函數B,函數B可以訪問到函數A中的變量,那么函數B就是閉包。 

              Q2:經典面試題:循環中使用閉包解決var定義函數的問題:
              答:第一種:使用閉包的方式: for (var i = 1; i <=5 ; i++) { ;(function(j) { setTimeout(function timer() { console.log(j) }, j * 1000) })(i)}

                第二種:用let定義的方式: for (let i=1 ; i <=5 ; i++) { setTimeout(function timer() { console.log(i) }, i * 1000) } Q3:閉包的優缺點? 閉包作用(優點):可以讀取到函數內部的變量,可以讓這些變量的值始終保持在內存中,不會被垃圾回收掉。

              閉包缺點:因為閉包會使得函數中變量保存在內存中,所以會增大內存使用量,使用不當很容易造成內存泄漏。浪費內存。
              清除閉包:退出函數之前,將不使用的局部變量刪除。

              九.深淺拷貝:

              1.堆和棧:棧(stack)為自動分配的內存空間,它由系統自動釋放;而堆(heap)則是動態分配的內存,大小不定也不會自動釋放。
              2.基本數據類型存放在棧中,數據大小確定,內存空間大小可以分配,是直接按值存放的,所以可以直接訪問。基本類型的比較是值的比較。
              3.引用類型存放在堆中,變量實際上存放的是棧1內存的指針,引用類型的值可變。引用類型的比較是引用的比較。所以比較兩個引用類型,是看其的引用是否指向同一個對象。
              Q1.淺拷貝?

              答:淺拷貝只復制一層對象的屬性,并不包括對象里面的為引用類型的數據。 

              Q2.深拷貝?

              答: 深拷貝遞歸復制了對象的所有層級屬性。 

              Q3.深拷貝,淺拷貝以及賦值的區別?

              答:淺拷貝,深拷貝和原數據都不是指向同一對象,而賦值對象和原對象是指向同一對象。
              第一層數據為基本類型,改變會使原數據改變,深拷貝以及淺拷貝不會。 原數據中包含子對象,改變子對象會使賦值對象以及淺拷貝對象改變,不會使深拷貝對象改變。 

              Q4.如何實現淺拷貝?

              答:1.可以通過Object.assign來解決。(Object.assign()方法用于將所有可枚舉的值從一個或多個源對象復制到目標對象。它將返回目標對象。)
                  eg: 
                    let a={ age: 1 } 
                    let b=O bject.assign({}, a) 
                    a.age=2 console.log(b.age) // 1 
                  2.可以通過展開運算符...來實現淺拷貝 
                  eg: 
                    let a={ age: 1} 
                    let b={ ...a } 
                    a.age=2 console.log(b.age) // 1 

              Q5.如何實現深拷貝?

              答:1.該問題可以通過JSON.parse(JSON.stringify(object))來解決。 
                  eg: let a={age: 1, jobs: { first: 'FE' } } 
                      let b=J SON.parse(JSON.stringify(a)) 
                      a.jobs.first='native' 
                      console.log(b.jobs.first) // FE
                  但是該方法也是有局限性的: 
                    * 會忽略undefined 
                    * 會忽略symbol 
                    * 不能序列化函數 
                    * 不能解決循環引用的對象 

              十:原型和原型鏈:

              js是基于原型的繼承。
              1.使用構造函數創建對象后,新對象與構造函數沒有關系了,新對象的[[prototype]]屬性指向的是構造函數的原型對象。
              2.構造函數、原型和實例的關系:

              * 構造函數都有一個屬性prototype,這個屬性是一個對象(Object的實例)
              * 原型對象里面有個constractor屬性,該屬性指向原型對象所屬的構造函數。當原型對象被修改過,constractor就不一定指向原來的構造函數了。
              * 實例對象都有一個_proto_屬性,該屬性也指向構造函數的原型對象,它是一個非標準屬性,不可以用于編程,它用于瀏覽器自己使用。

              3.prototype和_proto_的關系:

              * prototype是構造函數的屬性;
              * _proto_是實例對象的屬性;
              * 這兩者都會指向同一個對象。
              總結:*函數也是對象,對象不一定是函數;
                    * 對象的本質:無序的鍵值對集合,鍵值對當中的值可以是任意數據類型的值;
                    *對象就是一個容器,這個容器當中放的是屬性和方法。

              4.原型鏈:

              原型鏈就是可以理解為有限的實例對象和原型之間組成的有限鏈,就是用來實現屬性共享和繼承的。

              5.屬性搜索:

              * 在訪問對象的某個成員的時候在對象中查找是否存在;
              * 如果當前對象中沒有就在構造函數的原型對象中查找;
              * 如果原型對象中沒有就在原型對象的原型上找;
              * 直到找到Object的原型對象的原型是null為止。
              eg:
                var arr = []
                原型鏈:arr -> Array.prototype -> Object.prototype -> null

              Q1:什么是原型?

              答: 原型也是一個對象,并且這個對象中包含了很多函數。原型的constract屬性指向構造函數,構造函數又通過prototype屬性指回原型,到那時并不是所有函數都具有這個屬性。

              十一:js繼承:

              1.原型鏈繼承:將父類的實例作為子類的原型。

              eg:Cat.prototype = new Animal()
              缺點:子類無法給父類傳參,子類要新增屬性和方法的話,必須要在new Parent()這樣的語句之后執行,否則會被覆蓋。

              2.構造繼承:使用父類的構造函數來增強子類的實例,等于是在子類的構造函數內部執行Parent.call(this)。

              eg:function Cat(name) {
                Animal.call(this);
                this.name = name || 'Tom';
              }
              var cat = new Cat();
              缺點:沒有原型,每次創建一個子類實例都要執行一遍Parent函數。

              3.組合式繼承:結合原型鏈繼承和構造繼承,組合式繼承在使用過程中會被調用兩次:一次是創建子類的時候,一次是在子類構造函數的內部。

              eg: function Cat(name){
                  Animal.call(this);
                  this.name = name || 'Tom';
                }
                Cat.prototype = new Animal();

              3.class繼承:

              class繼承的核心在于使用extends表明繼承自哪個父類,并且在子類構造函數中必須調用super,因為這段代碼可以看成Parent.call(this,value).
              eg:
              class Parent {
                constructor(value) {
                  this.val = value
                }
                getValue() {
                  console.log(this.val)
                }
              }
              class Child extends Parent {
                constructor(value) {
                  super(value)
                  this.val = value
                }
              }
              let child = new Child(1)
              child.getValue() // 1
              child instanceof Parent // true
              

              十二:var、let及const區別:

              1.var和let區別:

              * let有塊級作用域的說法,也就是let聲明的變量只能在這個塊內部使用,別的地方不能使用。var聲明的變量可以在全局使用,var在函數內部聲明的變量只能在函數內部使用。
              * let沒有變量提升,var有變量提升
              * let聲明的變量存在“暫時性死區”,而var聲明的變量沒有
              * let不允許在同一個快內重復聲明一個變量。因此也不能在函數內部重復聲明一個變量。
              * var聲明的變量會掛載到window上,而let聲明的對象不會掛載到window上。
              

              const特性:

              const聲明一個只讀的常量。一旦聲明,常量的值就不能改變; const聲明的變量必須初始化,不然會報錯; const聲明的變量也存在暫時性死區; const聲明的變量只在所聲明的塊級作用域內有效; const聲明的常量也與let一樣不可重復聲明。

              Q1.什么是提升?

              答:就是變量可以在神明之前使用,并且值為undefined。

              Q2. 什么是暫時性死區?

              答:在let命令聲明之前,該變量都素hi不可用的。

              十三.模塊化:

              Q1.為什么要使用模塊化?

              答:使用模塊化可以帶來以下好處:
                * 解決命名沖突;
                * 提供復用性;
                * 提高代碼可維護性。

              Q2.實現模塊化的方式?

              CommonJS  AMD  CMD

              1.require/exports:

              遵循CommonJS/AMD,只能在運行時確定模塊的依賴關系及輸入/輸出的變量,無法進行靜態優化。

              2.import/export:

              遵循ES6規范,支持編譯時靜態分析,便于JS引入宏和類型檢驗,動態綁定。
              
              點擊復制鏈接 與好友分享!回本站首頁
              相關TAG標簽 js
              上一篇:我理解的core目錄 Angularx項目開發雜亂隨筆
              下一篇:最后一頁
              相關文章
              圖文推薦
              點擊排行

              關于我們 | 聯系我們 | 廣告服務 | 投資合作 | 版權申明 | 在線幫助 | 網站地圖 | 作品發布 | Vip技術培訓 | 舉報中心

              版權所有: 紅黑聯盟--致力于做實用的IT技術學習網站

              极速飞艇好假
              <dl id="opymh"></dl>

              <div id="opymh"></div>
                  <div id="opymh"><tr id="opymh"></tr></div>

                    <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

                    <em id="opymh"></em>

                    <em id="opymh"><ol id="opymh"></ol></em>

                          <dl id="opymh"></dl>

                          <div id="opymh"></div>
                              <div id="opymh"><tr id="opymh"></tr></div>

                                <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

                                <em id="opymh"></em>

                                <em id="opymh"><ol id="opymh"></ol></em>