聊聊從Vue.js源碼中我學(xué)到了精妙方法
話不多說(shuō),趕快試試尤大大教給我們的這幾個(gè)精妙方法吧!在工作中肯定會(huì)用得到。
立即執(zhí)行函數(shù)
頁(yè)面加載完成后只執(zhí)行一次的設(shè)置函數(shù)。
- (function (a, b) {
- console.log(a, b); // 1,2
- })(1, 2);
通常,全局變量被作為一個(gè)參數(shù)傳遞給立即執(zhí)行參數(shù),這樣它在函數(shù)內(nèi)部不使用window也可以被訪問(wèn)到。
- (function (global) {
- console.log(global); // Window對(duì)象
- })(this);
多層嵌套三目運(yùn)算符
三目運(yùn)算符嵌套的寫(xiě)法,使得代碼可讀性差,簡(jiǎn)單業(yè)務(wù)場(chǎng)景下可以試著使用。
- var a = 1;
- var b = 0;
- a == 1 ? (b == 2 ? (b = 3) : (b = 1)) : "";
- console.log(b); // 1
凍結(jié)對(duì)象
不可對(duì)指定對(duì)象增刪改。
- var emptyObject = Object.freeze({
- key: "1",
- });
- emptyObject.name = "maomin";
- delete emptyObject.key;
- emptyObject.key = "2";
- console.log(emptyObject);
密封對(duì)象
只能對(duì)指定對(duì)象進(jìn)行更改,不可進(jìn)行增加刪除操作。
- 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-line
- typeof value === "symbol" ||
- typeof value === "boolean"
- );
- }
快速檢測(cè)是否是對(duì)象
當(dāng)我們知道原始值時(shí),它主要用于將對(duì)象與原始值區(qū)分開(kāi)來(lái)。
- function isObject(obj) {
- return obj !== null && typeof obj === "object";
- }
- console.log(isObject(true)); //false
檢測(cè)目標(biāo)類(lèi)型
- var _toString = Object.prototype.toString;
- function toRawType(value) {
- return _toString.call(value).slice(8, -1);
- }
- console.log(toRawType([])); // Array
檢查目標(biāo)是否是有效的數(shù)組索引
- function isValidArrayIndex(val) {
- var n = parseFloat(String(val));
- return n >= 0 && Math.floor(n) === n && isFinite(val);
- }
檢測(cè)是否是Promise對(duì)象
- 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) {
- // 一段耗時(shí)的異步操作
- resolve("成功"); // 數(shù)據(jù)處理完成
- // reject('失敗') // 數(shù)據(jù)處理出錯(cuò)
- }).then(
- (res) => {
- console.log(res);
- }, // 成功
- (err) => {
- console.log(err);
- } // 失敗
- );
- console.log(isPromise(promiseObj)); // true
目標(biāo)轉(zhuǎn)換為字符串
- 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}
轉(zhuǎn)化為數(shù)字
將輸入值轉(zhuǎn)換為數(shù)字以便持久化。如果轉(zhuǎn)換失敗,則返回原始字符串。
- function toNumber(val) {
- var n = parseFloat(val);
- return isNaN(n) ? val : n;
- }
檢測(cè)key是否在創(chuàng)建的Map對(duì)象內(nèi)
- 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
刪除簡(jiǎn)單數(shù)組中某一項(xiàng)
- 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]
檢測(cè)對(duì)象中是否有指定key
- var hasOwnProperty = Object.prototype.hasOwnProperty;
- function hasOwn(obj, key) {
- return hasOwnProperty.call(obj, key);
- }
- console.log(hasOwn({ name: 1 }, "name")); //true
將類(lèi)數(shù)組對(duì)象轉(zhuǎn)化為真實(shí)數(shù)組
- 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]
將屬性混合到目標(biāo)對(duì)象中
- 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}
將對(duì)象數(shù)組合并為單個(gè)對(duì)象
- 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}
檢測(cè)指定項(xiàng)在數(shù)組(簡(jiǎn)單數(shù)組、數(shù)組對(duì)象)中的索引
- 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
確保函數(shù)只調(diào)用一次
- 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();
定義對(duì)象屬性
如果你想禁止一個(gè)對(duì)象添加新屬性并且保留已有屬性,就可以使用Object.preventExtensions(obj)。
- function def(obj, key, val, enumerable) {
- Object.defineProperty(obj, key, {
- value: val, // 對(duì)象定義屬性
- enumerable: !!enumerable, // 描述屬性是否會(huì)出現(xiàn)在for in 或者 Object.keys()的遍歷中
- writable: true, // 是否可寫(xiě)
- configurable: true, // 是否重新定義或者刪除
- });
- }
- var obj = {
- name: 1,
- };
- def(obj, "name1", 2, true);
- obj.name1 = 3;
- console.log(obj); // {name: 1, name1: 3}
瀏覽器環(huán)境嗅探
- 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構(gòu)造函數(shù)內(nèi)的方法與構(gòu)造函數(shù)prototype屬性上方法的對(duì)比
定義在構(gòu)造函數(shù)內(nèi)部的方法,會(huì)在它的每一個(gè)實(shí)例上都克隆這個(gè)方法;定義在構(gòu)造函數(shù)的 prototype 屬性上的方法會(huì)讓它的所有示例都共享這個(gè)方法,但是不會(huì)在每個(gè)實(shí)例的內(nèi)部重新定義這個(gè)方法。如果我們的應(yīng)用需要?jiǎng)?chuàng)建很多新的對(duì)象,并且這些對(duì)象還有許多的方法,為了節(jié)省內(nèi)存,我們建議把這些方法都定義在構(gòu)造函數(shù)的 prototype 屬性上。當(dāng)然,在某些情況下,我們需要將某些方法定義在構(gòu)造函數(shù)中,這種情況一般是因?yàn)槲覀冃枰L問(wèn)構(gòu)造函數(shù)內(nèi)部的私有變量。
- 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();
獲取標(biāo)簽內(nèi)容(包含標(biāo)簽)
- 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