原本是写_.clone这个系列,没想到碰到了assign。想了想,仍是得扒皮这个方法。就特地从新开一章。写这个方法。javascript
/** * The base implementation of `_.assign` without support for multiple sources * or `customizer` functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @returns {Object} Returns `object`. */ function baseAssign(object, source) { return object && copyObject(source, keys(source), object);
baseAssign是_.assign
的基础实现。对lodash来讲,它是一个private方法。priviate是私有方法,只在lodash这个库内部调用。对应的是public方法 ,_.assign
就是对外暴露使用的public方法。java
换言之,_.assign
是在baseAssign这个方法上进一步封装实现。git
在baseAssign中,使用到了copyObjectgithub
--
源码copy多了,看着有点乱,让我胡乱分析一下。数组
baseAssign中是copyObject(source, keys(source), object)
使用的copyObject
的,显然source
是一个期待被覆盖的对象,咱们知道,咱们使用_.assign
的时候,若是source
上的属性存在而且object
上的同名属性不存在,source的属性会保持不变,object
上若是存在同名属性,那么object
上同名属性的value会覆盖到source
的同名属性上,代替原有的值。ide
咱们继续看一下lodash的做者是如何实现这个功能的。ui
/** * Copies properties of `source` to `object`. * 复制属性,从soure复制属性到object * @private * @param {Object} source The object to copy properties from. 源对象 * @param {Array} props The property identifiers to copy. 被copy的 对象属性标识符,是个数组 * @param {Object} [object={}] The object to copy properties to. 目标对象 * @param {Function} [customizer] The function to customize copied values. * @returns {Object} Returns `object`.返回目标对象 */ function copyObject(source, props, object, customizer) { // props显然是source上已有属性的数组。 var isNew = !object;// 若是object是一个对象,那么isNew为false object || (object = {}); // object不存在,默认一个空对象 var index = -1, length = props.length;// 属性数组的长度 while (++index < length) { var key = props[index];// var newValue = undefined; if (newValue === undefined) { newValue = source[key]; // 没有customizer的状况下,newValue为undefined,到这一步,变成了source上key属性的值。 } // baseAssignValue和assignValue都是将newValue合并到object的key上。简单粗暴点就是object[key] = newValue的功能,那是否会是屡次一举呢,咱们还要往下看代码。 if (isNew) { baseAssignValue(object, key, newValue); } else { assignValue(object, key, newValue);// } } return object; }
--es5
baseAssing
源码以下翻译
/** * The base implementation of `assignValue` and `assignMergeValue` without * `assignValue` and `assignMergeValue`的基础实现 * value checks. * * @private * @param {Object} object The object to modify. * 被修改的对象 * @param {string} key The key of the property to assign. * 被合并的属性名 * @param {*} value The value to assign. * 被合并的值 */ function baseAssignValue(object, key, value) { if (key == '__proto__' && defineProperty) { // es5的defineProperty,这里不展开介绍, defineProperty(object, key, { 'configurable': true,//可配置 'enumerable': true,// 可遍历 'value': value, // 值 'writable': true // 可写 }); } else { object[key] = value; // 不解释 } }
简单粗暴点的话,这个方法的做用就是object[key] = value;
code
咱们在看
/** * Assigns `value` to `key` of `object` if the existing value is not equivalent。 * 若是现有值不相等,则将`value`分配给`object`的`key` * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @private * @param {Object} object The object to modify. * 被修改的对象 * @param {string} key The key of the property to assign. * @param {*} value The value to assign. */ function assignValue(object, key, value) { var objValue = object[key]; // 当前的key上的value // object自身没有key这个属性 好比object={c:[1,2,3,4]},key='c', if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || (value === undefined && !(key in object))) { baseAssignValue(object, key, value); } }
这个if条件怎么看怎么纠结。他分为两个条件
eq: 执行 SameValueZero 比较二者的值,来肯定它们是否相等。
/** * _.eq(object, object); * // => true * * _.eq(object, other); * // => false * * _.eq('a', 'a'); * // => true * * _.eq('a', Object('a')); * // => false * * _.eq(NaN, NaN); */ function eq(value, other) { return value === other || (value !== value && other !== other); }
The internal comparison abstract operation SameValueZero(x, y), where x and y are ECMAScript language values, produces true or false. Such a comparison is performed as follows:
这里也不知道怎么翻译,大概意思就是,ECMAScript国际上的抽象比较操做规则,返回true或者false,遵循以下的规则。
1.If Type(x) is different from Type(y), return false.
2.若是x,y类型不一样,直接返回false
If Type(x) is Number, then 若是x是number类型,那么以下 If x is NaN and y is NaN, return true. x,y是NaN,返回true,*这里与咱们知道的NaN!==NaN有区别* If x is +0 and y is -0, return true. 不解释 If x is -0 and y is +0, return true. 不解释 If x is the same Number value as y, return true. 不解释 Return false.
3.Return SameValueNonNumber(x, y).
If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.
If x and y are both true or both false, return true; otherwise, return false.
If x and y are both the same Symbol value, return true; otherwise, return false.