Object.assign()
//浅拷贝
Symbol()
//ES6引入了一个新的内置类Reflect,它的ownKeys方法可以识别出所有属性名
var s = Symbol();
var s1 = Symbol('s1');
var obj = {
[s]: function() {
console.log(1);
},
[Symbol()]: () => {
console.log(2);
},
[s1]: 3,
a: 4
};
Reflect.ownKeys(obj).forEach(function(item) {
if (typeof obj[item] === 'function') {
obj[item]();
} else {
console.log(obj[item]);
}
});
stringObj.trim()
/*
*params:
* stringObj: 必选。String对象或字符串。trim方法不修改字符串
*返回值:
* 已移除前导空格、尾随空格和行终止符的原始字符串(移除的字符包括空格、制表符、换页符、回车符和换行符。)
*/
var message=" abc def \r\n";
document.write("["+message.trim()+"]");
document.write("</br>");
document.write("length"+message.trim().length);
//Output:
// [abc def]
// length:7
/*stringObj.trim()源码实现*/
//实现1,速度惊人
String.prototype.trim = fucntion() {
return this.replace(/^\s\s*/,'').replace(/\s\s*$/,'');
}
//实现2,和实现1很相似,但稍慢一点,主要原因是它最先是假设至少存在一个空白符
String.prototype.trim = function() {
return this.replace(/^\s+/,'').replace(/\s+$/,'')
}
/*
实现3,以截取方式取得空白部分(当然允许中间存在空白符),总共调用了四个原生方法。设计得非常巧妙,substring以两个数字作为参数。Math.max以两个数字作参数,search则返回一个数字。速度比上面两个慢一点,但比下面大多数都快。
*/
String.prototype.trim = function() {
return this.substring(Math.max(this.search(/\S/),0),this.search(/\S\s*$/)+1);
}
//实现4,这个可以称得上实现2的简化版,就是利用候选操作符连接两个正则。但这样做就失去了浏览器优化的机会,比不上实现3。由于看来很优雅,许多类库都使用它,如JQuery与mootools
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
}
/*
实现5,match是返回一个数组,因此原字符串符合要求的部分就成为它的元素。为了防止字符串中间的空白符被排除,我们需要动用到非捕获性分组(?:exp)。由于数组可能为空,我们在后面还要做进一步的判定。好像浏览器在处理分组上比较无力,一个字慢。所以不要迷信正则,虽然它基本上是万能的。
*/
String.prototype.trim = function() {
var str = this;
str = str.match(/\S+(?:\s+\S+)*/);
return str ? str[0] : '';
}
对对象判空
/*
*params:
* 非Array的Obj
*返回数据:
* 如果是空的对象,返回true,否则返回false或者“不是期待的Obj”
*/
function objIsNull(obj) {
if(typeof(obj) === 'object' && !(obj instanceof Array) {
var obj_name;
for (obj_name in obj) {
return false;
}
return true
})else {
return "不是期待的Obj"
}
}
//如果是空对象不会进入 for in 循环中,即如果传入的是非空对象,立即返回 false
var obj_name;
for (obj_name in obj) {
return false;
}
获取url的查询参数,并将其改造成对象
no-return-assign
ESlint 检测工具
localStorage&&sessionStorage
简介
html5 中的 web Storage 包括了两种存储方式:sessionStorage 和 localStorage。 sessionStorage 用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问,会话结束后数据也随之销毁。localStorage 用于存储一个域名下的需要永久存在在本地的数据,这些数据可以被一直访问,直到这些数据被删除。
因此sessionStorage 和 localStorage 的主要区别在于他们存储数据的生命周期,sessionStorage 存储的数据的生命周期是一个会话,而 localStorage 存储的数据的生命周期是永久,直到被主动删除,否则数据永远不会过期的。
区别
相同点
- localStroage和sessionStroage是相似的
不同点
- 生命周期不同,localStroage的生命周期是永久,数据在localStorage中是可以无限期保存的;sessionStroage的生命周期是一个会话,会话结束时会清除sessionStorage中保存的数据
API
localStorage.getItem()
localStorage.setItem()
localStorage.removeItem()
localStorage.clear()
sessionStorage.getItem()
sessionStorage.setItem()
localStorage.removeItem()
localStorage.clear()
example
- 添加键值对:localStorage.setItem(key, value)setItem 用于把值 value 存储到键key上,除了使用 setItem ,还可以使用 localStorage.key = value 或者 localStorage['key'] = value 这两种形式。另外需要注意的是,key和value值必须是字符串形式的,如果不是字符串,会调用它们相应的toString() 方法来转换成字符串再存储。当我们要存储对象是,应先转换成我们可识别的字符串格式(比如JSON格式)再进行存储。
localStorage.setItem('name','linjianran')
//localStorage.name = 'linjianran'
//localStorage['name'] = 'linjianran'
//把一个用户存储在user的键上
localStorage.setItem('user', JSON.stringify(id:1,name:'linjianran'))
- 获取键值:localStorage.getItem(key)getItem 用于获取键 key 对应的数据,和 setItem 一样,getItem 也有两种等效形式 value = localStorage.key和 value = localStorage['key'] 。获取到的 value 值是字符串类型,如果需要其他类型,要做手动的类型转换。
let name = localStorage.getItem('name')
//let name = localStorage.name
//let name = localStorage['name']
//获取存储到user的键上的值
let user = JSON.parse(localStorage.getItem('user'));
- 删除键值对:localStorage.removeItem(key)removeItem 用于删除指定键的项,localStorage 没有数据过期的概念,所有数据如果失效了,需要开发者手动删除。
let name = localStorage.getItem('name') //'linjianran'
localStorage.removeItem('name')
name = localStroage.getItem('name') //null
- 清除所有键值对:localStorage.clear() 用于删除所有存储的内容,它和removeItem不同的地方是removeItem 删除的是某一项,而clear是删除所有。
localStorage.clear()
let length = localStorage.length // 0
- 获取 localStorage 的属性名称(键名称):localStorage.key(index)key 方法用于获取指定索引的键名称。需要注意的是赋值的早晚对键值对应的索引值无影响,索引值按键值名称做升序排列,key方法可用于遍历 localStorage 存储的键值。
localStorage.setItem('aKey1','aValue')
localStorage.key(0) // aKey1
localStorage.setItem('bKey','bValue')
localStorage.key(1) // bKey
localStorage.setItem('aKey2','aValue')
localStorage.key(0) // aKey1
localStorage.key(1) // aKey2
localStorage.key(2) // bKey
- 获取loaclStorage中保存的键值对的数量:localStorage.length length 属性用于获取localStorage中键值对的数量
localStorage.setItem('aKey1','aValue')
localStorage.length // 1
localStorage.setItem('bKey','bValue')
localStorage.length // 2
下面的示例会自动保存一个文本输入框的内容,如果浏览器因偶然因素被刷新了,文本输入框里面的内容会被恢复,因此写入的内容不会丢失。
//获取文本输入框
let field = document.getElementById('field')
//检测是否存在autosave键值
//(这个会在页面偶然被刷新的情况下存在)
if (sessionStorage.getItem('autosave')) {
//恢复文本输入框的内容
field.value = sessionStorage.getItem('autosave')
}
//监听文本输入框的 change 事件
field.addEventListener("change",function() {
// 保存结果到 sessionStorage 对象中
sessionStorage.setItem('autosave', field.value)
})
Web Storage 事件
- storage 事件当存储的数据发生变化时,会触发 storage 事件。但要注意的是它不同于click类的事件会事件捕获和冒泡,storage 事件更像是一个通知,不可取消。触发这个事件会调用同域下其他窗口的storage事件,不过触发storage的窗口(即当前窗口)不触发这个事件。storage 的 event 对象的常用属性如下:
oldValue:更新前的值。如果该键为新增加,则这个属性为null。
newValue:更新后的值。如果该键被删除,则这个属性为null。
url:原始触发storage事件的那个网页的网址。
key:存储store的key名
function storageChanged() {
console.log(arguments);
}
window.addEventListener('storage', storageChanged, false);
时间戳和date对象相互转换
将Date对象转换成时间戳
- 使用Number()
let newDate = new Date()
// 返回当前时间的时间戳
Number(newDate)
- 使用Date.parse()
let newDate = new Date()
// 返回当前时间戳
Date.parse(newDate)
- 利用转义符进行转义
// 使用“+”对时间对象进行转义
let newDate = +new Date()
将时间戳转换为Date对象
- 实例化一个Date对象,并将13位的时间戳传入
//let newDate = new Date(1538148600000)
let newDate = new Date(时间戳)
- 使用Date.setTime(),设置Date对象的时间为时间戳的时间
// 时间戳
let timestamp = 1538148600000
// 实例一个时间戳对象
let newDate = new Date()
// 设置Date对象的时间为时间戳的时间
newDate.setTime(tiemstamp)
实例1:格式化时间戳
将时间戳转换为日期,时间格式为:'yyyy-MM-dd hh:mm:ss'
9 属性 (RegExp) (JavaScript)
/*
* value为时间戳,fmt为时间格式('yyyy-MM-dd hh:mm:ss')
* @param { Number | Date } value
* @param { String } fmt
* 格式化完成的时间
* @return { String } fmt
*/
const dateFmt = (value, fmt) => {
if(typeof value !== undefined) {
value = new Date(value)
const fmtObj = {
'M+': value.getMonth() + 1, // 月份
'd+': value.getDate(), // 日期
'h+': value.getHours(), // 小时
'm+': value.getMinutes(), // 分钟
's+': value.getSeconds(), // 秒
'q+': Math.floor((value.getMonth() + 3) / 3), //季度
'S': value.getMilliseconds() // 毫秒
}
if (/(y+)/.test(fmt)) {
// fmt = fmt.replace(Reg.Exp.$1,(value.getFullYear() + '').substr(4 - RegExp.$1.length));
fmt = fmt.replace(/(y+)/, (value.getFullYear() + '').substr(4 - RegExp.$1.length))
}
for (let key in fmtObj) {
let regExp = new RegExp('(' + key + ')')
if (regExp.test(fmt)) {
//fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (fmtObj[key]) : (('00' + fmtObj[key]).substr(('' + fmtObj[key]).length)))
fmt = fmt.replace(regExp, (RegExp.$1.length === 1) ? fmtObj[key] : (('00' + fmtObj[key]).substr(('' + fmtObj[key]).length)))
}
}
return fmt
}
}
const fmt = "yyyy-MM-dd hh:mm:ss"
const timestamp = 1538148600000
const date = dateFmt(timestamp, fmt) // "2018-09-28 23:30:00"
实例2:计算两个时间戳或 Date对象 相隔多少天
/*
* 计算time1和time2相隔时间,精确到‘日’
* @param { String | Date } time1
* @param { String | Date } time2
* @return { Number } (time2 - time1) / (24 * 60 * 60 * 1000)
*/
const diffDay = function (time1, time2) {
// 如果 time1 或者 time2 不是Date对象则将其转换为Date对象
const time1 = time1 instanceof Date ? time1 : new Date(time1)
const time2 = time2 instanceof Date ? time2 : new Date(time2)
time1.setHours(0)
time1.setMinutes(0)
time1.setSeconds(0)
time1.setMilliseconds(0)
time2.setHours(0)
time2.setMinutes(0)
time2.setSeconds(0)
time2.setMilliseconds(0)
/*
*如果是负数说明 time2 比 time1 早。如 -1,则说明早了一天,即 time1 是今天,则 time2 是昨天。
*如果是正数说明 time2 比 time1 晚。如1,则说明晚一天,即 time1 是今天,则 time2 是明天。
*/
return (time2 - time1) / (24 * 60 * 60 * 1000)
}
实例3:将时间戳或者Date对象转换为对应的日期
/*
* 计算 value 的日期,返回值可能为“昨天 00:00”,“今天 00:00”,“明天 00:00”,
* “**月**日 00:00”,“****年**月**日 00:00”,精确到分钟
* @param { String | Date } value
* @return { String } result
*/
const moment = (value) => {
if(typeof value !== undefined) {
const today = new Date()
let result = ''
value = value instanceof Date ? value : new Date(value)
// 调用实例2的diffDay()方法
const diff = diffDay(today, value)
// 设置日期
if (diff === -1) {
result = '昨天'
} else if (diff === 0) {
result = '今天'
} else if (diff === 1) {
result = '明天'
} else if (Math.abs(diff) >= 365) {
result = value.getFullYear() + '年' + (value.getMonth() + 1) + '月' + value.getDate() + '日'
} else {
result = (value.getMonth() + 1) + '月' + value.getDate() + '日'
}
// 设置小时和分钟
let hours = value.getHours()
let minutes = value.getMinutes()
hours = hours >= 10 ? hours : '0' + hours
minutes = minutes >= 10 ? minutes : '0' + minutes;
result += ' ' + hours + ':' + minutes
return result
} else {
return false
}
}
// 传入时间戳 1538148600000
let result = moment(1538148600000) // "9月28日 23:30"
RegExp.9
非标准2, 4, 6, 8, $9 属性是包含括号子串匹配的正则表达式的静态和只读属性。(该特性是非标准的,请尽量不要在生产环境中使用它!)
语法
// RegExp.$_,与正则表达式匹配的完整字符串。
RegExp.$_
// RegExp.$n,(n为1-9之间的数值)指的是与正则表达式匹配的第n个子匹配(以括号为标志)字符串
RegExp.$1
RegExp.$2
RegExp.$3
RegExp.$4
RegExp.$5
RegExp.$6
RegExp.$7
RegExp.$8
RegExp.$9
描述
- 9 属性是静态的, 他不是独立的的正则表达式属性. 所以, 我们总是像这样子使用他们RegExp.9.
- 属性的值是只读的而且只有在正确匹配的情况下才会改变.
- 括号匹配项是无限的, 但是RegExp对象能捕获的只有九个. 你可以通过返回一个数组索引来取得所有的括号匹配项.
- 这些属性可以在String.replace 方法中替换字符串. 在这种情况下,不用在前面加上RegExp。下面的例子将详细说明. 当正则表达式中不包含括号, 脚本中的 $n's 就是字面上的意思 (当n是正整数).
例子
使用replace()去匹配一个 first last 格式的 name String 实例,然后输出 last first 格式。在替换文本中,用 2 表示正则表达式中括号匹配项的结果。
let regExp = /(\w+)\s(\w+)/
let str = 'Jianran Lin'
str.replace(regExp, '$2 '+ '$1') // "Lin Jianran"
console.log(RegExp.$1) // "Jianran"
console.log(RegExp.$2) // "Lin"
技术指标
非标准,不属于当前的任何规范