每天一题,mixin

603 阅读2分钟

每天一题,坚持思考

题目

实现mixin函数,该方法类似于Object.assign,递归合并其他来源对象自身和继承的可枚举属性到 target 目标对象。

var a = {a: 1};
mixin(a, {b: 2}, {c: 3});
console.log(a); // {a: 1, b: 2, c: 3}

具体实现

// 判断是否为对象类型
function isObj(value) {
  return value != null && (typeof value === 'object' || typeof value === 'function');
}

// 遍历obj上的每一个属性,调用copy方法,绑定this的指向
function forIn(obj, fn, thisArg) {
  for (var key in obj) {
    if (fn.call(thisArg, obj[key], key, obj) === false) {
      break;
    }
  }
}

// 判断属性值非'__proto__'、'constructor'、'prototype'
function isValidKey(key) {
  return key !== '__proto__' && key !== 'constructor' && key !== 'prototype';
};

// 拷贝对象
function copy(val, key) {
  if (!isValidKey(key)) {
    return;
  }

  var obj = this[key];
  if (isObj(val) && isObj(obj)) {
    mixin(obj, val);
  } else {
    this[key] = val;
  }
}

// 合并多个对象,改变target的值
function mixin(target) {
  var length = arguments.length,
      index = 0;
  while (++index < length) {
    var obj = arguments[index];
    if (isObj(obj)) {
      forIn(obj, copy, target);
    }
  }
  return target;
}

实现思路

参数:

  1. target(Object):需要合并的对象;

步骤:

  1. 使用while遍历arguments的成员,开始位置是1;如果是当前遍历的值类型是对象,则调用forIn方法,否则就跳过。
  2. 调用forIn方法的时候,会把当前对象进行遍历去调用copy复制方法
  3. copy方法中判断对应的属性值,如果不是'__proto__'、'constructor'、'prototype'这三个中的其中一种,则返回true,否则返回false。如果当前需要拷贝的值是对象,那么会递归调用mixin方法,这里的this指向其实就是mixin的需要合并的那个对象,最后执行完mixin方法后会把一开始的target值给改变。

如果读者发现有不妥或者可以改善的地方,欢迎在评论区指出。如果觉得写得不错或者对你有所帮助,可以点赞、评论、转发分享,谢谢~