有写过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实现的是浅拷贝,他直接改变了目标对象的值。