前言:

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

        本篇文章为您分析一下原生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. D - 淡黄的长裙 HDU - 4221(贪心)

    D - 淡黄的长裙 HDU - 4221(贪心) James is almost mad! Currently, he was assigned a lot of works to do, so ma ...

  2. XXE验证与利用流程

    特征 特征1 --- .ashx 看到url是 .ashx后缀的 特征2 --- 响应体是xml 发现有这些特征都可以用下面的流程测试 测试 在线工具: http://ceye.io/ http:// ...

  3. D3属性大全

    https://www.cnblogs.com/bester-ace/articles/10948793.html https://www.cnblogs.com/qingmingsang/artic ...

  4. 原生的js操作实现通过对URL的监控获取参数

    原生的js操作实现通过对URL的监控获取用户的操作信息 优化网站的时候,因为列表是用vue组件进行循环渲染,就出现了一个问题,单击跳转的问题,想了很多方案,使用js函数的方式面对这种情况并不乐观,想到 ...

  5. Pytest系列(9) - 参数化@pytest.mark.parametrize

    如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 pytest允许在多个级别启 ...

  6. Spring Taco Cloud——Controller的创建(含SpringMVC执行过程&SpringBoot&Spring三者解释及关联)

    在记录这次控制器编写前,对于Spring的感觉就是经常提这样代码好简洁,这样好方便,这个是用来干嘛的诸如之类的话. What is Spring ?这是我想问自己的,一直认为是简化代码利于工程的开源框 ...

  7. pythone 时间模块

    时间模块(时区) 计算方式:时间戳是一串数字,从计算机诞生的那一秒到现在过了多少秒,每过一秒+1 #时间戳#由时间戳获取格式化时间#由格式化时间获取时间戳 import time def timene ...

  8. Kubernetes 二进制部署

    目录 1.基础环境 2.部署DNS 3.准备自签证书 4.部署Docker环境 5.私有仓库Harbor部署 6.部署Master节点 6.1.部署Etcd集群 6.2.部署kube-apiserve ...

  9. 类 文件 右下角呈现 红色小圆圈,里面有一个J 标记

    intellj(idea) 项目中类 文件 右下角呈现 红色小圆圈,里面有一个J 标记,表明此为 未设置为源文件,没有编译,本来应该是属于源文件的,结果现在没有被标记为源文件,也就没法编译了.

  10. 解决xcode ***is missing from working copy

    这是由于SVN置顶文件导致的,cd 至项目根目录 命令行 输入 find . -type d -name .svn | xargs rm -rf