大家好,我是若川。歡迎加我微信?ruochuan12,長期交流學習。今天推薦Vuejs源碼中幾個實用的方法。
如果想看Vuejs源碼,不知道如何下手,一般推薦配置Sourcemap,針對單個問題調試來看,如何調試Vuejs源碼,我的vuex源碼文章中寫了。
點擊下方卡片關注我、加個星標,或者查看源碼等系列文章。學習源碼整體架構系列、年度總結、JS基礎系列
話不多說,趕快試試尤大大教給我們的這幾個實用函數吧!在工作中肯定會用得到。
立即執行函數
頁面加載完成后只執行一次的設置函數。
(function?(a,?b)?{console.log(a,?b);?//?1,2
})(1,?2);
通常,全局變量被作為一個參數傳遞給立即執行參數,這樣它在函數內部不使用window也可以被訪問到。
(function?(global)?{console.log(global);?//?Window對象
})(this);
多層嵌套三目運算符
三目運算符嵌套的寫法,使得代碼可讀性差,簡單業務場景下可以試著使用。
var?a?=?1;
var?b?=?0;
a?==?1???(b?==?2???(b?=?3)?:?(b?=?1))?:?"";
console.log(b);?//?1
凍結對象
不可對指定對象增刪改。
var?emptyObject?=?Object.freeze({key:?"1",
});
emptyObject.name?=?"maomin";
delete?emptyObject.key;
emptyObject.key?=?"2";
console.log(emptyObject);
密封對象
只能對指定對象進行更改,不可進行增加刪除操作。
var?sealObject?=?Object.seal({key:?3,
});
sealObject.name?=?"maomin";
delete?sealObject.key;
sealObject.key?=?4;
console.log(sealObject);?//?4
檢查是否是原始值
function?isPrimitive(value)?{return?(typeof?value?===?"string"?||typeof?value?===?"number"?||//?$flow-disable-linetypeof?value?===?"symbol"?||typeof?value?===?"boolean");
}
快速檢測是否是對象
當我們知道原始值時,它主要用于將對象與原始值區分開來。
function?isObject(obj)?{return?obj?!==?null?&&?typeof?obj?===?"object";
}
console.log(isObject(true));?//false
檢測目標類型
var?_toString?=?Object.prototype.toString;function?toRawType(value)?{return?_toString.call(value).slice(8,?-1);
}
console.log(toRawType([]));?//?Array
檢查目標是否是有效的數組索引
function?isValidArrayIndex(val)?{var?n?=?parseFloat(String(val));return?n?>=?0?&&?Math.floor(n)?===?n?&&?isFinite(val);
}
檢測是否是Promise對象
function?isDef(v)?{return?v?!==?undefined?&&?v?!==?null;
}
function?isPromise(val)?{return?(isDef(val)?&&typeof?val.then?===?"function"?&&typeof?val.catch?===?"function");
}
var?promiseObj?=?new?Promise(function?(resolve,?reject)?{//?一段耗時的異步操作resolve("成功");?//?數據處理完成//?reject('失敗')?//?數據處理出錯
}).then((res)?=>?{console.log(res);},?//?成功(err)?=>?{console.log(err);}?//?失敗
);
console.log(isPromise(promiseObj));?//?true
目標轉換為字符串
var?_toString?=?Object.prototype.toString;
function?isPlainObject(obj)?{return?_toString.call(obj)?===?"[object?Object]";
}
function?toString(val)?{return?val?==?null??"":?Array.isArray(val)?||?(isPlainObject(val)?&&?val.toString?===?_toString)??JSON.stringify(val,?null,?2):?String(val);
}
console.log(toString({?name:?1?}));?//?{"name":?1}
轉化為數字
將輸入值轉換為數字以便持久化。如果轉換失敗,則返回原始字符串。
function?toNumber(val)?{var?n?=?parseFloat(val);return?isNaN(n)???val?:?n;
}
檢測key是否在創建的Map對象內
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);
console.log(isBuiltInTag("component"));?//?true
刪除簡單數組中某一項
function?remove(arr,?item)?{if?(arr.length)?{var?index?=?arr.indexOf(item);if?(index?>?-1)?{return?arr.splice(index,?1);}}
}
console.log(remove([1,?2],?1));?//?[1]
檢測對象中是否有指定key
var?hasOwnProperty?=?Object.prototype.hasOwnProperty;
function?hasOwn(obj,?key)?{return?hasOwnProperty.call(obj,?key);
}
console.log(hasOwn({?name:?1?},?"name"));?//true
將類數組對象轉化為真實數組
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;
}
console.log(toArray({?0:?42,?1:?52,?2:?63,?length:?3?}));?//?[42,?52,?63]
將屬性混合到目標對象中
function?extend(to,?_from)?{for?(var?key?in?_from)?{to[key]?=?_from[key];}return?to;
}
console.log(extend({?name:?1?},?{?name1:?2?}));?//?{name:1,name1:2}
將對象數組合并為單個對象
function?extend(to,?_from)?{for?(var?key?in?_from)?{to[key]?=?_from[key];}return?to;
}
function?toObject(arr)?{var?res?=?{};for?(var?i?=?0;?i?<?arr.length;?i++)?{if?(arr[i])?{extend(res,?arr[i]);}}return?res;
}
console.log(toObject([{?name:?1?},?{?name:?1?},?{?name:?2?},?{?name1:?3?}]));?//?{name:?2,?name1:?3}
檢測指定項在數組(簡單數組、數組對象)中的索引
function?isObject(obj)?{return?obj?!==?null?&&?typeof?obj?===?"object";
}
function?looseEqual(a,?b)?{if?(a?===?b)?{return?true;}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)?{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;
}
console.log(looseIndexOf([{?name:?1?},?{?name:?2?}],?4));?//?-1
console.log(looseIndexOf([{?name:?1?},?{?name:?2?}],?{?name:?1?}));?//?0
確保函數只調用一次
function?once(fn)?{var?called?=?false;return?function?()?{if?(!called)?{called?=?true;fn.apply(this,?arguments);}};
}
var?callOnce?=?once(function?()?{console.log("javascript");
});
callOnce();?//?javascript
callOnce();
定義對象屬性
如果你想禁止一個對象添加新屬性并且保留已有屬性,就可以使用Object.preventExtensions(obj)。
function?def(obj,?key,?val,?enumerable)?{Object.defineProperty(obj,?key,?{value:?val,?//?對象定義屬性enumerable:?!!enumerable,?//?描述屬性是否會出現在for?in?或者?Object.keys()的遍歷中writable:?true,?//?是否可寫configurable:?true,?//?是否重新定義或者刪除});
}
var?obj?=?{name:?1,
};
def(obj,?"name1",?2,?true);
obj.name1?=?3;
console.log(obj);?//?{name:?1,?name1:?3}
瀏覽器環境嗅探
var?inBrowser?=?typeof?window?!==?"undefined";
var?inWeex?=?typeof?WXEnvironment?!==?"undefined"?&&?!!WXEnvironment.platform;
var?weexPlatform?=?inWeex?&&?WXEnvironment.platform.toLowerCase();
var?UA?=?inBrowser?&&?window.navigator.userAgent.toLowerCase();var?isIE?=?UA?&&?/msie|trident/.test(UA);
var?isIE9?=?UA?&&?UA.indexOf("msie?9.0")?>?0;
var?isEdge?=?UA?&&?UA.indexOf("edge/")?>?0;
var?isAndroid?=?(UA?&&?UA.indexOf("android")?>?0)?||?weexPlatform?===?"android";
var?isIOS?=?(UA?&&?/iphone|ipad|ipod|ios/.test(UA))?||?weexPlatform?===?"ios";
var?isChrome?=?UA?&&?/chrome\/\d+/.test(UA)?&&?!isEdge;
var?isPhantomJS?=?UA?&&?/phantomjs/.test(UA);
var?isFF?=?UA?&&?UA.match(/firefox\/(\d+)/);
JS構造函數內的方法與構造函數prototype屬性上方法的對比
定義在構造函數內部的方法,會在它的每一個實例上都克隆這個方法;定義在構造函數的 prototype 屬性上的方法會讓它的所有示例都共享這個方法,但是不會在每個實例的內部重新定義這個方法。如果我們的應用需要創建很多新的對象,并且這些對象還有許多的方法,為了節省內存,我們建議把這些方法都定義在構造函數的 prototype 屬性上。當然,在某些情況下,我們需要將某些方法定義在構造函數中,這種情況一般是因為我們需要訪問構造函數內部的私有變量。
function?A()?{this.say?=?function?()?{console.log(1);};
}
var?a?=?new?A();
a.say();
function?B()?{}
B.prototype.say?=?function?()?{console.log(2);
};
var?b?=?new?B();
b.say();
var?c?=?new?B();
c.say();
獲取標簽內容(包含標簽)
function?getOuterHTML(el)?{if?(el.outerHTML)?{return?el.outerHTML;}?else?{var?container?=?document.createElement("div");container.appendChild(el.cloneNode(true));return?container.innerHTML;}
}
字符串hash值
function?hash(str)?{var?hash?=?5381;var?i?=?str.length;while?(i)?{hash?=?(hash?*?33)?^?str.charCodeAt(--i);}return?hash?>>>?0;
}
console.log(hash("222sd"));//?164533792
最近組建了一個江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你進群。
·················?若川出品?·················
今日話題
有時候付費學習,真的是能節省很多時間,時間也是資源,也是金錢。視頻學習和書籍學習都是很好的學習方式,相輔相成,當然,符合自己學習方式才是最重要的。書籍出版一般要經過嚴格審核流程,網上視頻的質量參差不齊。歡迎分享、收藏、點贊、在看我的公眾號文章~
一個愿景是幫助5年內前端人走向前列的公眾號
可加我個人微信 ruochuan12,長期交流學習
推薦閱讀
我在阿里招前端,我該怎么幫你?(現在還能加我進模擬面試群)
如何拿下阿里巴巴 P6 的前端 Offer
點擊上方卡片關注我、加個星標,或者查看源碼等系列文章。
學習源碼整體架構系列、年度總結、JS基礎系列