腱鞘炎犯了。第三天就沒堅持住,罪過罪過。javascript
concat源碼連接java
建立一個用任何數組 或 值鏈接的新數組。git
* var array = [1]; * var other = _.concat(array, 2, [3], [[4]]); * * console.log(other); * // => [1, 2, 3, [4]] * * console.log(array); * // => [1]
注意,會返回一個新數組,而且不改變傳入的數組。github
源碼裏有100多行,顯着有點亂,可是讀下來,仍是有不少值得思考的地方。chrome
var MAX_SAFE_INTEGER = 9007199254740991;
express
JS中Number
類型的最大值,2的32次冪指-1npm
/** `Object#toString` result references. */ var argsTag = '[object Arguments]', funcTag = '[object Function]', genTag = '[object GeneratorFunction]';
在js中判斷類型咱們能夠借用Object.prototype.toString
方法來判斷類型。 下邊是demo數組
var toString =Object.prototype.toString var a = function(){console.log(toString.call(arguments))} // [object Arguments]
link閉包
var root = freeGlobal || freeSelf || Function('return this')();
這裏我比較注意的Function('return this')()
,我在chrome裏執行這段代碼,返回的是全局對象。函數
經過google查到了緣由。
Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called. This is different from using eval with code for a function expression.
使用Function構造函數建立的函數不會建立對其建立上下文的閉包;他們老是在全局建立。執行時,它們只能訪問它們本身的局部變量和全局變量,而不能訪問函數構造函數調用的範圍。這與使用eval解析函數表達式的代碼不一樣。
arrayPush
是concat
中用到的工具方法。他接收兩個數組,返回一個新的數組。
function arrayPush(array, values) { var index = -1, length = values.length, //傳入的數組長度 offset = array.length; //偏離值,values併入array,固然要從array的最後一位往裏傳。 while (++index < length) { // loop 操做。 array[offset + index] = values[index]; } return array; } arrayPush([1,2,3],[4,5,6]) //[1, 2, 3, 4, 5, 6]
var objectProto = Object.prototype; //保留Object.prototype的引用。 var hasOwnProperty = objectProto.hasOwnProperty; // 這個方法判斷是不是該對象上的自建屬性,而不是prototype上的。 var objectToString = objectProto.toString; //保留引用。加快訪問該方法的速度
/** * The base implementation of `_.flatten` with support for restricting flattening. * _.flatten的基本實現方法 * @private * @param {Array} array The array to flatten. // 須要被打平的數組。 * @param {number} depth The maximum recursion depth. // 最大的遞歸深度。 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. * @param {Array} [result=[]] The initial result value.// 指望放到指定的數組裏,不傳默認爲一個空數組。 * @returns {Array} Returns the new flattened array.//返回一個新的被扁平化的數組 */ // 傳入的方式 baseFlatten([[1,2,3,4,],1],1,false) => function baseFlatten(array, depth, predicate, isStrict, result) { var index = -1, //初使下標 length = array.length;//須要被扁平的長度 => 2 predicate || (predicate = isFlattenable);// 這裏貌似只能傳false,或者一個方法 => isFlattenable result || (result = []); // result => [] while (++index < length) { var value = array[index]; // 0: [1,2,3,4] depth:1 1: 1, 從1的位置就走到else if裏了。 if (depth > 0 && predicate(value)) {//predicate(value) 返回true or false,默認狀況下是用來判斷value是不是可被打平的。 depath 若是是2的話,就會將更高階的數組打平,而後遞歸調用而傳入result。 if (depth > 1) { // Recursively flatten arrays (susceptible to call stack limits). baseFlatten(value, depth - 1, predicate, isStrict, result); } else { arrayPush(result, value); //arrayPush([],[1,2,3,4]) => result=[1,2,3,4] } } else if (!isStrict) { result[result.length] = value; } } return result; } /** * Checks if `value` is a flattenable `arguments` object or array. * 返回傳入的value 是不是一個能夠被打平的 arguments 對象或者數組 * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. */ function isFlattenable(value) { return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]); }
正主concat來了
//concat([1,2,3,4],[5,6,7,8]) function concat() { var length = arguments.length, // 2 args = Array(length ? length - 1 : 0),//arg = [empty] array = arguments[0],// [1,2,3,4] index = length;//2 while (index--) { // 1 args[index - 1] = arguments[index]; } // args[0]= [1,2,3,4] args[-1]=[5,6,7,8] return length ? arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)) : []; } //isArray(array) ? copyArray(array) : [array] => [1,2,3,4] //baseFlatten(args, 1) => [5,6,7,8] // return這裏就成了 arrayPush([1,2,3,4],[5,6,7,8]) => [1,2,3,4,5,6,7,8] /** * Copies the values of `source` to `array`. * * @private * @param {Array} source The array to copy values from. * @param {Array} [array=[]] The array to copy values to. * @returns {Array} Returns `array`. */ function copyArray(source, array) { var index = -1, length = source.length; array || (array = Array(length)); // array 不存在就建立一個和source長度同樣的數組 while (++index < length) { array[index] = source[index]; // 賦值進去,返回copy的數組,不改變原有的數組 } return array; }