(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對象。不污染全局變量,也不會別的代碼污染es6
var emptyObject = Object.freeze({});數組
字面上意義:空對象=凍結掉這個對象瀏覽器
Object.freeze({})這個方法核心在於對於這個對象將沒法修改,添加。
function isUndef (v) {return v === undefined || v === null}babel
是否未被定義,若是參數等於undefined或者爲空,返回true
function isDef (v) {return v !== undefined && v !== null}閉包
是否認義,若是參數不等於undefined或者爲空,返回true
function isTrue (v) {return v === true}app
是否真,參數爲真是返回true
function isFalse (v) {return v === false}ide
是否假,參數爲真是返回true
function isPrimitive (value) { return ( typeof value === 'string' || typeof value === 'number' || // $flow-disable-line typeof value === 'symbol' || typeof value === 'boolean' ) }
是否爲原始類型,typeof 返回
function isObject (obj) {return obj !== null && typeof obj === 'object'}函數
是否爲對象,若是對象不等於空且typeof返回爲object,返回true
var _toString = Object.prototype.toString;oop
該方法返回描述某個對象數據類型的字符串,如自定義的對象沒有被覆蓋,則會返回「[object type]」,其中,type則是實際的對象類型。在使用該方法檢測的時候,可使用Object.prototype.toString.call()或者Object.prototype.toString.apply()進行測試,如
function toRawType (value) {return _toString.call(value).slice(8, -1)}性能
slice(startIndex,endIndex),從0開始索引,其中8表明從第8位(包含)開始截取(本例中表明空格後面的位置),-1表明截取到倒數第一位(不含),因此正好截取到[object String]中的String。
function isPlainObject (obj) {return _toString.call(obj) === '[object Object]'}
isPlainObject 靜態函數 判斷指定參數是不是一個純粹的對象
function isRegExp (v) {return _toString.call(v) === '[object RegExp]'}
判斷指定參數是不是一個正則
function isValidArrayIndex (val) { var n = parseFloat(String(val)); return n >= 0 && Math.floor(n) === n && isFinite(val) }
是否爲一個有效的數組,現將值轉爲字符串,而後用parseFloat解析,字符串中的首個字符是不是數字。若是是,則對字符串進行解析,直到到達數字的末端爲止,而後以數字返回該數字,而不是做爲字符串。
若是n>=0以及向下取整等於n以及isFinite是一個有限數。如1/0
function isPromise (val) { return ( isDef(val) && typeof val.then === 'function' && typeof val.catch === 'function' ) }
首先檢測這個值是否被定義,而後判斷它的then和catch是否爲一個函數
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個參數,
不然將val轉成字符串
function toNumber (val) { var n = parseFloat(val); return isNaN(n) ? val : n }
先使用parseFloat函數轉換值,而後isNaN檢查是否爲一個數值,若是是輸出val,不然輸出parseFloat(val)基本也就輸出NaN了
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');
官方解釋:製做一個映射並返回一個函數,用於檢查鍵是否在該映射中。
建立一個空的對象複製給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) } } }
從數組中移除
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有多少類型啊,記得多了一個。
hasOwn這個函數主要是檢測當前對象是否有某種屬性。
這個地方還能夠作一些衍生
若是你想要實現支持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() });
註釋寫着將字符串駝峯化
匹配一個-組成單詞的字符
調用前面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,
例如,Phantomjs 1.x。從技術上講,咱們再也不須要這個了。
由於在大多數瀏覽器中,本機綁定的性能已經足夠了。
可是刪除它意味着破壞可以運行的代碼
PhantomJS 1.x,因此爲了向後兼容,必須保留它。
function nativeBind (fn, ctx) { return fn.bind(ctx) } var bind = Function.prototype.bind ? nativeBind : polyfillBind;
原生的bind。以及斷定這個bind是原生的仍是polyfill
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上。
function extend (to, _from) { for (var key in _from) { to[key] = _from[key]; } return to }
檢查有多少個屬性,而後賦值返回到to上
function toObject (arr) { var res = {}; for (var i = 0; i < arr.length; i++) { if (arr[i]) { extend(res, arr[i]); } } return res }
定義了一個res對象
遍歷傳遞的arr數組。而後經過上面那個extend函數傳遞到res
function noop (a, b, c) {}
一個空函數?。。。不知道幹啥。往下再看看
var no = function (a, b, c) { return false; };
一個no??綁定了一個函數返回false?再看看
var identity = function (_) { return _; };
一個傳什麼返回本身的東西?
function genStaticKeys (modules) { return modules.reduce(function (keys, m) { return keys.concat(m.staticKeys || []) }, []).join(',') }
從編譯器模塊生成包含靜態鍵的字符串
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 } }
這一段有點長,我看下注釋打在代碼裏.做用判斷兩個值是否相等。結構是否相同
function looseIndexOf (arr, val) { for (var i = 0; i < arr.length; i++) { if (looseEqual(arr[i], val)) { return i } } return -1 }
返回索引,若是沒找到-1,不然用上面的looseEqual()函數
function once (fn) { var called = false; return function () { if (!called) { called = true; fn.apply(this, arguments); } } }
一個閉包函數,只有在called = false時執行,若是調用事後,返回true。只能用一次。