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