前言:

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

        本篇文章为您分析一下原生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. Aircoinst 三层架构ASP.NET开源

    <注意! 本源码为我本人所写,可能有点烂.仅供学习使用,请勿进行商业用途~!> <本源码永久归于MineLSG 及 Aircoinst_慈 所拥有> 使用方法:直接拷贝 一.结 ...

  2. STM32F103ZET6外部中断

    1.EXTI功能 外部中断/事件控制器EXTI管理了STM32的20个中断/事件线. EXTI的功能框图如下: 在功能框图中,可以看到很多在信号线上打了一个斜杠并标注“20”的字样,这是表示在STM3 ...

  3. windows的注册表有什么用?

    注册表是什么 注册表是Microsoft Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息.早在Windows 3.0推出OLE技术的时候,注册表就已经出现.随后推出的Window ...

  4. PyJWT 详解

    1.首先,我们需要先了解 JWT 的概念,所以我们先看pyjwt的官网 https://jwt.io/ 2.对于官方 JWT 有两篇博文写的不错分别如下: https://blog.csdn.net/ ...

  5. matplotlib TransformWrapper

    2020-04-09 23:26:53 --Edit by yangray TransformWrapper 是Transform的子类, 支持在运行中替掉一个变换(可以是不同类型, 但维度必须相同) ...

  6. matplotlib中的基本概念

    有外语基础的朋友看这里: matplotlib官方文档 Figure(图像): 组成部分

  7. HTTP 405 的错误提示:消息 JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS 的解决方法

    如果项目是运行在 Tomcat 8 及以上,会发现发出的 PUT 请求和 DELETE 请求可以被控制其接收到,但是返回页面时(forward)会报HTTP 405 的错误提示:"消息 JS ...

  8. 【翻译】Java Array的排名前十方法(Top 10 Methods for Java Arrays)

    这里列举了Java Array 的前十的方法.他们在stackoverflow最大投票的问题. The following are top 10 methods for Java Array. The ...

  9. JVM 调优之 Eclipse 启动调优实战

    本文是我12年在学习<深入理解Java虚拟机:JVM高级特性与最佳实践>时,做的一个 JVM 简单调优实战笔记,版本都有些过时,不过调优思路和过程还是可以分享给大家参考的. 环境基础配置 ...

  10. GNU的make命令、makefile编写

    makefile简介 makefile可实现工程的自动化编译,只需一个make命令即可一键完成.makefile定义了一些规则,指定哪些文件需要先编译.后编译.重新编译等. 一般的C或者C++程序,都 ...