欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

实现一个克隆函数,可以深拷贝JS中的5种数据类型

程序员文章站 2022-06-09 19:09:49
...

要求: 封装一个克隆函数 clone ,可以对 JavaScript 5 种主要的数据类型(包括 NumberStringObjectArrayBoolean)进行值的深拷贝。(注意:null 、array 和 object 都是属于 Object 类型

    <script>

        // 封装 clone 克隆函数
        function clone(obj) {
            var o;  // 此函数的返回值存储克隆后的数
            switch (typeof obj) {   // 判断条件是 obj 的数据类型
                case 'undefined':   // undefined 类型
                    break
                case 'string':      // 字符串 类型
                    o = obj + ''
                    break
                case 'number':      // 数字 类型
                    o = obj - 0
                    break
                case 'boolean':     // 布尔 类型
                    o = obj
                    break
                case 'object':      // 对象 类型(其中包含三种数据情况)
                    if (obj === null) {     // 值为 null 的情况
                        return o = null
                    } else {
                        // 判断这个对象类型是数组还是一个对象
                        if (Object.prototype.toString.call(obj).slice(8, -1) === 'Array') {
                            o = []
                            // 使用循环嵌套递归一个个将数添加到 o 数组中
                            for (let i = 0; i < obj.length; i++) {
                                o.push(clone(obj[i]))
                            }
                        } else {
                            o = {}
                            // 使用 for...in 遍历对象嵌套递归将对象属性和值对应并赋值给 o 对象
                            for (const k in obj) {
                                o[k] = clone(obj[k])
                            }
                        }
                    }
                    break
                // 若类型不属于上述所有情况则直接为 o 赋值
                default:
                    o = obj
                    break

            }
            // 将 o 作为返回值 return 给调用者
            return o;
        }
        // var a = []  // [object Array]
        // let str = Object.prototype.toString.call(a)
        // console.log(str.slice(8, -1));  // Array

        var obj = { id: 1, name: 'zs', age: 13 }

        console.log('该数的原始类型是:' + typeof obj);  // 该数的原始类型是:object
        var str = clone(obj);     // 调用克隆函数将返回值赋值给 str
        obj.name = 'li'     // 这里修改了 obj 中的属性值不会影响 str 所以是深拷贝
        console.log('obj = ', obj);  // obj =  {id: 1, name: 'li', age: 13}
        console.log('str = ', str);  // str =  {id: 1, name: 'zs', age: 13}

    </script>

解析:在判断对象是属于 Array 还是 Object 时我们可以直接使用 Object.prototype.toString 方法,但是我们还需要使用 call() 方法来改变 this 指向到我们的对象上,比如:

var a = []
var b = {}
console.log(Object.prototype.toString.call(a)); // [object Array]
console.log(Object.prototype.toString.call(b)); // [object Object]

然后我们再使用 slice(start , stop) 方法来截取字符串,该方法用于通过开始点和结束点来限制组合中元素的选择:start 参数是创建子集的开始索引(从 0 开始),stop 参数是一个可选的结束点(截取到的内部不包含 stop 所在的点)。

var a = []
console.log(Object.prototype.toString.call(a).slice(8, -1)); // Array

如此,我们最后根据一个对象的 Object.prototype.toString.call(obj).slice(8, -1) 等于 Array 还是 Object 即可判断出该对象是数组类型还是对象类型