"不畏懼,不講究,將來的日子好好努力"——你們好!我是小芝麻😄javascript
標題黨,它又、又、又來了......css
這篇文章是集合了小芝麻以前全部寫過和沒寫過的API的彙總,爲後面總體複習作準備,若是你也恰好須要,那就跟小芝麻一塊兒來複習吧😄 ;前端
(proto => {
function myCall(thisArg, ...args) {
thisArg = thisArg == undefined ? window : thisArg;
let type = typeof thisArg;
if (!/^(object|function)$/.test(type)) {
if (/^(symbol|bigint)$/.test(type)) {
thisArg = Object(thisArg);
} else {
thisArg = new thisArg.constructor(thisArg);
}
}
let key = Symbol('key');
thisArg[key] = this;
let result = thisArg[key](...args);
delete thisArg[key];
return result;
}
proto.myCall = myCall;
})(Function.prototype)
複製代碼
(proto => {
function myApply(thisArg, args) {
thisArg = thisArg == undefined ? window : thisArg;
let type = typeof thisArg;
if (!/^(object|function)$/.test(type)) {
if (/^(symbol|bigint)$/.test(type)) {
thisArg = Object(thisArg);
} else {
thisArg = new thisArg.constructor(thisArg);
}
}
let key = Symbol('key');
thisArg[key] = this;
let result = thisArg[key](args);
delete thisArg[key];
return result;
}
proto.myApply = myApply;
})(Function.prototype)
複製代碼
(proto => {
function myBind(thisArg, ...args) {
let _this = this;
thisArg = thisArg == undefined ? window : thisArg;
let type = typeof thisArg;
if (!/^(object|function)$/.test(type)) {
if (/^(symbol|bigint)$/.test(type)) {
thisArg = Object(thisArg);
} else {
thisArg = new thisArg.constructor(thisArg);
}
}
return function an(...innerArgs) {
_this.call(thisArg, ...args.concat(innerArgs));
}
}
proto.myBind = myBind;
})(Function.prototype)
複製代碼
function Dog(name) {
this.name = name;
}
Dog.prototype.bark = function () {
console.log('wangwang');
}
Dog.prototype.sayName = function () {
console.log('my name is ' + this.name);
}
//==========重寫開始
function _new(Func, ...args) {
let obj = Object.create(Func.prototype);
let result = Func.call(obj, ...args);
if (result !== null && /^(object|function)$/.test(typeof result)) return result;
return obj;
}
//==========重寫結束
let sanmao = _new(Dog, '三毛');
sanmao.bark(); //=>"wangwang"
sanmao.sayName(); //=>"my name is 三毛"
console.log(sanmao instanceof Dog); //=>true
複製代碼
debounce:函數防抖不是完成某個事件就去執行某函數,而是在某個間隔時間內只執行一次,避免函數的過多執行java
let debounce = function (func, wait, immediate) {
//=>result用來存儲函數執行返回的結果
//=>timeout記錄定時器
let result,
timeout = null;
//=>返回可被執行的函數
return function (...args) {
//=>now記錄的是事件觸發的時候當即執行,仍是須要等待間隔事件後執行
let context = this,
now = immediate && !timeout;
//=>每一次設置新的定時器等待以前,都要先清空上一次設置的,確保間隔時間內只執行一次
clearTimeout(timeout);
//=>設置定時器:到達時間間隔後執行函數
timeout = setTimeout(() => {
timeout = null;
if (!immediate) result = func.apply(context, args);
}, wait);
//=>若是是事件觸發就執行,把函數執行便可
if (now) result = func.apply(context, args);
return result;
};
};
複製代碼
throttle:函數節流是爲了縮減執行頻率,當達到了必定的時間間隔就會執行一次shell
let throttle = function (func, wait) {
let timeout = null,
result = null,
previous = 0; //=>上次執行時間點
return function (...args) {
let now = new Date,
context = this;
//=>remaining小於等於0,表示上次執行至此所間隔時間已經超過一個時間間隔
let remaining = wait - (now - previous);
if (remaining <= 0) {
clearTimeout(timeout);
previous = now;
timeout = null;
result = func.apply(context, args);
} else if (!timeout) {
timeout = setTimeout(() => {
previous = new Date;
timeout = null;
result = func.apply(context, args);
}, remaining);
}
return result;
};
};
複製代碼
方法一:markdown
let clone = JSON.parse(JSON.stringify(obj));
複製代碼
方法二:數據結構
function _cloneDeep(obj) {
if (obj === null) return null;
if (typeof obj !== "object") return obj;
if (obj instanceof RegExp) return new RegExp(obj);
if (obj instanceof Date) return new Date(obj);
let cloneObj = new obj.constructor;
for (let key in obj) {
if (!obj.hasOwnProperty(key)) continue;
cloneObj[key] = _cloneDeep(obj[key]);
}
return cloneObj;
}
複製代碼
受高人指點,這裏把break
修改成continue
,確保漏掉任何一個私有屬性,更爲妥帖😄app
function _assignDeep(obj1, obj2) {
let obj = _cloneDeep(obj1);
for (let key in obj2) {
if (!obj2.hasOwnProperty(key)) continue;
let v2 = obj2[key],
v1 = obj[key];
if ((v1 !== null && typeof v1 === "object") && (v2 !== null && typeof v2 === "object")) {
obj[key] = _assignDeep(v1, v2);
continue;
}
obj[key] = v2;
}
return obj;
}
複製代碼
function _is(val1, val2) {
const type1 = val1 === null ? 'null' : typeof val1,
type2 = val2 === null ? 'null' : typeof val2;
// 函數
if (type1 === "function" && type2 === "function") {
return val1.toString() === val2.toString();
}
// 對象
if (type1 === "object" && type2 === "object") {
// 正則和日期
const ct1 = val1.constructor,
ct2 = val2.constructor;
if ((ct1 === RegExp && ct2 === RegExp) || (ct1 === Date && ct2 === Date)) {
return val1.toString() === val2.toString();
}
// 其它對象
const keys1 = Object.keys(val1),
keys2 = Object.keys(val2);
if (keys1.length !== keys2.length) return false;
for (let i = 0; i < keys1.length; i++) {
let key1 = keys1[i],
key2 = keys2[i];
if (key1 !== key2) return false;
let item1 = val1[key1],
item2 = val2[key2];
let flag = _is(item1, item2);
if (!flag) return false;
}
return true;
}
// 其它
return val1 === val2;
}
複製代碼
function toType(obj) {
let class2type = {};
["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object", "Error", "Symbol"].forEach(
item => {
class2type["[object " + item + "]"] = item.toLowerCase();
});
if (obj == null) return obj + "";
return typeof obj === "object" || typeof obj === "function" ?
class2type[class2type.toString.call(obj)] || "object" :
typeof obj;
}
let obj = function () {};
console.log(toType(obj))
複製代碼
繼承這裏詳細能夠看:JS中的多種繼承方式ide
function Parent() {
this.x = 100;
}
function Child() {
this.y = 200;
}
//=> 讓子類的原型等於父類的實例
Child.prototype = new Parent; //=>原型繼承
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
複製代碼
function Parent() {
this.x = 100;
}
Parent.prototype.getX = function getX() {
return this.x;
};
function Child() {
// 在子類構造函數中,把父類當作普通方法執行(沒有父類實例,父類原型上的那些東西也就和它不要緊了)
// this -> Child的實例c1
Parent.call(this); // this.x=100 至關於強制給c1這個實例設置一個私有的屬性x,屬性值100,至關於讓子類的實例繼承了父類的私有的屬性,而且也變爲了子類私有的屬性 「拷貝式」
this.y = 200;
}
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
複製代碼
function Parent() {
this.x = 100;
}
Parent.prototype.getX = function getX() {
return this.x;
};
function Child() {
Parent.call(this);
this.y = 200;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
複製代碼
String.prototype.formatTime = function formatTime(template) {
// 1.根據操做的時間字符串獲取年月日小時分鐘秒等信息
let arr = this.match(/\d+/g).map(item => {
return item.length < 2 ? '0' + item : item;
});
// 2.解析格式化的模板,找到對應的時間,替換模板中的內容
template = template || '{0}年{1}月{2}日 {3}時{4}分{5}秒';
return template.replace(/\{(\d+)\}/g, (_, group) => {
return arr[group] || "00";
});
};
複製代碼
方法一:replace處理
(proto => {
function queryURLParams() {
let obj = {};
this.replace(/([^?=&#]+)=([^?=&#]+)/g, (_, key, value) => obj[key] = value);
this.replace(/#([^?=&#]+)/g, (_, hash) => obj['HASH'] = hash);
return obj;
}
proto.queryURLParams = queryURLParams;
})(String.prototype);
console.log('http://www.xxxxxxx.cn/?lx=1&name=JS&from=baidu#video'.queryURLParams());
複製代碼
方法二:利用A標籤內置方法
function queryURLParams(url) {
// 1.建立A標籤(A元素對象)來獲取到問號參數和哈希值
let link = document.createElement('a');
link.href = url;
let askText = link.search.substr(1),
polText = link.hash.substr(1),
obj = {};
// 2.向對象中進行存儲
polText ? obj['HASH'] = polText : null;
if (askText) {
let arr = askText.split(/(?:&|=)/g); //=>同時按照兩個字符來拆分:["lx", "1", "name", "JS", "from", "baidu"]
for (let i = 0; i < arr.length; i += 2) {
// console.log(arr[i], arr[i + 1]); 屬性名和屬性值
obj[arr[i]] = arr[i + 1];
}
}
return obj;
}
let result = queryURLParams('http://www.xxxxxxx.cn/?lx=1&name=JS&from=baidu#video');
console.log(result);
/* <a href="http://www.xxxxxxx.cn/?lx=1&name=JS&from=baidu#video" id="link">*/
複製代碼
String.prototype.millimeter = function millimeter() {
return this.replace(/\d{1,3}(?=(\d{3})+$)/g, value => {
return value + ',';
});
};
複製代碼
let str = "hello";
let ary = [...new Set(str.split(''))];
let max = 0;
let code = '';
for (let i = 0; i < ary.length; i++) {
let reg = new RegExp(ary[i], 'g');
let val = str.match(reg).length;
if (val > max) {
max = val;
code = ary[i];
} else if (val === max) {
code = `${code}、${ary[i]}`;
}
}
console.log(`出現次數最多的字符是:${code},次數爲:${max}`);
複製代碼
該方法引自:掘金做者:李開心呀 的 【建議收藏】一份超簡潔的前端總結 ;(PS:聽說是一位很漂亮的小姐姐喲🌹 )
方法一:雙for循環
for (let i = 0; i < arr.length - 1; i++) {
let item = arr[i];
for (let j = i + 1; j < arr.length; j++) {
if (item === arr[j]) {
arr[j] = arr[arr.length - 1];
arr.length--;
j--;
}
}
}
console.log(arr);
複製代碼
方法二:對象鍵值對的方式
let arr = [1, 2, 3, 1, 1, 4, 2, 3];
let obj = {};
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (obj[item] !== undefined) {
arr[i] = arr[arr.length - 1];
arr.length--;
i--;
continue;
}
obj[item] = item;
}
console.log(arr);
複製代碼
方法三:ES6利用Set方式
/* ES6中沒有提供現成的去重辦法,可是提供了一些去重的方式 :Set數據結構*/
let obj = { y: 200 };
let arr = [obj, 1, 2, 3, 1, obj, 1, 4, 2, 3, '3', { x: 100 }, { x: 100 }];
arr = Array.from(new Set(arr));
console.log(arr);
複製代碼
方法一:冒泡排序
// 交換位置函數
function swap(arr, i, j) {
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
return arr;
}
Array.prototype.bubble = function bubble() {
// 外層循環I控制比較的輪數
for (let i = 0; i < this.length - 1; i++) {
// 裏層循環控制每一輪比較的次數J
for (let j = 0; j < this.length - 1 - i; j++) {
if (this[j] > this[j + 1]) {
// 當前項大於後一項,交換位置
swap(this,j,j+1);
}
}
}
return this;
}
let ary = [12, 8, 24, 16, 1];
ary.bubble();
console.log(ary);
複製代碼
方法二:選擇排序
Array.prototype.select = function select() {
for (let j = 0; j < this.length - 1; j++) {
let min = j,
temp = null;
// 找到比當前項還小的這一項索引
for (let i = min + 1; i < this.length; i++) {
if (this[i] < this[min]) {
min = i;
}
}
// 讓最小的項和當前首位交換位置
swap(this,min,j);
}
return this;
};
let ary = [12, 8, 24, 16, 1];
ary.select();
console.log(ary);
複製代碼
方法三:插入排序
Array.prototype.insert = function insert() {
// 1.準備一個新數組,用來存儲抓到手裏的牌,開始先抓一張牌進來
let handle = [];
handle.push(this[0]);
// 2.從第二項開始依次抓牌,一直到把檯面上的牌抓光
for (let i = 1; i < this.length; i++) {
// A是新抓的牌
let A = this[i];
// 和HANDDLE手裏的牌依次比較(從後向前比)
for (let j = handle.length - 1; j >= 0; j--) {
// 每一次要比較的手裏的牌
let B = handle[j];
// 若是當前新牌A比要比較的牌B大了,把A放到B的後面
if (A > B) {
handle.splice(j + 1, 0, A);
break;
}
// 已經比到第一項,咱們把新牌放到手中最前面便可
if (j === 0) {
handle.unshift(A);
}
}
}
return handle;
}
let ary = [12, 8, 24, 16, 1];
ary.insert();
console.log(ary);
複製代碼
方法四:快速排序
Array.prototype.quick = function quick() {
// 4.結束遞歸(當數組中小於等於一項,則不用處理)
if (this.length <= 1) {
return this;
}
// 1.找到數組的中間項,在原有的數組中把它移除
let middleIndex = Math.floor(this.length / 2);
let middleValue = this.splice(middleIndex, 1)[0];
// 2.準備左右兩個數組,循環剩下數組中的每一項,比當前項小的放到左邊數組中,反之放到右邊數組中
let aryLeft = [],
aryRight = [];
for (let i = 0; i < this.length; i++) {
let item = this[i];
item < middleValue ? aryLeft.push(item) : aryRight.push(item);
}
// 3.遞歸方式讓左右兩邊的數組持續這樣處理,一直到左右兩邊都排好序爲止(最後讓左邊+中間+右邊拼接成爲最後的結果)
return quick(aryLeft).concat(middleValue, quick(aryRight));
}
let ary = [12, 8, 15, 16, 1, 24];
ary.quick();
console.log(ary);
複製代碼
方法四:希爾排序
Array.prototype.shell = function shell() {
let gap = Math.floor(this.length / 2);
while (gap >= 1) {
for (let i = gap; i < this.length; i++) {
while (i - gap >= 0 && this[i] < this[i - gap]) {
swap(this, i, i - gap);
i = i - gap;
}
}
gap = Math.floor(gap / 2);
}
};
let arr = [58, 23, 67, 36, 40, 46, 35, 28, 20, 10];
arr.shell();
console.log(arr);
複製代碼
方法一:基於sort
ary.sort(function (a, b) {
return a - b;
});
let min = ary[0];
let max = ary[ary.length - 1];
console.log(min, max);
複製代碼
方法二:利用Math.min/max
let min = Math.min(...ary);
console.log(min);
//==========================
let min = Math.min.apply(null,ary);
console.log(min);
複製代碼
方法三:假設法
let max = ary[0];
for (let i = 1; i < ary.length; i++) {
let item = ary[i];
item > max ? max = item : null;
}
//=> for 循環 也能夠改寫爲 forEach
ary.forEach(item => {
item > max ? max = item : null;
});
console.log(max);
複製代碼
function offset(element) {
let parent = element.offsetParent,
top = element.offsetTop,
left = element.offsetLeft;
while (parent) {
if (!/MSIE 8/.test(navigator.userAgent)) {
left += parent.clientLeft;
top += parent.clientTop;
}
left += parent.offsetLeft;
top += parent.offsetTop;
parent = parent.offsetParent;
}
return {
top,
left
};
}
複製代碼
/* 獲取CSS樣式 */
function getCss(element, attr) {
let value = window.getComputedStyle(element)[attr],
reg = /^\d+(px|rem|em)?$/i;
if (reg.test(value)) {
value = parseFloat(value);
}
return value;
}
/* 設置CSS樣式:單個設置 */
function setCss(element, attr, value) {
if (attr === "opacity") {
element['style']['opacity'] = value;
element['style']['filter'] = `alpha(opacity=${value*100})`;
return;
}
let reg = /^(width|height|margin|padding)?(top|left|bottom|right)?$/i;
if (reg.test(attr)) {
if (!isNaN(value)) {
value += 'px';
}
}
element['style'][attr] = value;
}
/* 設置CSS樣式:對象形式設置 */
function setGroupCss(element, options) {
for (let key in options) {
if (!options.hasOwnProperty(key)) break;
setCss(element, key, options[key]);
}
}
function css(element) {
let len = arguments.length,
attr = arguments[1],
value = arguments[2];
if (len >= 3) {
// 單一設置樣式
setCss(element, attr, value);
return;
}
if (attr !== null && typeof attr === "object") {
// 批量設置
setGroupCss(element, attr);
return;
}
// 獲取樣式
return getCss(element, attr);
}
複製代碼
今天的內容就先到這裏吧,原本還想把梳理的部分源碼也放進來,可是考慮到一堆代碼原本就夠枯燥乏味的了,篇幅在很大的話,恐怕小芝麻本身都看不進去 😓 ;
同時也歡迎你們提供新的思路,和一些經常使用的方法,小芝麻感激涕零🙏 😄