## 共享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函数代码