shared/util.js
1.hasOwn
var hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwn (obj, key) { return hasOwnProperty.call(obj, key) }
extend
export function extend (to: Object, _from: ?Object): Object { for (const key in _from) { to[key] = _from[key] } return to }
mergeField
// 对option[key]进行策略处理,默认不处理 function mergeField (key) { const strat = strats[key] || defaultStrat options[key] = strat(parent[key], child[key], vm, key) }
makeMap
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] }
很多地方都会用到:例如”isPlainTextElement = makeMap('script,style,textarea', true)
2.getTypeIndex
function getType (fn) { var match = fn && fn.toString().match(/^s*function (w+)/); return match ? match[1] : '' //获得函数名 }
// console.log(Boolean.toString().match(/^s*function (w+)/))
// ["function Boolean", "Boolean", index: 0, input: "function Boolean() { [native code] }", groups: undefined] function isSameType (a, b) {
return getType(a) === getType(b)
}
function getTypeIndex (type, expectedTypes) { if (!Array.isArray(expectedTypes)) { return isSameType(expectedTypes, type) ? 0 : -1 } for (var i = 0, len = expectedTypes.length; i < len; i++) { if (isSameType(expectedTypes[i], type)) { return i } } return -1 }
3.proxy代理
//key a if (!(key in vm)) { proxy(vm, "_props", key); } function noop (a, b, c) {} var sharedPropertyDefinition = { enumerable: true, configurable: true, get: noop, set: noop }; function proxy (target, sourceKey, key) { sharedPropertyDefinition.get = function proxyGetter () { // this为vm。 return this[sourceKey][key] }; sharedPropertyDefinition.set = function proxySetter (val) { this[sourceKey][key] = val; }; Object.defineProperty(target, key, sharedPropertyDefinition); } //对vm._props进行代理。
4.toggleObserving
var shouldObserve = true; function toggleObserving (value) { shouldObserve = value; }
5.hasProto
var hasProto = '__proto__' in {};console.log(hasProto); //true
6.mergeOptions
export function mergeOptions ( parent: Object, child: Object, vm?: Component ): Object { if (process.env.NODE_ENV !== 'production') { //核实子对象中components的名字合法 checkComponents(child) } if (typeof child === 'function') { child = child.options } normalizeProps(child, vm) normalizeInject(child, vm) normalizeDirectives(child) const extendsFrom = child.extends if (extendsFrom) { parent = mergeOptions(parent, extendsFrom, vm) } if (child.mixins) { for (let i = 0, l = child.mixins.length; i < l; i++) { parent = mergeOptions(parent, child.mixins[i], vm) } } const options = {} let key for (key in parent) { mergeField(key) } for (key in child) { if (!hasOwn(parent, key)) { mergeField(key) } } function mergeField (key) { const strat = strats[key] || defaultStrat options[key] = strat(parent[key], child[key], vm, key) } return options }
7.toArray、cached(shared/util.js)
// 形成一个新数组,该数组是 any 从 number 以后的数组。 export function toArray (list: any, start?: number): Array<any> { start = start || 0 let i = list.length - start const ret: Array<any> = new Array(i) while (i--) { ret[i] = list[i + start] } return ret }
// 高阶函数,对外赋值之后调用。每次调用缓存结果。
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)
}
cached的用法如下:
function cached(fn) { const cache = Object.create(null) return (function cachedFn (str) { const hit = cache[str] return hit || (cache[str] = fn(str)) }) } let f = function (x) { return x*x } let k1 = cached(f) let k2 = k1('7') console.log('k2=',k2) //k2= 49 let k3 = k1('7') console.log('k3=',k3) //k3=49
以 _和$开头的变量或者方法的key,
/** * Check if a string starts with $ or _ */ export function isReserved (str: string): boolean { const c = (str + '').charCodeAt(0) return c === 0x24 || c === 0x5F }