摘要:创建一个自调用匿名函数,设计参数,并传入对象。表示独一无二的值声明时不能使用,而是声明时可以加参数,用于描述作为时不能被遍历这个函数主要是检测当前对象是否有某种属性。给变量赋值一个空的对象返回一个的函数,将函数的参数的带入并赋值,返回。
VUE 2.6.8
(function (global, factory) { typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (global = global || self, global.Vue = factory()); }(this, function () { "use strict";
创建一个自调用匿名函数,设计参数window,并传入window对象。不污染全局变量,也不会别的代码污染
emptyObjectvar emptyObject = Object.freeze({});
字面上意义:空对象=冻结掉这个对象
Object.freeze({})这个方法核心在于对于这个对象将无法修改,添加。isUndef
function isUndef (v) {return v === undefined || v === null}
是否未被定义,如果参数等于undefined或者为空,返回trueisDef
function isDef (v) {return v !== undefined && v !== null}
是否定义,如果参数不等于undefined或者为空,返回trueisTrue
function isTrue (v) {return v === true}
是否真,参数为真是返回trueisFalse
function isFalse (v) {return v === false}
是否假,参数为真是返回true
function isPrimitive (value) { return ( typeof value === "string" || typeof value === "number" || // $flow-disable-line typeof value === "symbol" || typeof value === "boolean" ) }
是否为原始类型,typeof 返回isObject
function isObject (obj) {return obj !== null && typeof obj === "object"}
是否为对象,如果对象不等于空且typeof返回为object,返回true_toString
var _toString = Object.prototype.toString;
该方法返回描述某个对象数据类型的字符串,如自定义的对象没有被覆盖,则会返回“[object type]”,其中,type则是实际的对象类型。在使用该方法检测的时候,可以使用Object.prototype.toString.call()或者Object.prototype.toString.apply()进行测试,如toRawType
function toRawType (value) {return _toString.call(value).slice(8, -1)}
slice(startIndex,endIndex),从0开始索引,其中8代表从第8位(包含)开始截取(本例中代表空格后面的位置),-1代表截取到倒数第一位(不含),所以正好截取到[object String]中的String。isPlainObject
function isPlainObject (obj) {return _toString.call(obj) === "[object Object]"}
isPlainObject 静态函数 判断指定参数是否是一个纯粹的对象isRegExp
function isRegExp (v) {return _toString.call(v) === "[object RegExp]"}
判断指定参数是否是一个正则isValidArrayIndex
function isValidArrayIndex (val) { var n = parseFloat(String(val)); return n >= 0 && Math.floor(n) === n && isFinite(val) }
是否为一个有效的数组,现将值转为字符串,然后用parseFloat解析,字符串中的首个字符是否是数字。如果是,则对字符串进行解析,直到到达数字的末端为止,然后以数字返回该数字,而不是作为字符串。isPromise
如果n>=0以及向下取整等于n以及isFinite是一个有限数。如1/0
function isPromise (val) { return ( isDef(val) && typeof val.then === "function" && typeof val.catch === "function" ) }
首先检测这个值是否被定义,然后判断它的then和catch是否为一个函数toString
function toString (val) { return val == null ? "" : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) ? JSON.stringify(val, null, 2) : String(val) }
首先判断val是否为空,如果为空输出""否则
Array.isArray() 先确定是否值为一个Array
或者前面的isPlainObject方法判定是否为一个对象
和值转成字符串是否等于Object.prototype.toString返回该对象的字符串;
如果条件满足JSON.stringify(val, null, 2)stringify是有3个参数,
第一个,参数是传入的值可以是String|Object|String|Number|Boolean|null
第二个,则是过滤器,过滤器可以是数组,也可以是函数
第三个,可以是空的格子(4)也可以是特殊符号/t
否则将val转成字符串toNumber
function toNumber (val) { var n = parseFloat(val); return isNaN(n) ? val : n }
先使用parseFloat函数转换值,然后isNaN检查是否为一个数值,如果是输出val,否则输出parseFloat(val)基本也就输出NaN了makeMap
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; } 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");
remove官方解释:制作一个映射并返回一个函数,用于检查键是否在该映射中。
创建一个空的对象复制给map
将值根据‘,’分割成字符串数组
遍历循环检测这个数组
如果expectsLowerCase有值且为true,将map中的数组转换为小写,否则直接输出map中的值实际上主要就是检查map中是否存在某个key
检查标记是否为内置标记
检查属性是否为保留属性
function remove (arr, item) { if (arr.length) { var index = arr.indexOf(item); if (index > -1) { return arr.splice(index, 1) } } }
hasOwnProperty从数组中移除
indexOf获取数组中参数的位置
如果index > -1 存在,删除当前
.splice(index,howmany,item1,.....,itemX)补充,index为位置,howmany为删除数量如果为0不删除,这2个参数为必填。第三个则是向数组中添加
var hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwn (obj, key) { return hasOwnProperty.call(obj, key) }
这个是很有意思的案例
首先hasOwnProperty();这个方法,它的参数很有意思,字符串或者Symbol。然后返回true或false
Symbol是es6一种新的类型,所以有的时候问js有多少类型啊,记得多了一个。
表示独一无二的值;
声明时不能使用new Symbol(),而是 Symbol();
声明时可以加参数,用于描述;
作为key时不能被遍历;
cachedhasOwn这个函数主要是检测当前对象是否有某种属性。
这个地方还可以做一些衍生
如果你想要实现支持setter和getter特性的拷贝,该怎么实现?Object.defineproperties (定义属性)
Object.getOwnPropertyDescriptors(es2017,获取对象的多个属性)
Object.getOwnPropertyDescriptor(老一点,获取对象的单个属性的属性),但babel可以解决。
function cached (fn) { var cache = Object.create(null); return (function cachedFn (str) { var hit = cache[str]; return hit || (cache[str] = fn(str)) }) }
给变量cache赋值一个空的对象驼峰化
返回一个cacheFn的函数,将函数的参数的key带入cache并赋值,返回hit。
如果cache中存在str那么返回hit,反之将其赋值到cache中返回
var camelizeRE = /-(w)/g; var camelize = cached(function (str) { return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ""; }) }); var hyphenateRE = /B([A-Z])/g; var hyphenate = cached(function (str) { return str.replace(hyphenateRE, "-$1").toLowerCase() });
polyfillBind注释写着将字符串驼峰化
匹配一个-组成单词的字符
调用前面cached函数,并将字符串replace(egexp/substr,replacement)中做一个判断里面的函数 c这个参数理解不清楚。
补充_是占位符,c是组1思考:.substring(0,1).toUpperCase()不知道是否可以这样写。或者直接用字符串型数组?.toUpperCase()
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 }
获取boundFn中的arguments的长度
if(l){ if(l>1){ fn.apply(ctx, arguments) }else{ fn.call(ctx, a) } }else{ fn.call(ctx) }
如果参数不存在,直接绑定作用域调用该函数fn.call(ctx)
如果存在且只有一个,那么调用fn.call(ctx, a), a是入参
如果存在且不止一个,那么调用fn.apply(ctx, arguments)call与apply的区别,call接受参数是一个一个接收,apply是作为数组来接收。如:
fn.call(this, 1,2,3) fn.apply(this, [1,2,3])
对于不支持它的环境,使用简单的绑定polyfill,nativeBind
例如,Phantomjs 1.x。从技术上讲,我们不再需要这个了。
因为在大多数浏览器中,本机绑定的性能已经足够了。
但是删除它意味着破坏能够运行的代码
PhantomJS 1.x,所以为了向后兼容,必须保留它。
function nativeBind (fn, ctx) { return fn.bind(ctx) } var bind = Function.prototype.bind ? nativeBind : polyfillBind;
原生的bind。以及判定这个bind是原生的还是polyfilltoArray
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 }
数据转换。感觉就是遍历循环一个个存储到一个新的ret上。extend
function extend (to, _from) { for (var key in _from) { to[key] = _from[key]; } return to }
检查有多少个属性,然后赋值返回到to上toObject
function toObject (arr) { var res = {}; for (var i = 0; i < arr.length; i++) { if (arr[i]) { extend(res, arr[i]); } } return res }
定义了一个res对象noop
遍历传递的arr数组。然后通过上面那个extend函数传递到res
function noop (a, b, c) {}
一个空函数?。。。不知道干啥。往下再看看no
var no = function (a, b, c) { return false; };
一个no??绑定了一个函数返回false?再看看identity
var identity = function (_) { return _; };
一个传什么返回自己的东西?genStaticKeys
function genStaticKeys (modules) { return modules.reduce(function (keys, m) { return keys.concat(m.staticKeys || []) }, []).join(",") }
从编译器模块生成包含静态键的字符串looseEqual(未完待续)
function looseEqual (a, b) { if (a === b) { return true } //如果:参数a和参数b恒等于返回true; //isObject这个函数已经看到过了,不为空且恒等于object var isObjectA = isObject(a); var isObjectB = isObject(b); if (isObjectA && isObjectB) { //判定a和b是否满足 try { var isArrayA = Array.isArray(a); var isArrayB = Array.isArray(b); //a和b是否为一个数组 if (isArrayA && isArrayB) { //如果如果满足,检测a是否满足条件 //补充every()函数 e是当前元素值,索引 //array.every(function(currentValue,index,arr), thisValue) return a.length === b.length && a.every(function (e, i) { return looseEqual(e, b[i]) }) } else if (a instanceof Date && b instanceof Date) { return a.getTime() === b.getTime() } else if (!isArrayA && !isArrayB) { var keysA = Object.keys(a); var keysB = Object.keys(b); return keysA.length === keysB.length && keysA.every(function (key) { return looseEqual(a[key], b[key]) }) } else { /* istanbul ignore next */ return false } } catch (e) { /* istanbul ignore next */ return false } } else if (!isObjectA && !isObjectB) { return String(a) === String(b) } else { return false } }
这一段有点长,我看下注释打在代码里.作用判断两个值是否相等。结构是否相同looseIndexOf
function looseIndexOf (arr, val) { for (var i = 0; i < arr.length; i++) { if (looseEqual(arr[i], val)) { return i } } return -1 }
返回索引,如果没找到-1,否则用上面的looseEqual()函数once
function once (fn) { var called = false; return function () { if (!called) { called = true; fn.apply(this, arguments); } } }
一个闭包函数,只有在called = false时执行,如果调用过后,返回true。只能用一次。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/102451.html
摘要:源码目录结构打包相关的配置文件,其中最重要的是。主要是根据不同的入口,打包为不同的文件。这个目录下的代码逻辑会把文件内容解析成一个的对象。 源码目录结构 VUE 2.6.10 ├── scripts # 打包相关的配置文件,其中最重要的是config.js。主要是根据不同的入口,打 包为不同的文件。 ├── dist # 打包之后文...
摘要:运行时用来创建实例渲染并处理虚拟等的代码。基本上就是除去编译器的其它一切。版本可以通过标签直接用在浏览器中。为这些打包工具提供的默认文件是只有运行时的构建。为浏览器提供的用于在现代浏览器中通过直接导入。 Vue版本:2.6.9 源码结构图 ├─ .circleci // 包含CircleCI持续集成/持续部署工具的配置文件 ├─ .github ...
摘要:运行时用来创建实例渲染并处理虚拟等的代码。基本上就是除去编译器的其它一切。版本可以通过标签直接用在浏览器中。为这些打包工具提供的默认文件是只有运行时的构建。为浏览器提供的用于在现代浏览器中通过直接导入。 Vue版本:2.6.9 源码结构图 ├─ .circleci // 包含CircleCI持续集成/持续部署工具的配置文件 ├─ .github ...
摘要:运行时用来创建实例渲染并处理虚拟等的代码。基本上就是除去编译器的其它一切。版本可以通过标签直接用在浏览器中。为这些打包工具提供的默认文件是只有运行时的构建。为浏览器提供的用于在现代浏览器中通过直接导入。 Vue版本:2.6.9 源码结构图 ├─ .circleci // 包含CircleCI持续集成/持续部署工具的配置文件 ├─ .github ...
阅读 611·2021-11-25 09:43
阅读 1612·2021-11-18 10:02
阅读 987·2021-10-15 09:39
阅读 1849·2021-10-12 10:18
阅读 2086·2021-09-22 15:43
阅读 717·2021-09-22 15:10
阅读 2056·2019-08-30 15:53
阅读 913·2019-08-30 13:00