lodash的工具方法(三)
_.toArray(value)
将value转换成一个数组。
/**
* @example
*
* _.toArray({ 'a': 1, 'b': 2 });
* // => [1, 2]
*
* _.toArray('abc');
* // => ['a', 'b', 'c']
*
* _.toArray(1);
* // => []
*
* _.toArray(null);
* // => []
*/
function toArray(value) {
if (!value) {
return [];
}
if (isArrayLike(value)) {
return isString(value) ? stringToArray(value) : copyArray(value);
}
if (iteratorSymbol && value[iteratorSymbol]) {
return iteratorToArray(value[iteratorSymbol]());
}
var tag = getTag(value),
func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
return func(value);
}
1.isArrayLike
,字符串也是可以通过这个判断的。所以内部又判断是否是字符串。
2。字符串的话,调用stringToArray
。字符串中有区分了Unicode
从而调用不同不同的方法来换成数组。
function stringToArray(string) {
return hasUnicode(string)
? unicodeToArray(string)
: asciiToArray(string);
}
3.数组的话,调用copyArray
,一目了然。遍历source,将source中的元素copy到array中并返回
function copyArray(source, array) {
var index = -1,
length = source.length;
array || (array = Array(length));
while (++index < length) {
array[index] = source[index];
}
return array;
}
4.到了iteratorSymbol&& value[iteratorSymbol]
在这里,我们先补充一点Symbol.iterator的知识
Symbol.iterator 为每一个对象定义了默认的迭代器。该迭代器可以被 for...of 循环使用。Array,TypedArray,String,Map,Set具有默认的迭代器行为。
//默认的迭代器行为 var myIterable = {}
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
了解了上边的相关知识,iteratorToArray
就很容易理解了。
/**
* terator.next() 返回的是一个对象{value: xxx,done:false | true}
* 如果done为true证明已经结束
*/
function iteratorToArray(iterator) {
var data,
result = [];
while (!(data = iterator.next()).done) {
result.push(data.value);
}
return result;
}
5.其它的逻辑
var tag = getTag(value),
func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
return func(value);
/**
* Converts `set` to an array of its values.
* 将set转换成values数组。
* @private
* @param {Object} set The set to convert.
* @returns {Array} Returns the values.
*/
function setToArray(set) {
var index = -1,
result = Array(set.size); // 获取set的长度
set.forEach(function(value) {
result[++index] = value; // 长度push到result的数组里
});
return result;
}
function values(object) {
// keys方法,获取可列举的属性(非prototype)
return object ? baseValues(object, keys(object)) : [];
}
// 获取object对应key上的值,,并返回
function baseValues(object, props) {
return arrayMap(props, function(key) {
return object[key];
});
}
_.toPlainObject
转换 value 为普通对象。 包括继承的可枚举属性。
/**
* @returns {Object} Returns the converted plain object.
* @example
*
* function Foo() {
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.assign({ 'a': 1 }, new Foo);
* // => { 'a': 1, 'b': 2 }
*
* _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
* // => { 'a': 1, 'b': 2, 'c': 3 }
*/
function toPlainObject(value) {
return copyObject(value, keysIn(value));
}
copyObject
我们在baseAssign中有过描述。它将value的keys,copy到第三个参数object上。(object不在就会返回一个新的对象)
keysIn
/**
* Creates an array of the own and inherited enumerable property names of `object`.
* 创建一个数组成员为自身的属性,或者继承的可枚举的属性。
* **Note:** Non-object values are coerced to objects. 非对象会被强制转换为对象
*
* @static
* @memberOf _
* @since 3.0.0
* @category Object
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names.
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.keysIn(new Foo);
* // => ['a', 'b', 'c'] (iteration order is not guaranteed)
*/
function keysIn(object) {
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);// 类数组和不同的走两种。
}
lodash对于arraylike
,首先不是数组,并且value。length
大于等于0,小于 Number.MAX_SAFE_INTEGER
.
如果是类数组,会调用arrayLikeKeys(object, true)
返回keys。非类数组调用baseKeysIn
arrayLikeKeys
/**
* Creates an array of the enumerable property names of the array-like `value`.
* 创建并返回一个数组。成员是类数组属性名。
* @private
* @param {*} value The value to query.
* @param {boolean} inherited Specify returning inherited property names.
* @returns {Array} Returns the array of property names.
*/
function arrayLikeKeys(value, inherited) {
// Safari 8.1 makes `arguments.callee` enumerable in strict mode.
// Safari 9 makes `arguments.length` enumerable in strict mode.
/*数组等格式,通过baseTimes,返回一个数组,通过string转换成字符串["0","1",...]*/
var result = (isArray(value) || isArguments(value))
? baseTimes(value.length, String)
: [];
var length = result.length,
skipIndexes = !!length;
// value数组情况下,这里为true,isIndex通常返回true,不会走到push这里 || value字符串这里为false,,isIndex通常返回false。,字符串会走到push这里。
for (var key in value) {
// case0 -如果是继承 或者 这个,value没有key这个属性。
// case1 - key不能是length属性,比如argument有length这个属性,是不能push到返回的。
// isIndex返回它是否是一个类数组的key,如果是就需要返回的。
if ((inherited || hasOwnProperty.call(value, key)) &&
!(skipIndexes && (key == 'length' || isIndex(key, length)))) {
result.push(key);
}
}
return result;
}
// - 这里调用时,iteratee使用的是String,将n转成字符串类型
function baseTimes(n, iteratee) { // n如果为4,iteratee => String, => ["0","1","2","3"]
var index = -1,
result = Array(n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
/**
* value是否是一个有效的array-like的index
*/
function isIndex(value, length) {
length = length == null ? MAX_SAFE_INTEGER : length;
return !!length &&
(typeof value == 'number' || reIsUint.test(value)) &&
(value > -1 && value % 1 == 0 && value < length);
}
// (typeof value == 'number' || reIsUint.test(value)) value必须是number 或者"012313"这种。
//(value > -1 && value % 1 == 0 && value < length) value必须是大于-1的整数,而且要小于length。
baseKeysIn
/**
* The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
* `_.keysIn`的基本实现,它不将稀疏数组视为密集。
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names.
*/
function baseKeysIn(object) {
if (!isObject(object)) {
return nativeKeysIn(object);
}
var isProto = isPrototype(object),
result = [];
for (var key in object) {
if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { // key如果是'constructor'这里避免,自身有了一个自己定义的constructor,只有这种情况下,我们会返回constructor
result.push(key);
}
}
return result;
}
这里的if判断相对简单些。key等于constructor
这种情况,我们要排除自身未重写这个属性。
如下,会返回
function Foo() {
this.a = 1;
this.b = 2;
this.constructor=3;
}
Foo.prototype.c = 3;
(function (){
console.log(keysIn(
new Foo()
))
})()
// => Array(4) ["a", "b", "constructor", "c"]
_.toString
将value转成字符串。如果value是null或者undefined返回空字符串。-0 将被转换为字符串"-0"。
/**
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to process.
* @returns {string} Returns the string.
* @example
*
* _.toString(null);
* // => ''
*
* _.toString(-0);
* // => '-0'
*
* _.toString([1, 2, 3]);
* // => '1,2,3'
*/
function toString(value) {
return value == null ? '' : baseToString(value);
}
baseString
该方法是_.baseString
的基础实现,它不会将nullish值转换为空字符串。
function baseToString(value) {
// Exit early for strings to avoid a performance hit in some environments.
if (typeof value == 'string') {
return value;
}
if (isSymbol(value)) {
return symbolToString ? symbolToString.call(value) : '';
}
var result = (value + ''); // 对象 =>[object object], [1,2,3] => "1,2,3"
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}
(result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
,允许-0
,只value为-0
时,返回-0
,其它情况返回result = value + ''
_.toSafeInteger(value)
转换 value 为安全整数。 安全整数可以用于比较和准确的表示。
function toSafeInteger(value) {
return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER);
}
baseClamp
The base implementation of _.clamp
which doesn't coerce arguments.
该方法对number的最大值最小值设定了范围,超出就返回边界值。
function baseClamp(number, lower, upper) {
if (number === number) { // not NaN
if (upper !== undefined) { //
number = number <= upper ? number : upper;
}
if (lower !== undefined) {
number = number >= lower ? number : lower;
}
}
return number;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。