lodash 源码解析 — size

吐槽君 分类:javascript

前言

size 函数可以取出数组的长度、类数组对象的长度、SetMap 以及对象的键值数、字符串长度等并返回

思路分析

about size.png

源码分析

1. size

1. 传入参数
  • collection 传入对象、类数组、数组、setmapstring 等值
2. 源码分析
function size(collection) {
  if (collection == null) {
    return 0;
  }
  if (isArrayLike(collection)) {
    return isString(collection) ? stringSize(collection) : collection.length;
  }
  var tag = getTag(collection);
  if (tag == mapTag || tag == setTag) {
    return collection.size;
  }
  return baseKeys(collection).length;
}
 

判断是否是 null

if (collection == null) {
    return 0;
}
 

判断是否是类数组,包含 StringArray

if (isArrayLike(collection)) {
    return isString(collection) ? stringSize(collection) : collection.length;
}
 

判断是否是 mapset,用这两个类型的 size 属性

var tag = getTag(collection);
if (tag == mapTag || tag == setTag) {
    return collection.size;
}
 

返回对象的 key

return baseKeys(collection).length;
 

2. stringSize

1. 传入参数

string 普通字符串

2. 源码分析

stringSize 函数会对含有特殊 Unicode 的字符串进行区分,单独用 unicodeSize 方法判断字符串大小

function stringSize(string) {
  return hasUnicode(string)
    ? unicodeSize(string)
  : asciiSize(string);
}
 

3. unicodeSize

1. 传入参数

string 含有特殊 Unicode 字符的字符串

2. 源码分析

hasUnicode 的中借助下面的正则把筛选出特定的符号:
/[\u200d\ud800-\udfff\u0300-\u036f\ufe20-\ufe2f\u20d0-\u20ff\ufe0e\ufe0f]/
这组正则包含:零宽连字符、未定义区间、结合附加符号、组合用记号、变体选择符15 - 16 等,这里的主要作用的是判断出连字符等的连字组合作用,使用 unicodeSize 的主要作用就是正确的将结合连字符后的字符串的长度大小结果输出

function unicodeSize(string) {
  var result = reUnicode.lastIndex = 0;
  while (reUnicode.test(string)) {
    ++result;
  }
  return result;
}
 

4. baseKeys

1. 传入参数

object 传入对象

2. 源码分析
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}
 

利用 Object.keys 获取不存在原型的对象的 key 数组并返回

  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
 

利用 hasOwnProperty 获取存在原型的对象的 key 数组并返回

  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
 

应用场景

通常的 size 函数肯定是用于判断传入的数组、类数组、字符串等的大小,尤其是其可以根据 Unicode 编码的含义将字符串的大小输出出来,比如下面的字符串中,\u0300\u200d 是两个特殊的 Unicode 字符,分别是组合用抑音符(表现为拼音四声符号)和零宽连接符,这几个字符在连接到一起的时候会进行结合,用 size 测量大小的时候就会表现为结合后的大小,而用 length 测量会表现为有多少字符就多大

'\u0300a\u200d\u200da'.length  // 5
_.size('\u0300a\u200d\u200da') // 3
'a\u0300a'.length // 3
_.size('a\u0300a') // 2
 

总结

size 函数是个比较简单的函数,但也有其巧妙的构思存在,最显著的就是可以根据 Unicode 的字符含义来判断字符串的长度

回复

我来回复
  • 暂无回复内容