前言:

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

        本篇文章为您分析一下原生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. 从上帝视角看Java如何运行

    JVM内存结构 可以看出JVM从宏观上可以分为 ‘内部’  及 ‘外部’  两个部分(便于记忆理解): ‘内部’包含:线程共享(公有)数据区 和 线程隔离(私有)数据区 ‘外部’包含:类加载子系统.垃 ...

  2. xmind转为markdown

    先将xmind导出为.opml 将opml导入Typora (需要安装pandoc)

  3. Appium自动化(1) - 环境准备详细教程

    Appium需要用到的工具 链接:https://pan.baidu.com/s/1od9x-1l0ALGRT5T6QFDHWg 提取码:bnhq 安装Appium Pyhton client包 1. ...

  4. 1089 Insert or Merge (25分)

    According to Wikipedia: Insertion sort iterates, consuming one input element each repetition, and gr ...

  5. 关于AUI框架自学心得

    2018年8月25日今天星期六,这段时间接触到移动端布局框架AUI,借着早上一个小时时间大致看了一下开发文档(后面统称文档),对AUI一点认识. 目前2.0版本为最新版,这个版本和1.0比较升级很多. ...

  6. hive常用函数五

    复合类型构建操作 1. Map类型构建: map 语法: map (key1, value1, key2, value2, …) 说明:根据输入的key和value对构建map类型 举例: hive& ...

  7. hive常用函数三

    日期函数 1. UNIX时间戳转日期函数: from_unixtime 语法: from_unixtime(bigint unixtime[, string format]) 返回值: string ...

  8. go中的error小结

    go中的error error和panic error接口 go中err的困局 推荐方法 总结 参考 go中的error go中的错误处理,是通过返回值的形式来出来,要么你忽略,要么你处理(处理也可以 ...

  9. redis中的分布式锁

    分布式锁的实现场景 在平时的开发中,对于高并发的开发场景,我们不可避免要加锁进行处理,当然redis中也是不可避免的,下面是我总结出来的几种锁的场景 Redis分布式锁方案一 使用Redis实现分布式 ...

  10. spring 中 hibernate 的 2种 配置方式(新旧 2种方式)

    Spring对hibernate配置文件hibernate.cfg.xml的集成,来取代hibernate.cfg.xml的配置 Spring对hibernate配置文件hibernate.cfg.x ...