Vue.js源碼中的幾個精妙方法
話不多說,趕快試試尤大大教給我們的這幾個精妙方法吧!在工作中肯定會用得到。
立即執(zhí)行函數(shù)
頁面加載完成后只執(zhí)行一次的設(shè)置函數(shù)。
(function?(a,?b)?{
??console.log(a,?b);?//?1,2
})(1,?2);
通常,全局變量被作為一個參數(shù)傳遞給立即執(zhí)行參數(shù),這樣它在函數(shù)內(nèi)部不使用window也可以被訪問到。
(function?(global)?{
??console.log(global);?//?Window對象
})(this);
多層嵌套三目運(yùn)算符
三目運(yùn)算符嵌套的寫法,使得代碼可讀性差,簡單業(yè)務(wù)場景下可以試著使用。
var?a?=?1;
var?b?=?0;
a?==?1???(b?==?2???(b?=?3)?:?(b?=?1))?:?"";
console.log(b);?//?1
凍結(jié)對象
不可對指定對象增刪改。
var?emptyObject?=?Object.freeze({
??key:?"1",
});
emptyObject.name?=?"maomin";
delete?emptyObject.key;
emptyObject.key?=?"2";
console.log(emptyObject);
密封對象
只能對指定對象進(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"
??);
}
快速檢測是否是對象
當(dāng)我們知道原始值時,它主要用于將對象與原始值區(qū)分開來。
function?isObject(obj)?{
??return?obj?!==?null?&&?typeof?obj?===?"object";
}
console.log(isObject(true));?//false
檢測目標(biāo)類型
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);
}
檢測是否是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("成功");?//?數(shù)據(jù)處理完成
??//?reject('失敗')?//?數(shù)據(jù)處理出錯
}).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;
}
檢測key是否在創(chuàng)建的Map對象內(nèi)
function?makeMap(str,?expectsLowerCase)?{
??var?map?=?Object.create(null);
??var?list?=?str.split(",");
??for?(var?i?=?0;?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
刪除簡單數(shù)組中某一項
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
將類數(shù)組對象轉(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)對象中
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}
將對象數(shù)組合并為單個對象
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?????if?(arr[i])?{
??????extend(res,?arr[i]);
????}
??}
??return?res;
}
console.log(toObject([{?name:?1?},?{?name:?1?},?{?name:?2?},?{?name1:?3?}]));?//?{name:?2,?name1:?3}
檢測指定項在數(shù)組(簡單數(shù)組、數(shù)組對象)中的索引
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?????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();
定義對象屬性
如果你想禁止一個對象添加新屬性并且保留已有屬性,就可以使用Object.preventExtensions(obj)。
function?def(obj,?key,?val,?enumerable)?{
??Object.defineProperty(obj,?key,?{
????value:?val,?//?對象定義屬性
????enumerable:?!!enumerable,?//?描述屬性是否會出現(xiàn)在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}
瀏覽器環(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屬性上方法的對比
定義在構(gòu)造函數(shù)內(nèi)部的方法,會在它的每一個實(shí)例上都克隆這個方法;定義在構(gòu)造函數(shù)的 prototype 屬性上的方法會讓它的所有示例都共享這個方法,但是不會在每個實(shí)例的內(nèi)部重新定義這個方法。如果我們的應(yīng)用需要創(chuàng)建很多新的對象,并且這些對象還有許多的方法,為了節(jié)省內(nèi)存,我們建議把這些方法都定義在構(gòu)造函數(shù)的 prototype 屬性上。當(dāng)然,在某些情況下,我們需要將某些方法定義在構(gòu)造函數(shù)中,這種情況一般是因?yàn)槲覀冃枰L問構(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評論
圖片
表情
