// 冻结对象var emptyObject = Object.freeze({});// 是否未定义functionisUndef(v){return v ===undefined|| v ===null}// 是否已定义functionisDef(v){return v !==undefined&& v !==null}// 是否为truefunctionisTrue(v){return v ===true}// 是否为falsefunctionisFalse(v){return v ===false}/**
* 是否为基础类型
*/functionisPrimitive(value){return(typeof value ==='string'||typeof value ==='number'||// $flow-disable-linetypeof value ==='symbol'||typeof value ==='boolean')}/**
* 是否为对象
*/functionisObject(obj){return obj !==null&&typeof obj ==='object'}/**
* toString原型函数
*/var _toString =Object.prototype.toString;// 原型类型functiontoRawType(value){return_toString.call(value).slice(8,-1)}/**
* 是否为纯粹对象
*/functionisPlainObject(obj){return_toString.call(obj)==='[object Object]'}// 是否正则functionisRegExp(v){return_toString.call(v)==='[object RegExp]'}/**
* 是否为有效数组下标
*/functionisValidArrayIndex(val){var n =parseFloat(String(val));return n >=0&& Math.floor(n)=== n &&isFinite(val)}// 是否PromisefunctionisPromise(val){return(isDef(val)&&typeof val.then ==='function'&&typeof val.catch ==='function')}/**
* 将纯粹对象、数组在渲染时转换成实际的字符
*/functiontoString(val){return val ==null?'': Array.isArray(val)||(isPlainObject(val)&& val.toString === _toString)?JSON.stringify(val,null,2):String(val)}/**
* 转换为数字
*/functiontoNumber(val){var n =parseFloat(val);returnisNaN(n)? val : n
}
第112~354行:高阶函数、闭包、全局函数
/**
* 创建一个map,用于检查key是否在map中。使用闭包
*/functionmakeMap(str,
expectsLowerCase){var map = Object.create(null);var list = str.split(',');for(var i =0; i < list.length; i++){
map[list[i]]=true;}return expectsLowerCase
?function(val){return map[val.toLowerCase()];}:function(val){return map[val];}}/**
* 是否构建标签
*/var isBuiltInTag =makeMap('slot,component',true);/**
* 是否保留属性
*/var isReservedAttribute =makeMap('key,ref,slot,slot-scope,is');/**
* 从数组移除一个元素
*/functionremove(arr, item){if(arr.length){var index = arr.indexOf(item);if(index >-1){return arr.splice(index,1)}}}/**
* 对象是否包含某个属性。不包括symbol属性
*/var hasOwnProperty =Object.prototype.hasOwnProperty;functionhasOwn(obj, key){returnhasOwnProperty.call(obj, key)}/**
* 高阶函数cached,用到闭包。保存键值对
*/functioncached(fn){var cache = Object.create(null);return(functioncachedFn(str){var hit = cache[str];return hit ||(cache[str]=fn(str))})}/**
* 驼峰化字符串
*/var camelizeRE =/-(\w)/g;var camelize =cached(function(str){return str.replace(camelizeRE,function(_, c){return c ? c.toUpperCase():'';})});/**
* 首字母大写
*/var capitalize =cached(function(str){return str.charAt(0).toUpperCase()+ str.slice(1)});/**
* 驼峰转连字符
*/var hyphenateRE =/\B([A-Z])/g;var hyphenate =cached(function(str){return str.replace(hyphenateRE,'-$1').toLowerCase()});// bind函数兼容functionpolyfillBind(fn, ctx){functionboundFn(a){var l = arguments.length;return l
? l >1?fn.apply(ctx, arguments):fn.call(ctx, a):fn.call(ctx)}
boundFn._length = fn.length;return boundFn
}// 原生bind函数functionnativeBind(fn, ctx){returnfn.bind(ctx)}// bind兼容写法var bind =Function.prototype.bind
? nativeBind
: polyfillBind;/**
* 类数组转数组
*/functiontoArray(list, start){
start = start ||0;var i = list.length - start;var ret =newArray(i);while(i--){
ret[i]= list[i + start];}return ret
}/**
* 合并目标对象属性
*/functionextend(to, _from){for(var key in _from){
to[key]= _from[key];}return to
}/**
* 对象数组合并为一个对象
*/functiontoObject(arr){var res ={};for(var i =0; i < arr.length; i++){if(arr[i]){extend(res, arr[i]);}}return res
}// 占位函数functionnoop(a, b, c){}/**
* 返回false的函数
*/varno=function(a, b, c){returnfalse;};/**
* 返回相同内容的函数
*/varidentity=function(_){return _;};/**
* 从编译模块中将静态key合并为一个字符串
*/functiongenStaticKeys(modules){return modules.reduce(function(keys, m){return keys.concat(m.staticKeys ||[])},[]).join(',')}/**
* 浅相等。
*/functionlooseEqual(a, b){if(a === b){returntrue}var isObjectA =isObject(a);var isObjectB =isObject(b);if(isObjectA && isObjectB){try{var isArrayA = Array.isArray(a);var isArrayB = Array.isArray(b);if(isArrayA && isArrayB){return a.length === b.length && a.every(function(e, i){returnlooseEqual(e, b[i])})}elseif(a instanceofDate&& b instanceofDate){return a.getTime()=== b.getTime()}elseif(!isArrayA &&!isArrayB){var keysA = Object.keys(a);var keysB = Object.keys(b);return keysA.length === keysB.length && keysA.every(function(key){returnlooseEqual(a[key], b[key])})}else{/* istanbul ignore next */returnfalse}}catch(e){/* istanbul ignore next */returnfalse}}elseif(!isObjectA &&!isObjectB){returnString(a)===String(b)}else{returnfalse}}/**
* 返回浅相等的索引
*/functionlooseIndexOf(arr, val){for(var i =0; i < arr.length; i++){if(looseEqual(arr[i], val)){return i }}return-1}/**
* 只执行一次的函数
*/functiononce(fn){var called =false;returnfunction(){if(!called){
called =true;fn.apply(this, arguments);}}}