《一名【合格】前端工程師的自檢清單》—— JavaScript基礎 之 變量和類型

前言

前幾天,@ConardLi 發佈了一篇名叫《一名【合格】前端工程師的自檢清單》的文章,才發現本身的知識體系原來有如此多的漏洞。這裏也感謝做者的分享。由此,我也萌發了對照列表,記錄和學習一遍,讓本身沒那麼迷茫。html

1、JavaScript基礎

1. JavaScript規定了幾種語言類型 (7 種)

基本數據類型(6種):string, number, boolean, null, undefined, symbol
引用數據類型(*):Object (萬物皆對象...)
複製代碼

2. JavaScript對象的底層數據結構是什麼

散列表(哈希表)
複製代碼

3. Symbol類型在實際開發中的應用、可手動實現一個簡單的Symbol

我已知使用的地方,組件屬性(mixin 模式)、常量定義。
要手寫必須先了解Symbol.
複製代碼

Symbol

特色 實例
函數 Symbol()
不能經過 new 關鍵字調用函數 new Symbol() => TypeError
instanceof 指向爲 false let a = Symbol('a');a instanceof Symbol => false
返回值類型爲 "symbol" typeof Symbol() === 'symbol'
惟一 Symbol() != Symbol()
可傳參,toString可查看 Symbol('foo').toString() === 'Symbol(foo)'
Symbol 不能夠運算 'Im a' + Symbol('foo') => TypeError
Symbol 可顯式轉 Str 和 Bool, 不能轉 Num String(Symbol('foo')) || Boolean(Symbol('foo'))
Symbol 屬性不能用常規方法遍歷 (for in)
Symbol.for([desc]) 設置惟一Symbol Symbol.for('foo') === Symbol.for('foo')
Symbol.keyFor([Symbol]) 查找Symbol 的key let a = Symbol.for('foo');Symbol.keyFor(a) === 'foo'

此外咱們須要先看一下Symbol 的規範前端

Symbol ( [ description ] )es6

When Symbol is called with optional argument description, the following steps are taken:segmentfault

  1. If NewTarget is not undefined, throw a TypeError exception. (不能 new)
  2. If description is undefined, let descString be undefined. ()
  3. Else, let descString be ToString(description).
  4. ReturnIfAbrupt(descString). (報錯就返回)
  5. Return a new unique Symbol value whose [[Description]] value is descString. (返回一個惟一Symbol值,Description 的值就是 descString 的值)
(function (w) {
            // 10. 能夠經過 Symbol.for 來設置全局惟一的 Symbol. ( 核心: 作一個映射表便可 )
            let globalSymbolMap = {}
            
            // ok 1. 函數 ok3
            function MySymbol(description) {
                // ok 2. 沒法使用 new 關鍵字
                if(this instanceof MySymbol)
                    throw new TypeError('MySymbol is not a constructor')

                // ok 3. instanceof 返回 false. 所以只能對象
                // err 4. 沒法實現 typeof MySymbol() === 'symbol',
                // ok 5. 返回的對象不是同一個,固然不同
                // ok 6. `Symbol('foo').toString() === 'Symbol(foo)'` 實現
                let symbol = Object.create({
                    toString() {
                        return 'MySymbol(' + ( this.__Description__ || '' )+ ')'
                    },
                    //ok 7. 運算會調用 valueOf , 覆寫便可。
                    //ok 8. 能夠顯示轉 String 和 Boolean, 不能轉 Number (由於複寫了 valueOf)
                    valueOf() {
                        throw new Error('Cannot convert a MySymbol value')
                    }
                })
                // err 9.沒法作到沒法被變遍歷。 由於遍歷對象是不肯定的,對象的屬性設置也是須要控制那個對象才能夠。
                Object.defineProperties(symbol, {
                    '__Description__': {
                        value: description === undefined ? undefined : String(description),
                        writable: false,
                        enumerable: false,
                        configurable: false
                    }
                })

                return symbol
            }
            // 10 設置for
            Object.defineProperties(MySymbol, {
                for: {
                    value: function(desc) {
                        if (globalSymbolMap[desc])
                            return globalSymbolMap[desc]
                        globalSymbolMap[desc] = MySymbol()
                        return globalSymbolMap[desc]
                    },
                },
                // 11. 設置 keyFor
                keyFor: {
                    value: function(symbol) {
                        for(let key in globalSymbolMap)
                            if (symbol === globalSymbolMap[key])
                                return key
                    },
                }
            })

            w.MySymbol = MySymbol
        })(window)
複製代碼

4. JavaScript中的變量在內存中的具體存儲形式

基本數據類型 和 引用數據類型。

內存中會被開闢兩塊地方,一個是棧區,一個是堆區。基本數據類型的值會放在棧,引用數據類型的值會放在堆,它在堆的地址會放在棧。

// 本身隨便畫的,你們不要噴我。。。。。
複製代碼

堆和棧

5. 基本類型對應的內置對象,以及他們之間的裝箱拆箱操做

以前有說過基本數據類型有6種。其中,Symbol 較爲特殊。他必須經過 Symbol() 獲取,由於沒有拆箱和裝箱。
複製代碼
  • null => Null
  • undefined => Undefined

上面兩個類型下都只有一個值,也沒方法,就不及與討論。數組

  • number => Number
  • string => String
  • boolean => Boolean

拆箱操做:valueOf()或者toString()安全

裝箱操做:調用其餘操做對當前數據進行操做的方法.(例如,String.toFixed , String.substring )前端工程師

6. 理解值類型和引用類型

根據第5題,值類型的數據直接存放在棧。引用類型在棧中存放了真實數據的地址
複製代碼

7. null和undefined的區別

表象:
    null: 是關鍵字,typeof null 是 object。
    undefined:是全局變量,爲了用於區分空值和未定義而引入的。
複製代碼

根據 js權威指南中的描述:數據結構

null 和 undefined 都表示「值的空缺」函數

你能夠認爲undefined是表示系統級的、出乎意料的或相似錯誤的值的空缺,而null是表示程序級的、正常的或在乎料之中的值的空缺。post

8. 至少能夠說出三種判斷JavaScript數據類型的方式,以及他們的優缺點,如何準確的判斷數組類型

  • typeof
    • 優勢:簡單....(也不知道算不算)
    • 缺點:區分不了 null 和 object 和 array,
  • instanceof (判斷變量是否爲 某對象的實例)
    • 優勢:null instanceof Object === false; [] instanceof Array === true;
    • 缺點:區分不了基本數據類型
  • Object.prototype.toString.call(data) 其中,data 爲入參
    • 優勢:能夠分辨大部分類型
    • 缺點:引用數據類型不能辨別具體得一些區別.(例如, 自定義的 Person 函數,返回的是 [object Object])

9. 可能發生隱式類型轉換的場景以及轉換原則,應如何避免或巧妙應用

下圖是《Javascript 權威指南》關於數據轉換的表

出自《Javascript 權威指南》

我的總結就是

  • string + 其餘類型,加號就是作字符串拼接。其餘數字類型就會轉換成 string類型再相加。

    • "string" + 1 => "string1"
    • "string" + true => "stringtrue"
    • "string" + null => "stringnull"
    • "string" + undefined => "stringundefined"
    • "string" + [] => "string"
    • "string" + {} => "string[object object]"
  • number: 通常用一下類型,都會轉Number.

    1. +/- 在前
    2. [+ - * / %] (算術運算符)
    3. [> < >= <= == != === !===] (關係運算符)

    以下:

    • +"1" => 1
    • -true => -1
    • 1 + true => 2
    • 1 + ["9"] => 19
    • 1 + [9] => 19
    • +[9] + 1 => 10
    • 1 + null => 1
    • 1 + {} => 1[object Object]

    關係運算符

    • "2" > 10 => false // 轉數字比較
    • "2" > "10" => true // 比的是 ASCII碼
    • NaN == NaN => false
    • undefined == null => false

    看到有一些史詩級坑的例子

    • [] == 0 //true
    • ![] == 0 // true
    • [] == ![] // true
    • [] == [] // false
    • {} == !{} // false
    • {} == {} // false

10.出現小數精度丟失的緣由,JavaScript能夠存儲的最大數字、最大安全數字,JavaScript處理大數字的方法、避免精度丟失的方法

  • 背景: JS 遵循的是 IEEE 754 規範,採用雙精度存儲,佔用 64 bit,也就是8位。雖然不少看似有窮的數據,對於計算機來講確實無窮的。如,大整數,浮點數。計算機只有0和1,因此十進制裏面的四捨五入,在計算機裏面就會變成 「0舍1入」了。

  • js 裏面最大的數字是 2^53。緣由:64位,1位表示正負,11位表示指數,52位表示尾數。52 + 1 = 53

  • js 裏面最大的安全數字是 2^53 - 1

  • 在我我的工做中,如如有大數字和浮點精度要求較高都是用 String存入。

其餘

文章有誤之處,敬請指正,以避免誤導你們~

參考文獻

相關文章
相關標籤/搜索