总结的一些 function 开箱即用
正则表达式
身份证号
function isIdCard(str) {
return /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(str);}
手机号
function isPhoneNumber(str) {
return /^1[3456789]\d{9}$/.test(str);}
是否合法的http/https域名
function isHttpUrl(str) {
return /^(http|https):\/\/[^\s]+$/.test(str);}
JavaScript
判断数据类型
/**
* 类型检测函数
* 为typeof关键字的增强版,可以准确判断null,date类型
* 原理是使用V8引擎最初的toString方法观察数据类型
* @author 不爱喝橙子汁
* @version 1.0.0
* @param {Object} obj 任意对象,例如null,undefined,date
* @return {String} 类型的全小写字符串
*/function type(obj) {
return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase(); }
数组操作
数组
数组是个线性结构
在js里它没有固定的大小
它也不要求所有元素的数据类型都一样(但你最好保证他们是一样的)
创建数组的方式
字面量(推荐)
const nums = [1, 2, 3];
使用Array里的静态方法
const strs = Array.from('Hello World')
API
javascript的数组实现了栈和队列
追加一个元素
num.push(10)
追加多个元素
num.push(11,15)
在数组前面加一个元素
strs.unshift('a')
在数组尾巴删除一个元素
num.pop()
在数组头部删除一个元素
strs.shift()
注意以上都是命令性的操作,虽然他们都有返回值但最好不用使用他们(对于追加来说会返回你追加的元素,对于弹出来说会返回弹出来的元素)
指定区间
nums.slice(1,3); // 从1到3
记得是左闭右开区间!!!
映射
nums.map(x => x * 2) // 获取所有元素都乘2了的版本
过滤
nums.filter(x => x % 2 === 0) // 只要偶数
累积
nums.reduce((result x) => result + x, 0);
反转
strs.reverse()
拼成字符串
strs.join('')
以上为 函数式操作,不会更改原有数组,它的返回值才是有意义的结果。
获取长度
num.length
把nums.length复制为0可以清空数组
索引一项
使用下标索引即可
nums[nums.length-1]; // 最后一个元素
节流与防抖函数
/**
* 节流
* 在给定时间内只有第一次的操作会返回结果
* 结合了防抖的思路:在delay时间内生成定时器,一旦到了delay的时间就返回结果
* 当用户只点击了一次的时候,在delay时间后得到结果
* 当用户点击了多次的时候,在delay时间后得到第一次的结果,其余的被节流阀忽视掉
* @author 不爱喝橙子汁
* @version 1.0.0
* @param {Function} fn 要包装的回调函数
* @param {number} delay 延迟时间,单位ms,默认500
* @return {Function} 被节流函数劫持的新的函数
*/function throttle(fn, delay = 500) {
let last = 0;
let timer = null;
return function () {
let args = arguments;
let now = +new Date();
let context = this;
if (now - last < delay) {
clearTimeout(timer);
timer = setTimeout(() => {
last = now;
fn.apply(context, args);
}, delay);
} else {
last = now;
fn.apply(context, args);
}
}}
/**
* 防抖
* 在delay时间后得到结果
* 如果没等到delay的时间一直触发则永远也得不到结果
* @author 不爱喝橙子汁
* @version 1.0.0
* @param {Function} fn 要包装的回调函数
* @param {number} delay 延迟时间,单位ms,默认500
* @return {Function} 被防抖函数劫持的新的函数
*/function debounce(fn, delay = 500) {
let timer = null;
return function () {
let args = arguments;
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
}}
this怎么就不对
this指向问题
this应该是第一个让人对JavaScript困惑的问题了,但是实际上它的原理非常简单:函数的this在运行时绑定。
什么叫运行时绑定?就是函数的this和你写在哪里无关,而是和谁调用它有关。谁调用这个函数,this就指向谁。
你现在大概会在想:原来这么简单,我精通了!
那可就大错特错了,可千万别忘了光函数的调用方法就有两种:直接调和new一个,而能做这两个操作的地方可以说非常的多,所以还需要往下看。
注意:以下例子均为严格模式下运行,非严格模式这里不做考虑。
初级
function f1 () {
console.log(this)}f1();
问结果是什么?先问自己:谁调用的它?你应该一下看不出来,这明明就是直接调的啊!可能有的基础比较扎实的人会说是window,那真是非常的恭喜你了,但你要注意的是以上代码在严格模式下是undefined。
正解: window / undefined
const foo = {
bar: 10,
fn: function() {
console.log(this)
console.log(this.bar)
}}let fn1 = foo.fnfn1()
结果是什么?你可能一眼看到fn是定义在foo对象里,那this可不就是foo吗,刚刚说什么来着,先问自己:谁调用的它,来看最后一行再回答一遍。
正解:window / undefined
中级
const foo = {
bar: 10,
fn: function() {
console.log(this)
console.log(this.bar)
}}foo.fn()
现在你应该已经有点感觉了,来,说出来,谁调用的它fn?
正解:foo
中级+
const person = {
name: '橙子',
brother: {
name: '河浪',
fn: function() {
return this.name }
}}console.log(person.brother.fn())
看能不能过关斩将,谁调用的fn?
正解:brother
call / bind / apply
此为3种干预this指向的操作,限于篇幅不展开讲。
箭头函数
箭头函数可以让你省很多事,因为它的this一般来说都是符合你的直觉的:它的this就是定义时候的this。
计算地图上两点间的距离
计算地图上两点距离
/**
* 获取地图上两点间距离。单位:米
* @param {lat1} 第一个点的纬度
* @param {lon1} 第一个点的经度
* @param {lat2} 第二个点的纬度
* @param {lon2} 第二个点的经度
* @author 不爱喝橙子汁
*/export function getDistance(lat1, lon1, lat2, lon2) {
const radLat1 = (lat1 * Math.PI) / 180.0;
const radLat2 = (lat2 * Math.PI) / 180.0;
const a = radLat1 - radLat2;
const b = (lon1 * Math.PI) / 180.0 - (lon2 * Math.PI) / 180.0;
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * 6378137;
s = Math.round(s * 10000) / 10000;
return s;}
css
我要超出显示省略号
单行显示
.oneline {
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
-webkit-box-orient: horizontal;
-webkit-line-clamp: 1;
line-clamp: 1;
display: -webkit-box;}
两行显示
.twoline {
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
line-clamp: 2;
display: -webkit-box;}
其他的自己类推吧
关键帧与动画
CSS关键帧与动画
动画的原理
即静态图片的快速切换,快到人眼分辨不出来的时候就可以产生连续移动动画的效果。
需要多快
对于纯静态图片来说,需要一秒切换三十张(游戏的CG),对于拍摄来说,需要一秒切换24张(电影)。
因为摄像机拍出来的东西并不是纯静态的,它的每一帧包含有它的上一帧和下一帧的部分信息(比如如果说风扇再转,拍摄出来的效果的每一张截图都是模糊的,相反赛车游戏,你截屏的每一张都是清晰的风景壁纸)
帧
通解即最小单元,这个概念在网络上也同样适用,在这里就是构成动画的每一张静态图片。
关键帧
对于早期动画来说,例如《大闹天宫》,30帧的动画几乎每一帧都是画出来的,但是现在在计算机的帮助下不需要了,计算机可以自动推算补帧,而你需要给出的是关键帧,关键帧与关键帧之间的动画则由计算机自己脑补。比如第一个关键帧说盒子在左边,第二个关键帧说盒子在右边,那么计算机会自动补齐从左到右的移动过程。
实战一下
HTML部分
<body>
<div class="box"></div></body>
非常简单,一个盒子就可以了
css部分
// 设置背景颜色
body {
background: #333;}.box {
background: #fff; // 设置显眼的颜色
width: 200px; // 固定宽,为了看的见
height: 200px; // 固定高,为了看的见
position: relative; // 相对定位
animation-name: myanimation; // 动画名字,指定关键帧的名字就可以,细节在下面的定义
animation-duration: 4s; // 动画持续时间,间接控制速率,越长越慢!
}// 定义关键帧
@keyframes myanimation {
// 必须。在动画开始时,关键帧的位置
0% {
background: #fff;
left: 0;
top: 0;
}
// 在动画四分之一时,关键帧的位置
25% {
background: #f00;
left: 300px;
top: 0;
}
// 在动画一半时,关键帧的位置
50% {
background: #0f0;
left: 300px;
top: 300px;
}
// 在动画四分之三时,关键帧的位置
75% {
background: #00f;
left: 0;
top: 300px;
}
// 必须,在动画结束时,关键帧的位置
100% {
background: #fff;
left: 0;
top: 0;
}}
CSS动画属性总结
动画基本属性总结
这里做复习和记忆
animation-name: myanimation; // 动画名字,指定关键帧的名字。
animation-duration: 4s; // 动画持续时间,间接控制速率,越长越慢!
animation-iteration-count: infinite; // 重复次数,可以填数字也可以填infinite,infinite代表无限重复
animation-timing-function: linear; // 动画速度,匀速
animation-delay: 2s; // 延迟2秒开始
animation-direction: reverse; // 动画方向,反向
这些属性的其他值就自己去查吧,并且注意他们也有all in one的简写形式。
过渡与动画
CSS过渡与动画
前言
过渡和关键帧均是实现动画的方式,但他们是两个系统的。他们的属性有相似性。
可被用来过渡的属性
background-color
background-position
border-color
border-width
border-spacing
bottom
color
font-size
font-weight
height
left
letter-spacing
line-height
magin
max-height
max-width
min-height
min-width
opacity
outline-color
outline-offset
outline-width
text-indent
text-shadow
z-index
word-spacing
visibility
verticle-align
...其他我懒得打的属性...
实战一下
HTML
<div class="box"></div>
CSS
body {
background: #333;}.box {
background: #fff;
width: 300px;
height: 300px;
position: relative;
margin: auto;
top: 200px;
transition-property: background, border-radius;
transition-duration: 1s;}.box:hover {
background: red;
border-radius: 50%;}
数据处理
对数组分组
把若干数组按指定的字段名进行分组
function groupBy(list, propName) {
return list.reduce((acc, item) => {
const key = item[propName];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(item);
return acc;
}, {});}
深拷贝对象
function deepClone(obj) {
if (obj === null) return null;
if (typeof obj !== 'object') return obj;
if (obj instanceof Date) {
let date = new Date();
date.setTime(obj.getTime());
return date;
}
if (obj instanceof RegExp) {
let re = new RegExp(obj.source);
re.lastIndex = obj.lastIndex;
return re;
}
let newObj = new obj.constructor();
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = deepClone(obj[key]);
}
}
return newObj;}
提取数组属性
/**
* 提取若干数组中指定字段组合成一个新数组
*/function extractProps(arr, prop) {
return arr.map((item) => item[prop]);}
提取对象属性
/**
* 提取对象中的指定的属性,返回一个新对象
*/function pickProps(obj, props) {
if (typeof obj !== 'object') {
return obj;
}
const newObj = {};
props.forEach((prop) => {
newObj[prop] = obj[prop];
});
return newObj;}