Vue源码-工具方法
/* */
//Object.freeze()阻止修改现有属性的特性和值,并阻止添加新属性。
var emptyObject = Object.freeze({});
// these helpers produces better vm code in JS engines due to their
// explicitness and function inlining
// these helpers produces better vm code in JS engines due to their
// explicitness and function inlining
//判断数据 是否是undefined或者null
function isUndef(v) {
return v === undefined || v === null
}
//判断数据 是否不等于 undefined或者null
function isDef(v) {
return v !== undefined && v !== null
}
//判断是否真的等于true
function isTrue(v) {
return v === true
}
// 判断是否是false
function isFalse(v) {
return v === false
}
/**
* Check if value is primitive
* //判断数据类型是否是string,number,symbol,boolean
*/
function isPrimitive(value) {
//判断数据类型是否是string,number,symbol,boolean
return (
typeof value === 'string' ||
typeof value === 'number' ||
// $flow-disable-line
typeof value === 'symbol' ||
typeof value === 'boolean'
)
}
/**
* Quick object check - this is primarily used to tell
* Objects from primitive values when we know the value
* is a JSON-compliant type.
*/
function isObject(obj) {
//判断是否是对象
return obj !== null && typeof obj === 'object'
}
/**
* Get the raw type string of a value e.g. [object Object]
*/
//获取toString 简写
var _toString = Object.prototype.toString;
function toRawType(value) {
//类型判断 返会Array ,Function,String,Object,Re 等
return _toString.call(value).slice(8, -1)
}
/**
* Strict object type check. Only returns true
* for plain JavaScript objects.
*/
function isPlainObject(obj) {
//判断是否是对象
return _toString.call(obj) === '[object Object]'
}
function isRegExp(v) {
//判断是否是正则对象
return _toString.call(v) === '[object RegExp]'
}
/**
* Check if val is a valid array index.
*/
/**
* Check if val is a valid array index.
* 检查VAL是否是有效的数组索引。
*/
function isValidArrayIndex(val) {
//isFinite 检测是否是数据
//Math.floor 向下取整
var n = parseFloat(String(val));
//isFinite 如果 number 是有限数字(或可转换为有限数字),那么返回 true。否则,如果 number 是 NaN(非数字),或者是正、负无穷大的数,则返回 false。
return n >= 0 && Math.floor(n) === n && isFinite(val)
}
/**
* Convert a value to a string that is actually rendered.
*/
function toString(val) {
//将对象或者其他基本数据 变成一个 字符串
return val == null
? ''
: typeof val === 'object'
? JSON.stringify(val, null, 2)
: String(val)
}
/**
* Convert a input value to a number for persistence.
* If the conversion fails, return original string.
*/
function toNumber(val) {
//字符串转数字,如果失败则返回字符串
var n = parseFloat(val);
return isNaN(n) ? val : n
}
/**
* Make a map and return a function for checking if a key
* is in that map.
*
* //map 对象中的[name1,name2,name3,name4] 变成这样的map{name1:true,name2:true,name3:true,name4:true}
* 并且传进一个key值取值,这里用到策略者模式
*/
function makeMap(str,
expectsLowerCase) {
var map = Object.create(null); //创建一个新的对象
var list = str.split(','); //按字符串,分割
for (var i = 0; i < list.length; i++) {
map[list[i]] = true; //map 对象中的[name1,name2,name3,name4] 变成这样的map{name1:true,name2:true,name3:true,name4:true}
}
return expectsLowerCase
? function (val) {
return map[val.toLowerCase()];
} //返回一个柯里化函数 toLowerCase转换成小写
: function (val) {
return map[val];
} //返回一个柯里化函数 并且把map中添加一个 属性建
}
/**
* Check if a tag is a built-in tag.
* 检查标记是否为内置标记。
*/
var isBuiltInTag = makeMap('slot,component', true);
/**
* Check if a attribute is a reserved attribute.
* 检查属性是否为保留属性。
* isReservedAttribute=function(vale){ map{key:true,ref:true,slot-scope:true,is:true,vaule:undefined} }
*/
var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is');
/**
* Remove an item from an array
* //删除数组
*/
function remove(arr, item) {
if (arr.length) {
var index = arr.indexOf(item);
if (index > -1) {
return arr.splice(index, 1)
}
}
}
/**
* Check whether the object has the property.
*检查对象属性是否是实例化还是原型上面的
*/
var hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
return hasOwnProperty.call(obj, key)
}
/**
* Create a cached version of a pure function.
*/
/**
* Create a cached version of a pure function.
* 创建纯函数的缓存版本。
* 创建一个函数,缓存,再return 返回柯里化函数
* 闭包用法
*/
/***********************************************************************************************
*函数名 :cached
*函数功能描述 : 创建纯函数的缓存版本。 创建一个函数,缓存,再return 返回柯里化函数 闭包用法
*函数参数 : fn 函数
*函数返回值 : fn
*作者 :
*函数创建日期 :
*函数修改日期 :
*修改人 :
*修改原因 :
*版本 :
*历史版本 :
***********************************************************************************************/
/*
* var aFn = cached(function(string){
*
* return string
* })
* aFn(string1);
* aFn(string2);
* aFn(string);
* aFn(string1);
* aFn(string2);
*
* aFn 函数会多次调用 里面就能体现了
* 用对象去缓存记录函数
* */
function cached(fn) {
var cache = Object.create(null);
return (function cachedFn(str) {
var hit = cache[str];
return hit || (cache[str] = fn(str))
})
}
/**
* Camelize a hyphen-delimited string.
* 用连字符分隔的字符串。
* camelize = cachedFn(str)=>{ var hit = cache[str];
return hit || (cache[str] = fn(str))}
调用一个camelize 存一个建进来 调用两次 如果建一样就返回 hit
横线-的转换成驼峰写法
可以让这样的的属性 v-model 变成 vModel
*/
var camelizeRE = /-(\w)/g;
var camelize = cached(function (str) {
return str.replace(camelizeRE, function (_, c) {
return c ? c.toUpperCase() : '';
})
});
/**
* Capitalize a string. 将首字母变成大写。
*/
var capitalize = cached(function (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
});
/**
* Hyphenate a camelCase string.
* \B的用法
\B是非单词分界符,即可以查出是否包含某个字,如“ABCDEFGHIJK”中是否包含“BCDEFGHIJK”这个字。
*/
var hyphenateRE = /\B([A-Z])/g;
var hyphenate = cached(function (str) {
//大写字母,加完减号又转成小写了 比如把驼峰 aBc 变成了 a-bc
//匹配大写字母并且两面不是空白的 替换成 '-' + '字母' 在全部转换成小写
return str.replace(hyphenateRE, '-$1').toLowerCase();
});
/**
* Simple bind polyfill for environments that do not support it... e.g.
* PhantomJS 1.x. Technically we don't need this anymore since native bind is
* now more performant in most browsers, but removing it would be breaking for
* code that was able to run in PhantomJS 1.x, so this must be kept for
* backwards compatibility.
* 改变this 上下文
* 执行方式
*/
/* istanbul ignore next */
//绑定事件 并且改变上下文指向
function polyfillBind(fn, ctx) {
function boundFn(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
}
//执行方式
function nativeBind(fn, ctx) {
return fn.bind(ctx)
}
//bing 改变this上下文
var bind = Function.prototype.bind
? nativeBind
: polyfillBind;
/**
* Convert an Array-like object to a real Array.
* 将假的数组转换成真的数组
*/
function toArray(list, start) {
start = start || 0;
var i = list.length - start;
var ret = new Array(i);
while (i--) {
ret[i] = list[i + start];
}
return ret
}
/**
* Mix properties into target object.
* * 浅拷贝
*/
/***********************************************************************************************
*函数名 :extend
*函数功能描述 : 浅拷贝
*函数参数 : to 超类, _from 子类
*函数返回值 : 合并类
*作者 :
*函数创建日期 :
*函数修改日期 :
*修改人 :
*修改原因 :
*版本 :
*历史版本 :
***********************************************************************************************/
//对象浅拷贝,参数(to, _from)循环_from的值,会覆盖掉to的值
function extend(to, _from) {
for (var key in _from) {
to[key] = _from[key];
}
return to
}
/**
* Merge an Array of Objects into a single Object.
*
*/
/***********************************************************************************************
*函数名 :toObject
*函数功能描述 : 和并对象数组合并成一个对象
*函数参数 : arr 数组对象类
*函数返回值 :
*作者 :
*函数创建日期 :
*函数修改日期 :
*修改人 :
*修改原因 :
*版本 :
*历史版本 :
***********************************************************************************************/
function toObject(arr) {
var res = {};
for (var i = 0; i < arr.length; i++) {
if (arr[i]) {
extend(res, arr[i]);
}
}
return res
}
/**
* 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/)
*/
function noop(a, b, c) {
}
/**
* Always return false.
* 返回假的
*/
var no = function (a, b, c) {
return false;
};
/**
* Return same value
*返回相同值
*/
var identity = function (_) {
return _;
};
/**
* Generate a static keys string from compiler modules.
*
* [{ staticKeys:1},{staticKeys:2},{staticKeys:3}]
* 连接数组对象中的 staticKeys key值,连接成一个字符串 str=‘1,2,3’
*/
function genStaticKeys(modules) {
return modules.reduce(
function (keys, m) {
//累加staticKeys的值变成数组
return keys.concat(m.staticKeys || [])
},
[]
).join(',') //转换成字符串
}
/**
* Check if two values are loosely equal - that is,
* if they are plain objects, do they have the same shape?
* 检测a和b的数据类型,是否是不是数组或者对象,对象的key长度一样即可,数组长度一样即可
*/
function looseEqual(a, b) {
if (a === b) {
return true
} //如果a和b是完全相等 则true
var isObjectA = isObject(a);
var isObjectB = isObject(b);
if (isObjectA && isObjectB) { //如果a和都是对象则让下走
try {
var isArrayA = Array.isArray(a);
var isArrayB = Array.isArray(b);
if (isArrayA && isArrayB) { //如果a和b都是数组
// every 条件判断
return a.length === b.length && a.every(function (e, i) { //如果a长度和b长度一样的时候
return looseEqual(e, b[i]) //递归
})
} else if (!isArrayA && !isArrayB) { //或者a和b都不是数组
var keysA = Object.keys(a); // 获取到a的key值 变成一个数组
var keysB = Object.keys(b); // 获取到b的key值 变成一个数组
//他们的对象key值长度是一样的时候 则加载every 条件函数
return keysA.length === keysB.length && keysA.every(function (key) {
//递归 a和b的值
return looseEqual(a[key], b[key])
})
} else {
//如果不是对象跳槽循环
/* istanbul ignore next */
return false
}
} catch (e) {
//如果不是对象跳槽循环
/* istanbul ignore next */
return false
}
} else if (!isObjectA && !isObjectB) { //b和a 都不是对象的时候
//把a和b变成字符串,判断他们是否相同
return String(a) === String(b)
} else {
return false
}
}
// 判断 arr数组中的数组 是否和val相等。
// 或者 arr数组中的对象,或者对象数组 是否和val 相等
function looseIndexOf(arr, val) {
for (var i = 0; i < arr.length; i++) {
if (looseEqual(arr[i], val)) {
return i
}
}
return -1
}
/**
* Ensure a function is called only once.
* 确保该函数只调用一次 闭包函数
*/
function once(fn) {
var called = false;
return function () {
if (!called) {
called = true;
fn.apply(this, arguments);
}
}
}
【Vue】VUE源码中的一些工具函数的更多相关文章
-
Vue.js源码中大量采用的ES6新特性介绍:模块、let、const
1 关于ES6 ECMAScript6(以下简称ES6)是JavaScript语言的最新一代标准,发布于2015年6月,因为ECMA委员会决定从ES6起每年更新一次标准,因此ES6被改名为E ...
-
jQuery源码分析-03扩展工具函数jQuery.extend
// 扩展工具函数 jQuery.extend({ // http://www.w3school.com.cn/jquery/core_noconflict.asp // 释放$的 jQuery 控制 ...
-
解读Vue.use()源码
Vue.use() vue.use()的作用: 官方文档的解释: 安装 Vue.js 插件.如果插件是一个对象,必须提供 install 方法.如果插件是一个函数,它会被作为 install 方法.i ...
-
从template到DOM(Vue.js源码角度看内部运行机制)
写在前面 这篇文章算是对最近写的一系列Vue.js源码的文章(https://github.com/answershuto/learnVue)的总结吧,在阅读源码的过程中也确实受益匪浅,希望自己的这些 ...
-
vue.js使用webpack发布,部署到服务器上之后在浏览器中可以查看到vue文件源码
webpack+vue 2.0打包发布之后,将发布的文件部署到服务器中之后,浏览器中访问的时候会出现一个webpack文件夹,里边会显示vue文件源码 如果不想让vue源文件显示出来,可以在confi ...
-
挖掘隐藏在源码中的Vue技巧!
前言 最近关于Vue的技巧文章大热,我自己也写过一篇(vue开发中的"骚操作"),但这篇文章的技巧是能在Vue的文档中找到蛛丝马迹的,而有些文章说的技巧在Vue文档中根本找不到踪迹 ...
-
2018-11-23 手工翻译Vue.js源码:尝试重命名标识符与文本
续前文: 手工翻译Vue.js源码第一步:14个文件重命名 对core/instance/索引中的变量, 方法进行重命名如下(题图): import { 混入初始化 } from './初始化' im ...
-
2018-11-21 手工翻译Vue.js源码第一步:14个文件重命名
背景 对现有开源项目的代码进行翻译(文件名/命名/注释) · Issue #107 · program-in-chinese/overview 简单地说, 通过翻译源码, 提高项目代码可读性(对于母语 ...
-
Vue.js 源码分析(二十八) 高级应用 transition组件 详解
transition组件可以给任何元素和组件添加进入/离开过渡,但只能给单个组件实行过渡效果(多个元素可以用transition-group组件,下一节再讲),调用该内置组件时,可以传入如下特性: n ...
随机推荐
-
AngularJS常用插件与指令收集
angularjs 组件列表 bindonce UI-Router Angular Tree angular-ngSanitize模块-$sanitize服务详解 使用 AngularJS 开发一个大 ...
-
Android studio 菜单介绍 3.1.文件(File)
文件(File) 3.1.1.New 1. Android Studio中的Project相当于Eclipse中的Workspace 3.1.5.Close Prject 关闭当前项目打开的窗口 2. ...
-
Windows Server 2008配置服务器证书[转载]
备忘 http://wangchunhai.blog.51cto.com/225186/139451
-
linux 学习5 文本编辑器 vim
vim 没有菜单,只有命令 //root用户既可以用vi,也可以用vim, 无实质性区别,vim是vi的升级版//粘贴用shift+insert , 要在insert模式下粘贴,否则粘贴不全// ^ ...
-
关于CSS3线型渐变这些事儿
CSS3兼容各浏览器的线型渐变方法: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
-
20145211 《Java程序设计》第8周学习总结——自在飞花轻似梦
教材学习内容总结 认识NIO Java NIO(New Input/Output)--新的输入/输出API包--是2002年引入到J2SE 1.4里的.Java NIO的目标是提高Java平台上的I/ ...
-
Wireshark抓包工具使用教程以及常用抓包规则
转载:http://fangxin.blog.51cto.com/1125131/735178 Wireshark是一个非常好用的抓包工具,当我们遇到一些和网络相关的问题时,可以通过这个工具进行分析, ...
-
javascript 之闭包-理解不了来找我
1,闭包是什么 (百度百科定义)--闭包是可以包含*(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变 量).“闭包” 一词 ...
-
ArrayList源码浅析(jdk1.8)
ArrayList的实质就是动态数组.所以可以通过下标准确的找到目标元素,因此查找的效率高.但是添加或删除元素会涉及到大量元素的位置移动,所以效率低. 一.构造方法 ArrayList提供了3个构造方 ...
-
mysql中data和datatime的区别
1.显示格式的区别 Date显示格式:YYYY-MM-DD:DateTime显示格式:YYYY-MM-DD HH:mm:ss. 2.显示范围的区别 Date显示范围是1601-01-01 到 9999 ...