## 共享onload事件
```
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
```
## 在現有的元素后插入一個新元素
```
function insertAfter(newElement,targetElement){
var parent = targetElement.parentNode;
if (parent.lastChild == targetElement) {
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement,targetElement.nextSubling)
}
}
```
## 查找下一個元素節點
```
function getNextElement(node){
if (node.nodeType == 1) {
return node ;
}
if (node.nextSibling) {
return getNextElement(node.nextSibling);
}
return null ;
}
```
## 利用JS去更新某個元素的class屬性
```
function addClass(element,value) {
if (!element.className) {
element.className = value;
} else {
newClassName = element.className;
newClassName+= " ";
newClassName+= value;
element.className = newClassName;
}
}
```
## ||短路符設置默認值
```
let person = {
name: '張三',
age: 38
}
let name = person.name || '佚名'
```
## 字符串拼接使用`${}`
```
let person = {
name: 'LiMing',
age: 18
}
// good
function sayHi (person) {
console.log(`大家好,我叫${person.name},我今年${person.age}了`)
}
// best
function sayHi ({name, age}) {
console.log(`大家好,我叫${name},我今年${age}了`)
}
```
## .函數使用箭頭函數
```
let arr [18, 19, 20, 21, 22]
// bad
function findStudentByAge (arr, age) {
return arr.filter(function (num) {
return num === age
})
}
// good
let findStudentByAge = (arr, age)=> arr.filter(num => num === age)
```
## 函數參數校驗
```
// good
let checkoutType = () => {
throw new Error('參數不能為空')
}
let findStudentByAge = (arr, age = checkoutType()) =>
arr.filter(num => num === age)
```
## if 判斷的優化
```
let commodity = {
phone: '手機',
computer: '電腦',
television: '電視',
gameBoy: '游戲機',
}
function price(name) {
if (name === commodity.phone) {
console.log(1999)
} else if (name === commodity.computer) {
console.log(9999)
} else if (name === commodity.television) {
console.log(2999)
} else if (name === commodity.gameBoy) {
console.log(3999)
}
}
price('手機') // 9999
```
缺點:代碼太長了,維護和閱讀都很不友好
好一點的方法:`Switch`
```
let commodity = {
phone: '手機',
computer: '電腦',
television: '電視',
gameBoy: '游戲機',
}
const price = (name) => {
switch (name) {
case commodity.phone:
console.log(1999)
break
case commodity.computer:
console.log(9999)
break
case commodity.television:
console.log(2999)
break
case commodity.gameBoy:
console.log(3999)
break
}
}
price('手機') // 9999
```
更優的方法: 策略模式
策略模式利用組合、委托和多態等技術和思想,可以有效地避免多重條件選擇語句。它提供了對開放—封閉原則的完美支持,將算法封裝在獨立的 strategy 中,使得它們易于切換,易于理解,易于擴展。
```
const commodity = new Map([
['phone', 1999],
['computer', 9999],
['television', 2999],
['gameBoy', 3999],
])
const price = (name) => {
return commodity.get(name)
}
price('phone') // 1999
```
## includes 的優化
`includes`是 ES7 新增的 API,與`indexOf`不同的是`includes`直接返回的是`Boolean`值,`indexOf`則 返回的索引值, 數組和字符串都有`includes`方法。
需求:我們來實現一個身份認證方法,通過傳入身份 Id 返回對應的驗證結果
```
//old
function verifyIdentity(identityId) {
if (identityId == 1 || identityId == 2 || identityId == 3 || identityId == 4) {
return '你的身份合法,請通行!'
} else {
return '你的身份不合法'
}
}
//new
function verifyIdentity(identityId) {
if ([1, 2, 3, 4].includes(identityId)) {
return '你的身份合法,請通行!'
} else {
return '你的身份不合法'
}
}
```
## for 循環
在 JavaScript 中,我們可以使用`for()`,`while()`,`for(in)`,`for(of)`幾種循環,事實上,這三種循環中`for(in)`的效率極差,因為他需要查詢散列鍵,所以應該盡量少用。
for 循環是最傳統的語句,它以變量 i 作為索引,以跟蹤訪問的位置,對數組進行操作。
```
var arr = ['a', 'b', 'c']
for (var i = 0, length = arr.length; i < length; i++) {
console.log(arr[i]) //結果依次a,b,c
}
```
此時`arr.length`只需要計算一次,優化了性能。
## 數組去重
利用 ES6 的`Set`方法。
`Set`本身是一個構造函數,用來生成`Set`數據結構。`Set`函數可以接受一個數組(或者具有 iterable 接口的其他數據結構)作為參數,用來初始化。`Set`對象允許你存儲任何類型的值,無論是原始值或者是對象引用。它類似于數組,但是成員的值都是唯一的,沒有重復的值。
```
function unique4(arr) {
return [...new Set(arr)]
}
console.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
// [1, 2, 3, 5, 6, 7, 4]
```
## 箭頭函數
箭頭函數表達式的語法比函數表達式更簡潔。所以在開發中更推薦使用箭頭函數。特別是在`vue`項目中,使用箭頭函數不需要在更`this`重新賦一個變量。
```
// old 使用functions
var arr = [5, 3, 2, 9, 1]
var arrFunc = arr.map(function (x) {
return x * x
})
console.log(arrFunc)
// 使用箭頭函數
var arr = [5, 3, 2, 9, 1]
var arrFunc = arr.map((x) => x * x)
```
要注意的是,箭頭函數不綁定`arguments`,取而代之用`rest`參數…解決。
```
// 不能使用 arguments
let fun1 = (b) => {
console.log(arguments)
}
fun1(2, 92, 32, 32) // Uncaught ReferenceError: arguments is not defined
// 使用rest 參數
let fun2 = (...c) => {
console.log(c)
}
fun2(3, 82, 32, 11323) // [3, 82, 32, 11323]
```
## Dom 的創建
創建多個 dom 元素時,先將元素`append`到`DocumentFragment`中,最后統一將`DocumentFragment`添加到頁面。
常規方法;
```
for (var i = 0; i < 1000; i++) {
var el = document.createElement('p')
el.innerHTML = i
document.body.appendChild(el)
}
```
使用`DocumentFragment`優化多次`append`
```
var frag = document.createDocumentFragment()
for (var i = 0; i < 1000; i++) {
var el = document.createElement('p')
el.innerHTML = i
frag.appendChild(el)
}
document.body.appendChild(frag)
```
更優的方法:使用一次`innerHTML`賦值代替構建 dom 元素
```
ar html = []
for (var i = 0; i < 1000; i++) {
html.push('<p>' + i + '</p>')
}
document.body.innerHTML = html.join('')
```
## 防抖與節流
在前端開發的過程中,我們經常會需要綁定一些持續觸發的事件,如`resize`、`scroll`、`mousemove`等等,但有些時候我們并不希望在事件持續觸發的過程中那么頻繁地去執行函數。這時候就用到防抖與節流。
案例 1:遠程搜索時需要通過接口動態的獲取數據,若是每次用戶輸入都接口請求,是浪費帶寬和性能的。
```
<Select :remote-method="remoteMethod">
<Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
<script>
function debounce(fn, wait) {
let timeout = null
return function () {
if (timeout !== null) clearTimeout(timeout)
timeout = setTimeout(fn, wait)
}
}
export default {
methods:{
remoteMethod:debounce(function (query) {
// to do ...
}, 200),
}
}
<script>
```
案例 2:持續觸發`scroll`事件時,并不立即執行`handle`函數,當 1000 毫秒內沒有觸發`scroll`事件時,才會延時觸發一次`handle`函數。
```
function debounce(fn, wait) {
let timeout = null
return function () {
if (timeout !== null) clearTimeout(timeout)
timeout = setTimeout(fn, wait)
}
}
function handle() {
console.log(Math.random())
}
window.addEventListener('scroll', debounce(handle, 1000))
```
*****
## 異步加載 js
默認情況下,瀏覽器是同步加載 js 腳本,解析 html 過程中,遇到`<script>`標簽就會停下來,等腳本下載、解析、執行完后,再繼續向下解析渲染。
如果 js 文件體積比較大,下載時間就會很長,容易造成瀏覽器堵塞,瀏覽器頁面會呈現出“白屏”效果,用戶會感覺瀏覽器“卡死了”,沒有響應。此時,我們可以讓 js 腳本異步加載、執行。
```
<script src="path/to/home.js" defer></script>
<script src="path/to/home.js" async></script>
```
上面代碼中,`<script>`標簽分別有`defer`和`async`屬性,瀏覽器識別到這 2 個屬性時 js 就會異步加載。也就是說,瀏覽器不會等待這個腳本下載、執行完畢后再向后執行,而是直接繼續向后執行
defer 與 async 區別:
* defer:DOM 結構完全生成,以及其他腳本執行完成,才會執行(渲染完再執行)。有多個`defer`腳本時,會按照頁面出現的順序依次加載、執行。
* async:一旦下載完成,渲染引擎就會中斷渲染,執行這個腳本以后,再繼續渲染(下載完就執行)。有多個`async`腳本時,不能保證按照頁面出現順序加載、執行
## import()
~~~js
const btn = document.getElementById("btn");
btn.onclick = () => {
import("./hello.js").then(module => {
module.hello();
});
};
~~~
## 可選鏈操作符(?.)
~~~js
const data = {
name: "張三",
age: 18,
sex: "男"
};
console.log(data?.friend?.name);
~~~
## 空值合并運算符(??)
~~~js
let a = 0;
let b = a || "aaa";
let c = a ?? "aaa";
console.log("b的值是 " + b);//b的值是 aaa
console.log("c的值是 " + c);//c的值是 0
~~~
## 箭頭函數
箭頭函數看起來會更加的簡潔,因為它允許你使用更短的語法來書寫函數:
~~~js
const myFunction = function() {
//...
}
~~~
到
~~~js
const myFunction = () => {
//...
}
~~~
如果函數體中只包含一條語句,你甚至可以省略大括號并直接書寫這條語句:
~~~js
const myFunction = () => doSomething()
~~~
參數在括號中傳遞:
~~~js
const myFunction = (param1, param2) => doSomething(param1, param2)
~~~
如果該函數**只有一個**參數,那么可以省略掉括號:
~~~js
const myFunction = param => doSomething(param)
~~~
由于這種簡短的語法,使得我們可以更便捷的使用**比較簡短的函數**
## Using `let`
`let` 是ES2015中引入的新功能,它本質上是具有塊級作用域的 `var` 。它可以被當前作用域(函數以及塊級作用域)以及子級作用域訪問到。
現代 JavaScript 開發者在 `let` 和 `var` 的選擇中可能會更傾向于前者。
## Using `const`
使用變量 `var` 或 `let` 聲明的變量可以被重新賦值。 使用 `const` 聲明的變量一經初始化,它的值就永遠不能再改變,即不可重新被賦值。
~~~js
const a = 'test'
~~~
我們不能再為 `a` 進行賦值操作。然而,`a` 如果它是一個具有屬性或者方法的對象,那么我們可以改變它的屬性或者方法。
`const` 并不意味著具有不可變性,只是保證用 `const` 聲明的變量的引用地址不被變更。
## 隱式返回
箭頭函數支持隱式返回:可以正常的 `return` 一個返回值但是可以不使用 `return` 關鍵字。
隱式返回只在函數體內只包含一條語句的情況下生效:
~~~js
const myFunction = () => 'test'
myFunction() //'test'
~~~
需要注意的一種情況,當返回一個對象時,記得將大括號括在括號中以避免產生歧義,誤將其(大括號)解析為函數體的大括號。
~~~js
const myFunction = () => ({ value: 'test' })
myFunction() //{value: 'test'}
~~~
## class 定義
如下是一個 class 的例子:
~~~js
class Person {
constructor(name) {
this.name = name
}
hello() {
return 'Hello, I am ' + this.name + '.'
}
}
~~~
在這個類的對象實例上調用:
~~~js
const flavio = new Person('Flavio')
flavio.hello()
~~~
## Class 繼承
一個子類可以 extend 另一個類,通過子類實例化出來的對象可以繼承這兩個類的所有方法。
如果子類中的方法與父類中的方法名重復,那么子類中的同名方法優先級更高:
~~~js
class Programmer extends Person {
hello() {
return super.hello() + ' I am a programmer.'
}
}
const flavio = new Programmer('Flavio')
flavio.hello()
~~~
## 靜態方法
在類中,通常會把方法直接掛載到實例對象上,直接在實例對象上調用。
而靜態方法則是直接使用類名來調用,而不是通過對象實例調用:
~~~js
class Person {
static genericHello() {
return 'Hello'
}
}
Person.genericHello() //Hello
~~~
## For-of循環
2009年的ES5引入了`forEach()`循環,雖然很好用,但是它跟`for`循環不一樣,沒法break。
ES2015引入了`**for-of**` **循環**,就是在`forEach`的基礎上加上了break的功能:
~~~js
//iterate over the value
for (const v of ['a', 'b', 'c']) {
console.log(v);
}
//get the index as well, using `entries()`
for (const [i, v] of ['a', 'b', 'c'].entries()) {
console.log(index) //index
console.log(value) //value
}
~~~
## 創建一個promise
Promise API暴露了一個Promise構造函數,可以通過`new Promise()`來初始化:
~~~js
let done = true
const isItDoneYet = new Promise((resolve, reject) => {
if (done) {
const workDone = 'Here is the thing I built'
resolve(workDone)
} else {
const why = 'Still working on something else'
reject(why)
}
})
~~~
## 使用一個promise
上面講了怎么創建一個promise,下面就講怎么使用(consume)這個promise。
~~~js
const isItDoneYet = new Promise()
//...
const checkIfItsDone = () => {
isItDoneYet
.then(ok => {
console.log(ok)
})
.catch(err => {
console.error(err)
})
}
~~~
## 鏈式promise的例子
Fetch API
~~~js
const status = response => {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
}
return Promise.reject(new Error(response.statusText))
}
const json = response => response.json()
fetch('/todos.json')
.then(status)
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data)
})
.catch(error => {
console.log('Request failed', error)
})
~~~
檢查日期是否為工作日
```
const isWeekday = (date) => date.getDay() % 6 !== 0;
```
反轉字符串
```
const reverse = (str) => str.split('').reverse().join('');
console.log(reverse('hello world'));;
```
檢查當前 Tab 頁是否在前臺
```
~~~
const isBrowserTabInView = () => document.hidden;
console.log(isBrowserTabInView());
~~~
```
保留小數點(非四舍五入)
```
const toFixed = (n, fixed) => ~~(Math.pow(10, fixed) * n) / Math.pow(10, fixed);
// Examples
a=toFixed(25.198726354, 1);
```
滾動到頁面頂部
```
const goToTop = () => window.scrollTo(0, 0);
```
獲取Cookie
~~~js
const cookie = name => `; ${document.cookie}`.split(`; ${name}=`).pop().split(';').shift();
cookie('_ga');
~~~
~~~text
/**
* 將字節轉換為合理的容量單位
* @param {number} bytes Bytes in Number
*/
const humanFileSize = (bytes) => {
let BYTES = bytes;
const thresh = 1024;
if (Math.abs(BYTES) < thresh) {
return `${BYTES} B`;
}
const units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
let u = -1;
const r = 10 ** 1;
do {
BYTES /= thresh;
u += 1;
} while (Math.round(Math.abs(BYTES) * r) / r >= thresh && u < units.length - 1);
return `${BYTES.toFixed(1)} ${units[u]}`;
};
/**
* storage具有過期時間
* Caching values with expiry date to the LocalHost.
* @param {string} key Local Storage Key
* @param {any} value Local Storage Value
* @param {number} ttl Time to live (Expiry Date in MS)
*/
const setLocalItem = (key, value, ttl = duration.month) => {
const now = new Date();
// `item` is an object which contains the original value
// as well as the time when it's supposed to expire
const item = {
value,
expiry: now.getTime() + ttl,
};
localStorage.setItem(key, JSON.stringify(item));
};
/**
* storage具有過期時間
* Getting values with expiry date from LocalHost that stored with `setLocalItem`.
* @param {string} key Local Storage Key
*/
const getLocalItem = (key) => {
const itemStr = localStorage.getItem(key);
// if the item doesn't exist, return null
if (!itemStr) {
return null;
}
const item = JSON.parse(itemStr);
const now = new Date();
// compare the expiry time of the item with the current time
if (now.getTime() > item.expiry) {
// If the item is expired, delete the item from storage
// and return null
localStorage.removeItem(key);
return null;
}
return item.value;
};
~~~
- 文檔說明
- 后臺定制類
- WordPress后臺樣式
- WordPress創建后臺小工具
- WordPress增加新的角色
- WordPress修改默認角色名
- WordPress后臺頂部去除新建文章
- WordPress后門代碼,僅參考思路,創建管理員
- 對訂閱用戶隱藏資料頁面
- 修改WordPress后臺側邊欄菜單名字
- 修改自定義文章菜單圖標
- 基于用戶角色權限區分不同的功能
- WordPress修改登錄頁面圖標,名字等功能
- WordPress對于非管理員禁用密碼修改欄
- WordPress禁用頂部工具欄
- WordPress后臺強制使用某種語言
- WordPress自定義后臺登錄失敗提示
- WordPress使用一欄后臺
- WordPress后臺自定義聯系方式
- WordPress將一些頁面跳轉到后臺
- 用戶登陸后跳轉到指定頁面
- WordPress禁用后臺歡迎工具
- WordPress后臺代碼文件必備驗證
- WordPress自定義后臺歡迎面板內容
- WordPress判斷是否為指定post-type
- WordPress用戶描述支持HTML代碼
- WordPress自定義后臺右下角文字
- WordPress禁用全部小工具
- 評論互動類
- 給評論提交按鈕添加class
- WordPress禁用附件評論
- WordPress評論去除鏈接欄
- 告訴用戶文章N天之后即將關閉評論
- 限制評論字數
- WordPress屏蔽指定外文垃圾評論
- WordPress替換評論者鏈接
- WordPress轉換評論中的HTML實體
- 去除自定義里面不想要的控制器
- 從自定義里面去除自定義CSS
- WordPress增加子主題名字到body class里面
- 自定義WordPress的body_class
- 修改WordPress媒體庫上傳文件格式限制
- 導航類
- WordPress面包屑導航
- 在導航欄加入搜索框
- 在導航里面添加自定義項目
- 高亮導航
- 圖片類定制
- 去除WordPress圖片尺寸限制
- 固定WordPress插入圖片設置
- 禁用WordPress的響應式圖片
- WordPress增加全站圖標
- WordPress后臺媒體庫替換縮略圖鏈接
- WordPress自動將第一個圖片設為特色圖
- WordPress要求必須增加特色圖才可以發布
- 第三方服務類
- WordPress禁用谷歌字體
- WordPress禁用emojis
- 百度主動推送代碼
- WordPress前臺禁用dashicon圖標字體
- 郵箱服務類
- 關閉WordPress注冊郵箱通知功能
- 修改用戶前線郵箱通知
- 頭像類
- WordPress禁用gavatar頭像
- WordPress自定義默認頭像
- WordPress替換頭像服務器
- 安全防御類
- 禁用WordPress的xmlrpc功能
- WordPress維護模式代碼
- WordPress數據庫維護代碼
- WordPress去除版本號
- 網站登錄驗證
- 禁用pingbak
- 條件判斷類
- 判斷評論用戶是否為注冊用戶
- WordPress判斷是否是管理員
- WordPress判斷是否登錄
- SEO優化類
- WordPress替換網站描述
- WordPress文章描述
- 將特色圖設置到OG標簽
- 自定義默認文章標題
- 頁面支持摘要
- 在某些頁面模板中禁用編輯器
- 移除某些頁面模板
- 權限控制類
- 針對不同狀態顯示不同顏色
- 文章顯示過期提示
- 從文章內容提取描述
- 短代碼保護郵箱
- 在用戶欄修改用戶ID
- 未登錄用戶強制跳轉登錄頁
- 分類描述支持HTML
- 移除已存在的分類
- 支持在小工具使用短代碼
- 禁用主題插件編輯器
- 定義默認主題slug
- 禁用默認主題的安裝
- 禁止主題和插件文件修改
- wp-config.php參數
- 修改數據前綴
- 清理無用自定義字段
- 在編輯器周圍自定義內容
- 清理頭部亂七八糟無用的代碼
- 禁用圖片的說明文字
- 禁用可視化編輯器
- WordPress各PHP頁面用緩存做數據交換
- 網絡資源類
- 網絡二維碼API
- bat批處理微信多開
- 獲取IP地址接口
- 頁面組件類
- 黑色網頁頁腳
- 黑色頁腳二
- 微軟卡片式通欄模塊
- 增強內置的延遲加載性能
- WordPress 禁用 admin/login 跳轉
- WordPress HOOKS執行順序
- 服務器類
- LNMP管理命令行
- 寶塔命令行
- 數據庫類
- WordPress數據庫查詢的安全處理
- 數據獲取類
- 通過ID獲取文章內容
- WordPress根據頁面模板路徑獲取頁面ID
- 獲取文章第一個鏈接
- WordPress獲取當前頁面鏈接
- 獲取頂層頁面的ID
- WordPress優化類
- WordPress自定義路由
- WordPress隱藏部分插件
- 關閉WordPress核心,主題,插件更新
- WordPress禁用RSS訂閱
- WordPress禁用靜態資源版本查詢
- WordPress去除后臺logo
- WordPress內容僅限登錄用戶查看
- WordPress延遲RSS訂閱
- WordPress屏蔽部分分類
- WordPress根據UA切換主題
- 自定義摘要字數
- 自定義更多內容文字
- 文章底部版權聲明以及自定義內容
- 小工具支持PHP代碼
- WordPress文本編輯器添加少量自定義按鈕
- WordPress文章關鍵字替換
- WordPress首頁排除某些分類文章
- WordPress添加隱藏的設置頁面
- WordPress加載自定義jQuery庫
- 限制WordPress版本號數目
- WordPress搜索結果包含自定義文章類型
- 禁止ping到自己的WordPress網站
- 在源代碼頁腳顯示資源消耗
- WordPress禁用自帶的小工具
- WordPress后臺刪除不必要的小工具
- WordPress指定用戶投稿分類
- WordPress增加ajax點贊功能
- 自定義WordPress登錄背景
- WordPress強制阻止代碼轉義功能
- WordPress頁面偽靜態化
- WordPress代碼版sitemap地圖
- WordPress非管理員不準進入后臺
- WordPress注冊之后跳轉到指定頁面
- WordPress增加通用短代碼下拉按鈕
- WordPress給不同狀態的文字添加顏色
- 后臺添加操作指引
- 短代碼實現倒計時顯示功能
- 讓登錄用戶選擇跳轉到哪里
- WordPress定時任務
- PHP驗證當前時間是否在指定時間段
- Git 命令大全
- 常用JS代碼
- 常用js函數使用方式
- 實用js函數代碼