原本是寫_.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.