vue3源码基础工具函数
# vue3源码基础工具函数[^1]
# 1、EMPTY_OBJ
空对象
/**
* - `object.freeze` 冻结对象内置api
* - 冻结对象的最外层无法修改
*/
const EMPTY_OBJ_1 = Object.freeze({});
EMPTY_OBJ_1.name = '小曹'
console.log(EMPTY_OBJ_1.name)
const EMPTY_OBJ_2 = Object.freeze({ props: { mp: '小曹' } })
EMPTY_OBJ_2.props.name = '小曹2'
EMPTY_OBJ_2.props2 = 'props2'
console.log(EMPTY_OBJ_2.props.name)
console.log(EMPTY_OBJ_2.props2)
console.log(EMPTY_OBJ_2)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13

# 2、NOOP
空函数
使用场景
方便判断:初始化instance的render属性时将NOOP赋值于它,render一旦发生了赋值行为不管被赋值的方法字面上是否和NOOP一样最后都不再等于NOOP了。可以用来判断属性初始化后续有无再改变。
方便压缩
const NOOP = () => { }
const instance = { render: NOOP }
const dev = true;
// if (dev) {
// instance.render = function () {
// console.log('hello xiaocao render')
// }
// }
if (instance.render === NOOP) {
console.log(true)
}
instance.render()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
const NOOP = () => { }
const instance = { render: NOOP }
const dev = true;
if (dev) {
instance.render = function () {
console.log('hello xiaocao render')
}
}
if (instance.render === NOOP) {
console.log(true)
}
instance.render()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3、isOn判断字符串是否on开头
正则表达式^在开头则表示以什么为开头,否则就是指非。
$符号在结尾则表示以什么结尾
eg:
/^a[^a-z]b$/
以a开头的非a~z之间的以b结尾的字符
const onRE = /^on[^a-z]/
const isOn = key => console.log(onRE.test(key))
isOn('onhappy')//false
isOn('onHappy')//true
const ex = /^a[^a-z]b$/
const isEx = key => console.log(ex.test(key))
isEx('aSb')// true
isEx('awb')// false
isEx('aSS')// false
isEx('dSS')// false
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 4、remove
移除数组中的一项
相关知识:
- Array.prototype.indexOf():
indexOf()
方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。- Array.prototype.splice():
splice()
方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。注:
splice
是很耗性能的方法,删除数组中的一项,其他的元素都会移动位置。axios InterceptorManager
拦截器移除拦截器时是将拦截器设置为null。最后执行时为null的不执行。性能更加优化
// 利用splice移除数组项
const remove = (arr, el) => {
const i = arr.indexOf(el)
if (i > -1) {
arr.splice(i, 1)
}
}
let arr = [1, 2, 3]
remove(arr, 3)
console.log(arr) // [1, 2]
// axios拦截器代码
// 代码有删减
// 声明
this.handlers = [];
// 移除
if (this.handlers[id]) {
this.handlers[id] = null;
}
// 执行
if (h !== null) {
fn(h);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 5、判断字符串是否以onUpdate:
开头
参考资料:实例方法:includes(), startsWith(), endsWith() (opens new window)
/**
* - 判断字符串是否以`onUpdate:`开头
*/
const isModeListener = key => key.startsWith('onUpdate:');
console.log(isModeListener('onUpdate:change')) // true
console.log(isModeListener('1onUpdate:change'))// false
console.log(isModeListener('1onUpdatechange'))// false
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 6、extend 继承 合并
利用Object.assign方法实现继承与合并
Object.assign()
方法用于将所有==可枚举属性==的值从一个或多个源对象分配到目标对象。它将==返回目标对象==。如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。
/**
* - extend 继承 合并
*/
const extend = Object.assign;
const data = { name: '小曹' }
const data2 = extend(data, { mp: '小曹1', name: '小曹1' })
console.log(data)
console.log(data2)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 7、hasOwn 判断是否本身所拥有的的属性
- Object.prototype.hasOwnProperty():
hasOwnProperty()
方法会返回一个布尔值,指示对象==自身属性==中是否具有指定的属性(也就是,是否有指定的键)。
/**
* - hasOwn 判断是否本身所拥有的的属性,不通过原型链向上查找
*/
const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key)
console.log(hasOwn({__proto__: {a: 1}}, 'a'))// false
console.log(hasOwn({a: undefined}, 'a'))// true
console.log(hasOwn({}, 'toString'))// false
console.log(hasOwn({}, 'a'))// false
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 8、isArray判断数组
const isArray = Array.isArray
console.log(isArray([]))
//严谨改良版
function isArray (arr) {
return Object.prototype.toString.call(arr) === '[object Array]' &&
Array.isArray(arr) &&
arr.__proto__ === Array.prototype &&
arr instanceof Array
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 9、isMap判断是否为map
/**
* - isMap判断是否为Map对象
*/
const isMap = val => val.toString() === '[object Map]'
const map = new Map()
const o = { p: 'hello word' }
map.set(o, 'content')
console.log(map)
console.log(isMap({}))// false
console.log(isMap(map))// true
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 10、isSet判断是否set对象
const isSet = (val) => toTypeString(val) === '[object Set]';
const set = new Set();
console.log(isSet(set)) // true
1
2
3
4
2
3
4
# 11、isDate判断是否Date对象
instanceof
操作符左边是右边的实例;
- 原理是根据原型链向上查找,如果能找到则返回true;所以并不是非常准确
const isDate = val => console.log(val instanceof Date)
isDate(new Date)// true
isDate({ __proto__: new Date() })// true 严格来说应该是false
1
2
3
4
2
3
4
# 12、isFunction判断是不是函数
const isFunction = val => typeof val === 'function'
console.log(isFunction(()=>{}))// true
console.log(isFunction({}))// false
console.log(isFunction(new Function))// true
1
2
3
4
2
3
4
# 13、由toTypeString 对象转字符串等引申的升级版typeof
💡Object.prototype.toString.call(obj):通过call改变获取toString方法获取类型'[object String]'来进行简单的类型判断
/**
* -typeof进阶版
* @param {*} obj 需要进行检查的参数
* @param {boolean} fullClass 是否仅仅是简单进行类型判断
* @returns {string} 类型字符串
*/
function type (obj, fullClass) {
if (fullClass) {
return (obj === null) ? '[object Null]' : Object.prototype.toString.call(obj)
}
// 判断参数为Null直接返回字符串’null‘
if (obj === null) {
return (obj + '').toLowerCase()
}
var deepType = Object.prototype.toString.call(obj).slice(8, -1).toLowerCase()
if (deepType === 'generatorfunction') {
return 'function'
}
// 检查一下防止边缘情况的发生导致判断不准确,比如[object, HTMLDivElement]..
return deepType.match(/^(array|bigint|date|error|function|generator|regexp|symbol)$/) ?
deepType : (typeof obj === 'object' || typeof obj === 'function') ? 'object' : typeof obj;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
编辑 (opens new window)
上次更新: 2022/02/21, 05:57:00