zoukankan      html  css  js  c++  java
  • 探寻Object.assign内部的奥秘

     有写过js插件的童鞋会知道我们在调用一些别人写好的插件时候,我们传入的参数调用的时候,其实在插件内部也会定义默认的参数,下面那我写过的一个移动端轮播插件为例子说明:

       new mslider({
            slideCell:".wrap",
            titCell:".hd ul",
            mainCell:".box",
            interTime:3000,
            autoPlay:false, //自动播放
            autoPage:true,//自动分页
        });
    

      这是我们在外部调用的参数,已经存在的属性会替换掉我们插件内部的属性,当我们什么都不传入的情况下,就会走默认参数。下面贴出之前写好的插件部分代码,方便大家理解。

     var mslider=function(option){
            //设置默认参数
            this.defaultopt={
                slideCell:".wrap",
                mainCell:".box",
                interTime:1000,
                autoPlay:false//自动播放
            }
            //判断传入的opts是否有默认参数中的值,如果默认参数值不存在opts中
            //就把默认参数加进opts中,这样就不会把默认参数修改了
            option=option||this.defaultopt;
            for(var k in this.defaultopt){
                if(!option[k]){
                    option[k]=this.defaultopt[k];
                }
            }
            this.option=option;
        }
    

     其实这就是实现传入的对象和定义的默认参数对象的一个合并操作,如果不传入这个参数,就会把默认的参数追加上去,当然你如果使用jquery开发插件的话,可以使用jquery提供的静态方法$.extend;不过我要说的是es6提供的一个新方法Object.assigin.

        var a={a:1,b:1};
        var b={c:1,d:1};
        var newObj=Object.assign({},a,b);
        console.log(newObj)//{a: 1, b: 1, c: 1, d: 1}
    

     传入的第一个参数为目标对象,将后面所有传入的对象的可枚举属性复制到目标对象上面,需要注意的是后面如果有同名属性的话,会直接覆盖掉之前的属性。

        var a={a:1,b:1};
        var newObj=Object.assign(a);
        console.log(newObj==a)  //true
    

      如果只传入一个目标对象的话,直接返回自己。需要注意的是目标函数不能是null或者undefined,否则会报错

        

    var a={a:1,b:1};
    var newObj=Object.assign(a,123);
    console.log(newObj) //{a: 1, b: 1}
    

      如果第二个参数传入的是数字的情况下,则忽略,直接返回自目标对象。

    var a={a:1,b:1};
    var newObj=Object.assign(a,"123");
    console.log(newObj) //{0: "1", 1: "2", 2: "3", a: 1, b: 1}
    

       如果传入的是字符串,则以关联数组的形式追加到目标对象上,同理如果是布尔值的话一样忽略掉。

           下面我们就可以自己用原生js模拟assign的功能。   

     Object.customeAssign = function (target, ...arg) {
                    if (target == null || target == undefined) {
                        throw new TypeError("Cannot convert undefined or null to object")
                    }
                    var target = Object(target);
                    for (var i = 0; i < arg.length; i++) {
                        var source = arg[i];
                        if (source != null) {
                            for (var key in source) {
                                if(Object.prototype.hasOwnProperty.call(source,key)){
                                    target[key]=source[key];
                                }
                            }
                        }
                    }
                    return target;
    }
    

      主要的难点在于遍历对象是时候需要判断下是否为对象的属性,因为遍历对象使用for in并不是准确的,他会把原型上的属性也会遍历出来。

     var obj={a:"123"};
     Object.prototype.name="xiaoming";
     for(var key in obj){
        console.log(key) //输出a,name
     }
    

        但细细钻研发现原生assign的方法是不可枚举的,我们直接写在Object构造函数上似乎不太严谨,这样这个方法就可以直接遍历出来,这个时候哦就用到我们的defineProproty属性了。

    Object.defineProperty(Object, "customeassgin", {
                    value: function (target, ...arg) {
                        if (target == null || target == undefined) {
                            throw new TypeError("Cannot convert undefined or null to object")
                        }
                        var target = Object(target);
                        for (var i = 0; i < arg.length; i++) {
                            var source = arg[i];
                            if (source != null) {
                                for (var key in source) {
                                    if (Object.prototype.hasOwnProperty.call(source, key)) {
                                        target[key] = source[key];
                                    }
                                }
                            }
                        }
                        return target;
                    },
                    writable:true,
                    configurable:true
    })

    通过源码分析我们就很容易看出Object.assign实现的是浅拷贝,他直接改变了目标对象的值。

  • 相关阅读:
    Nim教程【八】(博客园撰写工具客户端更新)
    图解 MongoDB 地理位置索引的实现原理(转)
    MongoDB学习笔记(索引)(转)
    Hadoop集群WordCount运行详解(转)
    java操作mongodb(连接池)(转)
    面向对象设计七大原则(转)
    Spring中IOC和AOP的详细解释(转)
    java单例模式使用及注意事项
    java.io包的总体框架图(转)
    Java常见异常(Runtime Exception )小结(转)
  • 原文地址:https://www.cnblogs.com/shentao11023/p/11045021.html
Copyright © 2011-2022 走看看