Vue shared/util.js 文件工具方法全解

发布于 2024-10-15 21:42:02 字数 10979 浏览 14 评论 0

emptyObject

源码如下:

export const emptyObject = Object.freeze({})

描述: emptyObject 是一个冻结的空对象,这意味着 emptyObject 是不可扩展、不可配置、不可写的

isUndef

源码如下:

export function isUndef (v: any): boolean %checks {
  return v === undefined || v === null
}
  • 描述: isUndef 函数用来判断给定的变量是否是未定义,要注意的是,这个函数认为即使变量值为 null ,也会认为其是未定义的。
  • 参数:{Any} v 任意变量

isPrimitive

源码如下:

export function isPrimitive (value: any): boolean %checks {
  return (
    typeof value === 'string' ||
    typeof value === 'number' ||
    // $flow-disable-line
    typeof value === 'symbol' ||
    typeof value === 'boolean'
  )
}
  • 描述: isPrimitive 用来判断给定的变量是否是原始类型值,即:字符串、数字、布尔值以及 symbol
  • 参数:{Any} v 任意变量

isValidArrayIndex

源码如下:

export function isValidArrayIndex (val: any): boolean {
  const n = parseFloat(String(val))
  return n >= 0 && Math.floor(n) === n && isFinite(val)
}
  • 描述: isValidArrayIndex 函数用来判断给定的值是否是有效的数组索引。如果是有效的则返回 true ,否则返回 false
  • 源码分析:

一个有效的数组索引要满足两个条件:1、大于等于 0 的整数,2、在条件一的基础上,这个整数不能是无限的。在源码中条件 n >= 0 && Math.floor(n) === n 保证了索引是一个大于等于 0 的整数,而条件 isFinite(val) 保证了该值是有限的。

extend

源码如下:

/**
 * Mix properties into target object.
 */
export function extend (to: Object, _from: ?Object): Object {
  for (const key in _from) {
    to[key] = _from[key]
  }
  return to
}
  • 描述:将 _from 对象的属性混合到 to 对象中
  • 参数:
    • {Object} to 目标对象
    • {Object} _from 源对象
  • 返回值:混合后的新对象

源码分析

extend 函数的实现还是挺简单的,使用一个 for in 语句实现。大家基本都能看得懂

makeMap

源码如下:

/**
 * Make a map and return a function for checking if a key
 * is in that map.
 */
export function makeMap (
  str: string,
  expectsLowerCase?: boolean
): (key: string) => true | void {
  const map = Object.create(null)
  const list: Array<string> = str.split(',')
  for (let i = 0; i < list.length; i++) {
    map[list[i]] = true
  }
  return expectsLowerCase
    ? val => map[val.toLowerCase()]
    : val => map[val]
}
  • 描述: makeMap 函数首先根据一个字符串生成一个 map ,然后根据该 map 产生一个新函数,新函数接收一个字符串参数作为 key ,如果这个 keymap 中则返回 true ,否则返回 undefined
  • 参数:
    • {String} str 一个以逗号分隔的字符串
    • {Boolean} expectsLowerCase 是否小写
  • 返回值:根据生成的 map 产生的函数

源码分析

首先定义一个对象 map

const map = Object.create(null)

然后根据逗号,将 str 分隔成数组并保存到 list 变量中:

const list: Array<string> = str.split(',')

遍历 list 并以 list 中的元素作为 mapkey ,将其设置为 true

for (let i = 0; i < list.length; i++) {
  map[list[i]] = true
}

最后,返回一个函数,并且如果 expectsLowerCasetrue 的话,将 mapkey 小写:

return expectsLowerCase
    ? val => map[val.toLowerCase()]
    : val => map[val]

使用示例:

// 检测是否是小写的元音字母
export const isVowel = makeMap('a,e,i,o,u', true)

isVowel('e')  // true
isVowel('b')  // false

isBuiltInTag

源码如下:

/**
 * Check if a tag is a built-in tag.
 */
export const isBuiltInTag = makeMap('slot,component', true)
  • 描述:检查是否是内置的标签

源码分析

isBuiltInTag 是一个使用 makeMap 生成的函数:

makeMap('slot,component', true)

可知: slotcomponentVue 内置的标签

remove

源码如下:

export function remove (arr: Array<any>, item: any): Array<any> | void {
  if (arr.length) {
    const index = arr.indexOf(item)
    if (index > -1) {
      return arr.splice(index, 1)
    }
  }
}
  • 描述:从数组中移除指定元素
  • 参数:
    • {Array} arr 源数组
    • {Any} item 要从数组中移除的元素
  • 返回值:如果成功移除,则返回移除后的元素,否则返回 undefined

源码分析:

首先判断数组 arr 的长度是否为 0 ,如果为 0 则说明没有任何需要移除的元素,如果不为 0 则使用 indexOf 函数查看要移除的元素是否在数组中以及在数组中的位置,然后使用 splice 方法将其移除。

cached

源码如下:

/**
 * Create a cached version of a pure function.
 */
export function cached<F: Function> (fn: F): F {
  const cache = Object.create(null)
  return (function cachedFn (str: string) {
    const hit = cache[str]
    return hit || (cache[str] = fn(str))
  }: any)
}
  • 描述:为一个纯函数创建一个缓存版本的函数
  • 参数:
    • {Function} fn 一个函数(注意:这个函数必须是纯函数)
  • 返回值: 新的函数

源码分析:

首先,大家要明白这个函数的意义,我们提到了,传递给 cached 函数的参数一定要是一个纯函数,那为什么要是一个纯函数呢?因为纯函数有一个特性,即输入不变则输出不变。在现实中,有很多这样的场景,简单举个例子,也是我们接下来要介绍的一个函数:中横线转驼峰 ( camelize() 函数),假设我们给 camelize 函数传递字符串 aaa-bbb ,那么得到的始终都是 aaaBbb ,不会有其他可能,那我们想象一下,在一个庞大的应用程序中,我们可能需要转译很多相同的字符串,如果每次都要重新执行转译程序,那么是一个极大的浪费,我们只需转译一次并将结果缓存,当再次需要转译该相同的字符串时,我们只需要从缓存中读取即可,这就是 cached 的目标,下面我们看一下它是怎么实现的。

首先创建一个 cache 对象:

const cache = Object.create(null)

随即便返回一个函数:

return (function cachedFn (str: string) {
  const hit = cache[str]
  return hit || (cache[str] = fn(str))
}: any)

这个函数与原函数 fn 的区别就在于:先读取缓存:

const hit = cache[str]

如果有命中则直接返回缓存的值,否则采用原函数 fn 计算一次并且设置缓存,然后返回结果:

return hit || (cache[str] = fn(str))

可以看到,这就是一个函数式编程的玩法,也是比较简单的。

emptyObject

源码如下:

export const emptyObject = Object.freeze({})
  • 描述:创建一个空的冻结对象
  • 源码分析:通过以空 json 对象 {} 为参数调用 Object.freeze 函数实现。

camelize

源码如下:

/**
 * Camelize a hyphen-delimited string.
 */
const camelizeRE = /-(\w)/g
export const camelize = cached((str: string): string => {
  return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
})
  • 描述:中横线转驼峰
  • 源码分析:

这是一个很基本的函数,定义一个正则表达式: /-(\w)/g ,用来全局匹配字符串中 中横线及中横线后的一个字符。真心没什么好说的.....

使用实例:

camelize('aaa-bbb')   // aaaBbb

noop

源码如下:

/**
 * Perform no operation.
 * Stubbing args to make Flow happy without leaving useless transpiled code
 * with ...rest ( https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/) 
 */
export function noop (a?: any, b?: any, c?: any) {}
  • 描述:空函数,什么都不做,用于初始化一些值为函数的变量。

源码分析:

就是简单的写了一个空函数 noop ,至于其中的参数 abc 的作用,我们看注释可知是为了避免 Flow 使用 rest 参数转译代码。

no

源码如下:

/**
 * Always return false.
 */
export const no = (a?: any, b?: any, c?: any) => false
  • 描述:始终返回 false 的函数

toRawType

源码如下:

/**
 * Get the raw type string of a value e.g. [object Object]
 */
const _toString = Object.prototype.toString

export function toRawType (value: any): string {
  return _toString.call(value).slice(8, -1)
}
  • 描述:获取一个值的原始类型字符串。

源码分析:

首先使用 Object.prototype.toString 获取诸如这样的字符串: [object Object] ,然后使用 slice 方法截取,最终结果类似于 Object

isPlainObject

源码如下:

/**
 * Strict object type check. Only returns true
 * for plain JavaScript objects.
 */
export function isPlainObject (obj: any): boolean {
  return _toString.call(obj) === '[object Object]'
}
  • 描述:检测一个对象是否是纯对象。

源码分析:

原理很简单,使用 Object.prototype.toString'[object Object]' 做全等对比。

isRegExp

源码如下:

export function isRegExp (v: any): boolean {
  return _toString.call(v) === '[object RegExp]'
}
  • 描述:检测一个对象是否是正则对象。

源码分析:

原理很简单,使用 Object.prototype.toString'[object RegExp]' 做全等对比。

genStaticKeys

源码如下:

/**
 * Generate a static keys string from compiler modules.
 */
export function genStaticKeys (modules: Array<ModuleOptions>): string {
  return modules.reduce((keys, m) => {
    return keys.concat(m.staticKeys || [])
  }, []).join(',')
}
  • 描述:根据编译器( compiler ) 的 modules 生成一个静态键字符串。
  • 参数:
    • {Array} modules 编译器选项参数的 modules 选项

源码分析:

首先我们知道 modules 是编译器的一个选项,该选项是一个数组,其格式大概如下:

[
  {
    staticKeys: ['staticClass'],
    transformNode,
    genData
  },
  {
    staticKeys: ['staticStyle'],
    transformNode,
    genData
  },
  {
    preTransformNode
  }
]

可以发现 modules 的每一个元素是一个对象,该对象可能包含 staticKeys 属性,也可能不包含,而 genStaticKeys 函数的作用就是通过对 modules 数组的遍历,将所有的 staticKeys 收集到一个数组,最终转换成一个以逗号 , 拼接的字符串。

其实现方式很简单,对数组 modules 使用 reduce 函数进行归并,将所有的 staticKeys 归并到一个数组中,最后通过 join(',') 实现目的。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

居里长安

暂无简介

0 文章
0 评论
652 人气
更多

推荐作者

謌踐踏愛綪

文章 0 评论 0

开始看清了

文章 0 评论 0

高速公鹿

文章 0 评论 0

alipaysp_PLnULTzf66

文章 0 评论 0

热情消退

文章 0 评论 0

白色月光

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文