讓前端面試不在難(三)

今天聊一下clone這個前端面試高頻問題,由此引出typeof、instanceof、Object.prototype.toString這些javascript Api。

下面我們先詳細的聊一下,完了解決下面試官的問題。

typeof

typeof能獲取一個變量或表達式的類型。

  • 原始類型

    • Boolean
    • Null
    • Undefined
    • String
    • Symbol
    • Number
    • Symbol
  • 和 引用類型 Object,Function

下面看一些栗子

        //基礎類型也可以說非引用類型
        let str = 'hello word!'
        console.log(typeof str) //string
        let num = 12
        console.log(typeof num) //number
        let udf = undefined
        console.log(typeof udf) //undefined
        let bl = true
        console.log(typeof bl) //boolean
        let nl = null
        console.log(nl) //null
        let sl = Symbol()
        console.log(typeof sl) //symbol

        //複合類型也可以說是引用類型,
        let obj = {
            a: 1
        }
        console.log(typeof obj) //object
        let arr = [1, 2, 3]
        console.log(typeof arr) //object

        //函數也屬於引用類型,不過typeof卻能準確的返回類型
        function fn() {}
        console.log(typeof fn) //function

從以上的執行結果可以看出,typeof不能夠準確分返回所有類型

instenceof

我們從instenceof的實現來了解下instenceof是幹什麼的

        // 模擬instenceof實現
        // 1、instenceof接收兩個參數
        // 2、返回true或false

        function myInstenceof(X, Y) {
            let L = X._proto_
            let R = Y.prototype
            if (L !== R) {
                return false
            }
            return true
        }

        // test
        function Fn() {

        }
        let newFn = new Fn()
        console.log(newFn)
        console.log(new Fn())


        console.log(myInstenceof(newFn, new Fn())) //true
        console.log(myInstenceof([], new Array())) //true
        console.log(myInstenceof([], new Object())) //true

以上demo我們就能看出,instenceof也不夠靠譜,模擬實現就是判斷X的原型知否在Y的原型鏈上。
數組之所以instenceof Object爲true是因爲 [].prototype->new Array->new Object->null

上邊說了typeof和instenceof其實就是想說這兩個對於深度clone的實現來說不夠嚴謹要不就是多層判斷。

Object.prototype.toString.call()

接下里我們說個靠譜的

        Object.prototype.toString.call(''); // [object String]
        Object.prototype.toString.call(1); // [object Number]
        Object.prototype.toString.call(true); // [object Boolean]
        Object.prototype.toString.call(undefined); // [object Undefined]
        Object.prototype.toString.call(null); // [object Null]
        Object.prototype.toString.call(new Function()); // [object Function]
        Object.prototype.toString.call(new Date()); // [object Date]
        Object.prototype.toString.call([]); // [object Array]
        Object.prototype.toString.call(new RegExp()); // [object RegExp]
        Object.prototype.toString.call(new Error()); // [object Error]
        Object.prototype.toString.call(document); // [object HTMLDocument]
        Object.prototype.toString.call(window); //[object Window]

靠譜!

接下來我們就用Object.prototype.toString.call()來解答一下面試題

      function clone(obj, o) {
            //Object.prototype.toString.call(obj)返回類似[Object Array] 利用slice來截取我們需要的字符串
            let type = Object.prototype.toString.call(obj).slice(8, -1)
                // 如果是Object
            if (type === 'Object') {
                o = {}
                for (let k in obj) {
                    o[k] = clone(obj[k]);
                }
                // 如果是對象
            } else if (type === 'Array') {
                o = []
                for (let i = 0; i < obj.length; i++) {
                    o.push(clone(obj[i]));
                }
            } else {
                // 非引用類型
                o = obj
            }
            return o
        }

        let obj1 = {
            a: [1, 2, 3, 4, 5, 6],
            b: {
                c: 2
            },
            d: 1,
            f: function() {
                return 1
            }
        }
        let obj2 = clone(obj1)
        obj2.f = function() {
            return 2
        }
        obj2.a = 1
        console.log(obj1)
        console.log(obj2)

測試打印結果,obj2的改變不會影響到obj1。
image.png

歡迎吐槽!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章