前言:

        本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽。

        本篇文章为您分析一下原生JS写淘宝无缝轮播图效果

对象混合

页面中如下需求

var obj1 = {
    x: 1,
    y: "a"
}

var obj2 = {
    x: "b",
    o: 6
}

页面上有两个对象
我们要把这两个对象混合成一个
形成如下结构:

// 将obj2混合到obj1中
obj = {
    x: "b",
    y: "a",
    o: 6
    }

参考代码:

    /**
     *  ES5之前的版本
     * 对象的混合
     * @param {Object} obj1
     * @param {Object} obj2
     */
    function mixin(obj1, obj2){
        // 第一步: 创建一个对象
        var newObj = {};
        // 第二步: 循环obj2中的对象
        for(var prop in obj2){
            // 第三步: 将obj2中的属性添加到新创建爱对象中
            newObj[prop] = obj2[prop];
        }
        // 第四步: 循环obj1中的对象
        for(var prop in obj1){
            // 第五步: 看看obj1中的属性在不在obj2中,如果不在就将他加入的新的对象中
            if(!(prop in obj2)){
                newObj[prop] = obj1[prop];
            }
        }
        // 最后返回这个新的对象
        return newObj;
    }

    /**
     * ES6版本
     * 对象的混合
     * @param {Object} obj1
     * @param {Object} obj2
     */
    // function mixin(obj1, obj2){
    //     return Object.assgin({},obj1,obj2);
    // }

在页面中调用

        var obj = mixin(obj1, obj2);
        console.log(obj);

  

对象克隆

页面中如下需求

        var obj = {
            x: "123",
            y: 456,
            objSon: {
                c: "a"
            }
        }

        var newObj = clone(obj);
        //  要求实现newObj中有obj的所有属性
        //  并且newObj.objSon !== obj.objSon;

下面来看看代码

        function clone(obj) {
            var newObj = {};
            for (var prop in obj) {
                newObj[prop] = obj[prop];
            }
        }

下面来看看效果

如果obj是一个数字会怎么样呢?
var obj = 123;

为什么会是一个对象呢?
因为我们在function中创建了一个对象
如果obj是一个字符串呢?
var obj = "abcdefg";

如果obj是一个数组又会怎么样呢?
var obj = [12,35,65,87,1,3];

他克隆出来就是一个伪数组了
并且length属性还得不到

图片

鉴于上面出现的多种情况
我们刚刚写的代码(只是假设他是普通对象,还不是数组对象,数组本身也是对象嘛)就不足以完成一个完整的克隆函数
因此,我们要进行判断

        function clone(obj) {
            if (Array.isArray(obj)) {  // 如果他是一个数组
                return obj.slice();    // 复制数组
            } else if (typeof obj === "object") {  // 如果他是一个普通对象
                var newObj = {};       // 定义一个对象
                for (var prop in obj) {  // 循环obj
                    newObj[prop] = obj[prop];  // 添加属性
                }
                return newObj;         // 返回
            } else {                   // 函数、原始类型
                return obj;            // 直接返回
            }
        }

在页面上打印
var newObj1 = clone(obj1);
var newObj2 = clone(obj2);
var newObj3 = clone(obj3);
var newObj4 = clone(obj4);

现在来看这个克隆更加优化了
但是并没有完整
如果obj的属性也是一个对象呢?

        var obj = {
            x: "123",
            y: 456,
            subObj: {
                a: "abc"
            }
        }

newObj本身是不等于obj的,因为是克隆嘛,产生了一个新的对象
但是它里面的subObj属性的地址是一样的
如果我们给newObj.subObj.a ==="XXX";赋值了。
他会导致:obj.subObj.a也跟着改变。
所以我们把目前我们写的这种方式叫做 [浅度克隆]
还有一种克隆叫 [深度克隆] 就是要对他属性做深度处理
因此这个函数还需要一个参数来判断他是否需要深度克隆

        function clone(obj, deep) {
            if (Array.isArray(obj)) {  // 如果他是一个数组
                return obj.slice();    // 复制数组
            } else if (typeof obj === "object") {  // 如果他是一个普通对象
                var newObj = {};       // 定义一个对象
                for (var prop in obj) {  // 循环obj
                    if (deep){
                        // 如果是深度克隆的话,我们把这个属性的值再克隆一遍【递归】
                        newObj[prop] = this.clone(obj[prop], deep);
                    }else {
                        newObj[prop] = obj[prop];  // 添加属性
                    }
                }
                return newObj;         // 返回
            } else {                   // 函数、原始类型
                return obj;            // 直接返回 【递归的终止条件】
            }
        }

        // 再传入第二个参数
        var newObj = clone(obj, true);

针对数组如何深度克隆

        function clone(obj, deep) {
            if (Array.isArray(obj)) {  // 如果他是一个数组
            if(deep){  // 深度克隆
                var newArr = [];  //定义一个空数组
                for(var i = 0; i< obj.length; i++){ // 循环obj的每一项
                    newArr[i].push(clone(obj[i],deep)); // pun数组
                }
            }else {
                return obj.slice();    // 复制数组
            }

            } else if (typeof obj === "object") {  // 如果他是一个普通对象
                var newObj = {};       // 定义一个对象
                for (var prop in obj) {  // 循环obj
                    if (deep){
                        // 如果是深度克隆的话,我们把这个属性的值再克隆一遍【递归】
                        newObj[prop] = this.clone(obj[prop], deep);
                    }else {
                        newObj[prop] = obj[prop];  // 添加属性
                    }
                }
                return newObj;         // 返回
            } else {                   // 函数、原始类型
                return obj;            // 直接返回 【递归的终止条件】
            }
        }

这样就完成了对象的克隆

完整插件代码

对象混合


this.myPlugin.mixin = function (obj1, obj2) {

    return Object.assign({}, obj1, obj2);
    // // 建立一个新对象
    // var newObj = {};
    // // 进行 for in 循环
    // for (var prop in obj2) {
    //     newObj[prop] = obj2[prop];
    // }
    // // 找到obj1中有但是obj2中没有的属性
    // for (var prop in obj1) {
    //     if (!(prop in obj2)) {
    //         newObj[prop] = obj1[prop]
    //     }
    // }
    // return newObj;
}

对象克隆

/**
 * 克隆一个对象
 * @param {Array} obj  对象
 * @param {boolean} deep 是否深度克隆
 */
this.myPlugin.clone = function (obj, deep) {
    if (Array.isArray(obj)) {
        if (deep) {  //深度克隆
            var newArr = [];
            for (var i = 0; i < obj.length; i++) {
                newArr.push(this.clone(obj[i], deep));
            }
            return newArr;
        }
        else {      // 浅度克隆
            return obj.slice(); //复制数组
        }
    }
    else if (typeof obj === "object") {
        var newObj = {};
        for (var prop in obj) {
            if (deep) {
                //深度克隆
                newObj[prop] = this.clone(obj[prop], deep);
            }
            else {
                // 浅度克隆
                newObj[prop] = obj[prop];
            }
        }
        return newObj;
    }
    else {
        //函数、原始类型
        return obj; //递归的终止条件
    }
}

<!--插件要考虑通用性,易用性,尽量不要与其他功能冲突,防止污染太多的window上的全局变量,因此我这里使用多个js文件只污染一个全局变量的方式!在helpers.js中添加如下代码
if (!this.myPlugin) {
    this.myPlugin = {};
}
-->

<script src="../../plugin/helpers.js"></script>  <!--引入插件-->
<script>
            var opt = myPlugin.mixin(defaultOptions, option)
            console.log(opt);
</script>

结语

整完!!!

js 实现对象的混合与克隆效果,带完整版解析代码[helpers.js]的更多相关文章

  1. js 实现图片瀑布流效果,可更改配置参数 带完整版解析代码[waterFall.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS实现图片瀑布流效果 页面需求 1 ...

  2. js 实现淘宝放大镜功能,可更改配置参数 带完整版解析代码[magnifier.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写淘宝放大镜效果 基本功能: 运 ...

  3. js 实现淘宝无缝轮播图效果,可更改配置参数 带完整版解析代码[slider.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写淘宝无缝轮播图效果 需求分析: ...

  4. js 函数的防抖(debounce)与节流(throttle) 带 插件完整解析版 [helpers.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         函数防抖与节流是做什么的?下面进行通俗的讲解. 本文借鉴:h ...

  5. js 实现文字滚动功能,可更改配置参数 带完整版解析代码。

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写文字滚动效果 需求分析: 需要 ...

  6. js 函数对象的继承 inherit 带 插件完整解析版[helpers.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS的对象继承方法 需求分析: 1. ...

  7. 《JS高程》创建对象的7种方式(完整版)

    一.理解对象 ECMA-262定义对象:无序属性的集合,其属性可以包含基本值.对象或者属性. 我们可以把 ECMAScript 的对象想象成 散列表:无非就是一组 名值对,其中值可以是数据或函数. 创 ...

  8. js串口通信 调用MSCOMM32控件 链接电子秤(完整版实现方案)

    硬件环境:RS232转USB串口线*1 电子秤*1(本人采用G&G E600Y-C型号称重仪) 电子秤原装RS232数据线*1 计算机*1 软件环境:RS232转USB串口线驱动(这个可以在串 ...

  9. Google Analytics统计代码GA.JS中文教程

    2010-12-06 11:07:08|  分类: java编程 |  标签:google  analytics  ga  js  代码  |举报|字号 订阅     Google Analytics ...

随机推荐

  1. E 比赛评分

    时间限制 : - MS   空间限制 : - KB  评测说明 : 1s,128m 问题描述 Lj​最近参加一个选秀比赛,有N个评委参加了这次评分,N是奇数.评委编号为1到N.每位评委给Lj​的分数是 ...

  2. C/C++知识总结 四 循环与分支语句

    C/C++循环与分支语句 循环与分支语句的意义 关系运算符.逻辑运算符 for循环和嵌套for循环(基于范围for循环) while循环与do while循环 分支if语句.if else语句.if ...

  3. 3-1. 基于epoll架构的视频采集端设计

    精通epoll架构 epoll:Linux中最优秀的多路复用机制! 与select .poll区别 1.select和poll没有太大区别,除了select有文件描述符限制(1024个).select ...

  4. 监听窗口大小变化,改变画面大小-[Three.js]-[onResize]

    如果没有监听窗口变化,将会出现一下情况: ![](https://img2018.cnblogs.com/blog/1735896/202001/1735896-20200102081845027-2 ...

  5. 从谷歌面试翻车到offer收割的心路历程

    首先声明,这只是我的播客随感,其中无法避免有一些个人色彩的见解,请不要在意,我尊敬任何的互联网公司,尊敬研究生期间的老师同学,我只希望给在求学路上的CS同学一些启发. 先介绍一下背景,我是ACM铜牌退 ...

  6. Java序列化机制中的类版本问题 serialVersionUID的静态字段 含义

    Java序列化机制中的类版本问题 分类: [Java 基础]2014-10-31 21:13 480人阅读 评论(0) 收藏 举报   目录(?)[+]       原文地址:http://yanwu ...

  7. 07-rem

    一.什么是rem rem(font size of the root element)是指相对于根元素`的字体大小的单位.它就是一个相对单位. px:一个绝对单位 em:一个相对单位,根据的是当前盒子 ...

  8. GeoGebra的一些指令名字

    列举出老师上课提出的一些命令 比较不常见的命令 1.取得函数上一点的坐标值x(A).y(A).z(A) 2.复数指令real() imaginary() 复数中的虚数应该使用Alt+i打出 点的表示指 ...

  9. Extjs简单的form+grid组合

    采用的是Extjs4.2版本 http://localhost:49999/GridPanel/Index 该链接是本地连接,只是方便自己访问,读者无法正常访问. <script src=&qu ...

  10. DES原理及代码实现

    一.DES基础知识DES技术特点 DES是一种用56位密钥来加密64位数据的方法    DES采取了分组加密算法:明文和密文为64位分组长度    DES采取了对称算法:加密和解密除密钥编排不同外,使 ...