玖叶教程网

前端编程开发入门

Vue3中经常使用的js函数(vue中jsx)

makeMap

这个工具函数看起来很无厘头,根据注释创建一个map,返回一个函数检查是否有这个值,我们仔细看一下并且用一下,就会发现,不愧是写了一个框架的男人封装出来的函数

// 创建一个map并返回一个函数,检查是否存在key在map里面
function makeMap(str, expectsLowerCase) {
// 这里为什么使用Object.create(null)不是直接{}?
// 因为Object.create(null)是最纯净的对象,不会有任何的东西,比如constructor,hasOwnProperty等等
// 这使得我们不管有意还是无意,都不会影响任何东西
const map = Object.create(null)
const list = str.split(',')
for (let i = 0; i < list.length; i++) {
map[list[i]] = true
}
// 这里为什么要用!!
// 因为这里返回的只是true || false
// 有内容即'true' or true返回true,null ''fasle之类的则返回false
return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val]
}

关于Object.create(null){}的区别,具体可以看这里

我们直接看他怎么用

// 这里囊括了所有的html标签
const SVG_TAGS =
'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view'

const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS)
// 这样就可以直接传入字符串,判断是否是标签
// 比如isHTMLTag('input') --> true
const isKnownHtmlAttr = /*#__PURE__*/ makeMap(
`accept,accept-charset,accesskey,action,align,allow,alt,async,` +
`autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,` +
`border,buffered,capture,challenge,charset,checked,cite,class,code,` +
`codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,` +
`coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,` +
`disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,` +
`formaction,formenctype,formmethod,formnovalidate,formtarget,headers,` +
`height,hidden,high,href,hreflang,http-equiv,icon,id,importance,integrity,` +
`ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,` +
`manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,` +
`open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,` +
`referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,` +
`selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,` +
`start,step,style,summary,tabindex,target,title,translate,type,usemap,` +
`value,width,wrap`
)
// isKnownHtmlAttr('charset') --> true

babelParserDefaultPlugins

const babelParserDefaultPlugins = [
'bigInt',
'optionalChaining',
'nullishCoalescingOperator'
]
// babel默认插件

EMPTY_OBJ

创建一个空的对象,如果不是生产环境则freeze(冻结)这个对象,不能修改

生产环境想修改也改不了(手动狗头)

const EMPTY_OBJ = process.env.NODE_ENV !== 'production' ? Object.freeze({}) : {}

EMPTY_ARR

创建一个空的对象,如果不是生产环境则freeze(冻结)这个数组,不能修改

const EMPTY_ARR = process.env.NODE_ENV !== 'production' ? Object.freeze([]) : []

NOOP

返回空函数

const NOOP = () => {}

NO

返回false

const NO = () => false

isOn

判断字符串是否on开头,且 on 后首字母不是小写字母

const onRE = /^on[^a-z]/
const isOn = key => onRE.test(key)

匹配输入字符串的开始位置,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。要匹配 ^ 字符本身,使用 ^。

isModelListener

是否是onUpdate:开头

const isModelListener = key => key.startsWith('onUpdate:')

remove

删除数组的元素el

const remove = (arr, el) => {
const i = arr.indexOf(el)
if (i > -1) {
arr.splice(i, 1)
}
}

hasOwn

是否是自己本身拥有的属性

const hasOwnProperty = Object.prototype.hasOwnProperty
const hasOwn = (val, key) => hasOwnProperty.call(val, key)

isArray

是否是数组

const isArray = Array.isArray

isMap、isSet

判断是不是Map、Set对象

关于ES6Map、Set的详细介绍,可以看菜鸟教程MapSet

const isMap = val => toTypeString(val) === '[object Map]'
const isSet = val => toTypeString(val) === '[object Set]'

isDate、isFunction、isString、isSymbol

基本的判断数据类型函数

const isDate = val => val instanceof Date
const isFunction = val => typeof val === 'function'
const isString = val => typeof val === 'string'
const isSymbol = val => typeof val === 'symbol'

isObject

判断是否是对象

这个排除null是因为null typeof --> 'object'

这里并不能判定数组和对象的区别,typeof [] --> 'object'

const isObject = val => val !== null && typeof val === 'object'

isPromise

Promise其实是一个对象

有reject,resolve,then,all,rece,catch方法,这也是封装Promise的基本功能

所以他这里判断是否是Promise首先判断他是否是对象,再判断是否有then和catch方法

const isPromise = val => {
return isObject(val) && isFunction(val.then) && isFunction(val.catch)
}

toTypeString

call 是一个函数,第一个参数是 执行函数里面 this 指向

这个函数用来获取传入参数的类型

const objectToString = Object.prototype.toString
const toTypeString = value => objectToString.call(value)
Object.prototype.toString.call(123)
// --> '[object Number]'
Object.prototype.toString.call(new Promise((res, rej) => {}))
// --> '[object Promise]'

toRawType

截取toTypeString返回的类型slice(start,end),负数的时候为倒数第几位

const toRawType = value => {
return toTypeString(value).slice(8, -1)
}
toRawType(123)
// --> 'Number'
toRawType('123')
// --> 'String'

isPlainObject

判断是否是纯粹的对象

const isPlainObject = val => toTypeString(val) === '[object Object]'
isPlainObject({})
// --> true
isPlainObject([])
// --> false

注意这里和isObject的区别,isObject并不能判定[]是否是对象还是数组,这里可以

isIntegerKey

判断一个字符串是否是10进制的正整数

const isIntegerKey = key =>
isString(key) &&
key !== 'NaN' &&
key[0] !== '-' &&
'' + parseInt(key, 10) === key

cacheStringFunction

缓存字符串的函数

const cacheStringFunction = fn => {
const cache = Object.create(null)
return str => {
const hit = cache[str]
return hit || (cache[str] = fn(str))
}
}

这个函数咋一看不是很看得懂,就是分开来看就明了了,传入一个函数,返回一个函数,是不是和makeMap有点像,而且这里还使用了闭包进行了缓存,避免多次重复处理字符串

直接看他怎么用

// 首字母转大写
const camelizeRE = /-(\w)/g
const camelize = cacheStringFunction((str) => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));
});

hasChanged

value和oldVlaue是否改变

const hasChanged = (value, oldValue) => !Object.is(value, oldValue)

这里我们详细介绍Object.is()=====的区别

// ==
// 等同,比较运算符,两边值类型不同的时候,先进行类型转换,再比较
console.log('1' == 1)
// --> true

// ===
// 恒等,严格比较运算符,不做类型转换,类型不同就是不等
// 判定方式:
// 1、如果类型不同,就不相等
// 2、如果两个都是数值,并且是同一个值,那么相等
// 3、如果两个都是字符串,每个位置的字符都一样,那么相等;否则不相等
// 4、如果两个值都是同样的Boolean值,那么相等
// 5、如果两个值都引用同一个对象或函数,那么相等,即两个对象的物理地址也必须保持一致;否则不相等
// 6、如果两个值都是null,或者都是undefined,那么相等
console.log('1' === 1)
// --> fasle

// Object.is()
// Object.is()和===判定基本一致,但是有两个区别
// 1、+0不等于-0
// 2、NaN等于自身

console.log(+0 === -0)
// --> true
console.log(NaN === NaN)
// --> false

Object.is(+0, -0)
// --> false
object.is(NaN, NaN)
// --> true

invokeArrayFns

传入一个函数组成的数组,执行每一个函数,函数的参数是arg

const invokeArrayFns = (fns, arg) => {
for (let i = 0; i < fns.length; i++) {
fns[i](arg)
}
}

def

对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

const def = (obj, key, value) => {
Object.defineProperty(obj, key, {
configurable: true,
enumerable: false,
value
})
}

configurable
当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。

enumerable

使对象的属性是可以枚举的

toNumber

函数解析一个参数(必要时先转换为字符串)并返回一个浮点数。如果转换为NaN则说明不是Number类型,则返回原来的值

const toNumber = val => {
const n = parseFloat(val)
return isNaN(n) ? val : n
}

getGlobalThis

let _globalThis
const getGlobalThis = () => {
return (_globalThis ||
(_globalThis =
typeof globalThis !== 'undefined'
? globalThis
: typeof self !== 'undefined'
? self
: typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: {}));
};

获取全局 this 指向

初次执行肯定是 _globalThisundefined。所以会执行后面的赋值语句

如果存在 globalThis 就用 globalThis

如果存在self,就用self。在 Web Worker 中不能访问到 window 对象,但是我们却能通过 self 访问到 Worker 环境中的全局对象

如果存在window,就用window

如果存在global,就用globalNode环境下,使用global

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言