去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//第一种方法
Array.prototype.unique = function () {
//在原型上加方法
var res = [];
var json = {};
for (var i = 0; i < this.length; i++) {
if (!json[this[i]]) {
//是否存在
res.push(this[i]);
json[this[i]] = 1; //保存了
}
}
return res;
};
var arr = [112, 112, 34, "你好", 112, 112, 34, "你好", "str", "str1"];

console.log(arr.unique()); //[112, 34, "你好", "str", "str1"]

//2.
//判断是否第一个index,返回第一出现的值
let uniqueArr = arr.filter((item, index, arr) => arr.indexOf(item) == index);
console.log(uniqueArr); //[112, 34, "你好", "str", "str1"]

//3.es6 Set方法
let a = [...new Set(arr)];
console.log(a); //[112, 34, "你好", "str", "str1"]

防抖与节流

JS 的防抖与节流

防抖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function debounce(fn, wait) {
var 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));

节流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//节流
var throttle = function (func, delay) {
var timer = null;
var startTime = Date.now();
return function () {
var curTime = Date.now();
var remaining = delay - (curTime - startTime);
var context = this;
var args = arguments;
clearTimeout(timer);
if (remaining <= 0) {
func.apply(context, args);
startTime = Date.now();
} else {
// 超1s多出时间执行
timer = setTimeout(func, remaining);
}
};
};
function handle() {
console.log(Math.random());
}
//当第一次触发事件时马上执行事件处理函数,最后一次触发事件后也还会执行一次事件处理函数
window.addEventListener("scroll", throttle(handle, 3000));

多级数组变一级(扁平)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var arr = [1, 2, 3, 4, ["a", 55, [111, { name: "bbb" }]]];
var empty = [];
function flat(arr) {
arr.forEach((item) => {
if (typeof item === "string" || typeof item === "number") {
empty.push(item);
} else if (Array.isArray(item)) {
//判断数组 1.typeof item ==='object' &&item instanceof Array
// 2. Object.prototype.toString.call(item)==='[object Array]'
flat(item);
} else {
empty.push(item);
}
});

return empty;
}

console.log(flat(arr)); // [1, 2, 3, 4, "a", 55, 111, {"name":'bbb'}]

千分符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
var str = "3562123761"; //[3,562,123,761]

function test(str) {
var iNum = str.length % 3;

var prev = "";
var arr = [];
var iNow = 0;
var tmp = "";

if (iNum != 0) {
//不是三的整除,先放在数组
prev = str.substring(0, iNum);
arr.push(prev);
}
str = str.substring(iNum);

for (var i = 0; i < str.length; i++) {
iNow++;
tmp += str[i];

if (iNow == 3 && tmp) {
arr.push(tmp); //三个数字一组
tmp = "";
iNow = 0;
}
}
//console.log(arr)
return arr.join(",");
}

console.log(test(str));

//正则
//(?=)前项声明
//(?!)反前向声明
//例子
var str1 = "abacad";
var re = /a(?=b)/g;
str1 = str1.replace(re, "*");
console.log(str1); //*bacad

var re2 = /a(?!b)/g;
var str2 = str1.replace(re2, "*");
console.log(str2); //*b*c*d

function test2(str) {
var re = /(?=(?!\b)(\d{3})+$)/g; //边界不能替换
return str.replace(re, ",");
}

console.log(test2(str)); //3,562,123,761

驼峰命名法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var str = "border-bottom-color";
function test(str) {
var arr = str.split("-"); //[border,bottom,color]
for (var i = 1; i < arr.length; i++) {
arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
}
return arr.join("");
}
console.log(test(str)); //borderBottomColor

//2.正则
function test2(str) {
var re = /-(\w)/g;
return str.replace(re, function ($0, $1) {
//-b b
return $1.toUpperCase();
});
}

console.log(test2(str)); //borderBottomColor

排序

Javascript 常见排序算法的笔记

从小到大排序

冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var arr = [15, 55, 99, 77, 8, 0, 2];
let time = 0;

function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - 1 - i; j++) {
time++;
if (arr[j] > arr[j + 1]) {
var temp;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}

console.log(time); //21
console.log(bubbleSort(arr)); //[0, 2, 8, 15, 55, 77, 99]

二分法排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const Arr = [85, 24, 63, 45, 17, 31, 96, 50];

function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
let pivotIndex = Math.floor(arr.length / 2);
let pivot = arr.splice(pivotIndex, 1)[0];
let left = [];
let right = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
// 递归
return quickSort(left).concat([pivot], quickSort(right));
}
console.log(quickSort(Arr)); //[17, 24, 31, 45, 50, 63, 85, 96]

添加 class

1
2
3
4
5
6
7
8
9
10
11
12
function addClass(el, className) {
//加class
let reg = new RegExp("(^|\\s)" + className + "(\\s|$)"); //"className" 或者 “ className ”
if (reg.test(el.className)) {
//判断是否有class
return;
}
//加上class名
let newClass = el.className.split(" "); //拆分
newClass.push(className); //添加
el.className = newClass.join(" "); //字符串
}

设置 data 节点属性

1
2
3
4
5
6
7
function getData(el, name, val) {
const prefix = "data-";
if (val) {
return el.setAttribute(prefix + name, val); //设置
}
return el.getAttribute(prefix + name); //获取
}

浏览器 css 前缀的兼容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//设置浏览器的兼容
function prefixStyle(style) {
let elementStyle = document.createElement("div").style;
//供应商
let vendor = (() => {
let transformNames = {
webkit: "webkitTransform",
Moz: "MozTransform",
O: "OTransform",
ms: "msTransform",
standard: "transform",
};
for (let key in transformNames) {
if (elementStyle[transformNames[key]] !== undefined) {
return key; //返回前缀
}
}
return false;
})();

if (vendor === false) {
return false;
}

if (vendor === "standard") {
//标准,没有前缀
return style;
}

return vendor + style.charAt(0).toUpperCase() + style.substr(1); //驼峰命名
}

//测试
alert(prefixStyle("transform")); // webkitTransform (谷歌浏览器 webkit内核)

获取 DOM 大小和位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function getRect(el) {
if (el instanceof window.SVGElement) {
let rect = el.getBoundingClientRect();
return {
top: rect.top,
left: rect.left,
width: rect.width,
height: rect.height,
};
} else {
return {
top: el.offsetTop,
left: el.offsetLeft,
width: el.offsetWidth,
height: el.offsetHeight,
};
}
}

对象

hasOwnProperty

对象本身的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//构造函数
function Foo(name) {
this.name = name;
}
Foo.prototype.alertName = function () {
alert(this.name);
};
// 创建示例
var f = new Foo("小明");
f.printName = function () {
console.log(this.name); //小明
};
//测试
f.printName();
f.alertName();
f.toString(); //要去f.__proto__.__proto__中查找
var item;
for (item in f) {
//高级浏览器已经在 for in 中 屏蔽了来自原型的属性
//但是这里还是建议大家还是加上这个判断,保证程序的健壮性
if (f.hasOwnProperty(item)) {
console.log(item); // name printName
}
}

原型链

原型链

instanceof
用于判断引用类型属于哪个构造函数的方法

  • f instanceof 的判断逻辑是:
  1. f 的proto一层一层往上,能否找打对应到 Foo.prototype
  2. 再试判断 f instanceof Object

instanceof

变量 属于 数组

1
2
3
var arr = [];
arr instanceof Array; //true
typeof arr; //object, typeof 是无法判断是否是数组的

例子

DOM 操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Elem(id) {
this.elem = document.getElementById(id);
}
Elem.prototype.html = function (val) {
//设置/获取innerHTML
var elem = this.elem;
if (val) {
elem.innerHTML = val;
return this; //链式操作
} else {
return elem.innerHTML;
}
};
Elem.prototype.on = function (type, fn) {
//绑定事件
var elem = this.elem;
elem.addEventListener(type, fn);
return this;
};
let div1 = new Elem("div1"); //获取设置id类

//console.log(div1.html()) //innerHTML
div1.html("<p>hello world</p>").on("click", function () {
alert("clicked");
});

深层拷贝

1
2
3
4
5
6
7
function deepClone(obj) {
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
newObj[key] = typeof obj[key] === "object" ? deepClone(obj[key]) : obj[key];
}
return newObj;
}

日期

Date.now() //获取当前毫秒数 1531824326654
new Date().getTime()//获取毫秒数

1
2
3
4
5
6
7
8
9
10
11
12
13
function getTime() {
var dt = new Date(); //中国标准时间
var year = dt.getFullYear(); //年
var month = dt.getMonth() + 1; //月(0-11)
var date = dt.getDate(); //日(0-31)
var hour = dt.getHours(); //时(0-23)
var minute = dt.getMinutes(); //分 (0-59)
var second = dt.getSeconds(); //秒 (0-59)
return (
year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second
);
}
getTime(); //2018-6-17 18:58:22

递归

阶乘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//书P70 可以被es6引擎优化
//阶乘
function factorial(n, p = 1) {
if (n <= 1) {
return 1 * p;
} else {
let result = n * p;

//优化后
return factorial(n - 1, result);
}
}

factorial(3); //6

##菲波那契

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//菲波那契
//1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144
function fibo(n) {
if (n >= 2) {
return fibo(n - 1) + fibo(n - 2);
} else {
return n;
}
}

fibo(3); //2

//最优解
// 菲波那契可能是最普通的解法
var series = function (n) {
var sum = [0, 1];
if (n < 2) {
return sum[n];
}

var firstNum = 0;
var secondNum = 1;
var total = 0;
for (var i = 2; i <= n; i++) {
total = firstNum + secondNum;
firstNum = secondNum;
secondNum = total;
}
return total;
};

浏览器内置对象

navigator.userAgent 浏览器代理器名称

location

例子
location.href=’跳转的地址’
https://www.baidu.com/index.html?id=99&a=b#mid=100

location
location.protocolhttps:
location.pathname/index.html
location.search?id=99&a=b
location.hash#mid=100

事件

event. stopPropagatio()是阻止冒泡事件的方法,
在 ie 浏览器上没有 stopPropagatio()这个方法,
在 ie 上要用 e.cancelBubble=true 阻止冒泡事件

1
2
3
4
5
6
7
8
9
function stopPropagation(event) {
var e = window.event || event;
if (document.all) {
e.cancelBubble = true;
} else {
e.stopPropagation(); //阻止冒泡
e.preventDefault(); // 取消默认行为
}
}

事件委托代理

1
2
3
4
5
6
7
8
9
10
<div id="div1"><a href="">这是a标签</a></div>
<script>
let div1 = document.getElementById("div1");
div1.addEventListener("click", function (e) {
let target = e.target;
if (target.nodeName === "A") {
alert(target.innerHTML);
}
});
</script>

完善封装代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function bindEvent(elem, type, selector, fn) {
if (fn == null) {
//3个参数
fn = selector;
selector = null;
}
elem.addEventListener(type, function (e) {
var target;
if (selector) {
//四个参数(代理)
target = e.target;
console.log(target);
if (target.matches(selector)) {
fn.call(target, e);
}
} else {
//没有代理
fn(e);
}
});
}

//使用代理
var div1 = document.getElementById("div1");
bindEvent(div1, "click", "a", function (e) {
console.log(this.innerHTML);
});
//不使用代理
// var a=document.getElementById('a1')
// bindEvent(div1,'click',function(e){
// console.log(a.innerHTML)
// })

ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var xhr = new XMLHttpRequest();
xhr.open("GET", "/api", false);
xhr.onreadystatechange = function () {
//这里的函数异步执行
if ((xhr.readyState = 4)) {
//ajax状态码
if (xhr.status == 200) {
//http请求状态码
alert(xhr.responseText);
}
}
};

xhr.send(null);

AMD

异步模块定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//1.util.js
define(function () {
var util = {
getFormatData: function (date, type) {
if (type === 1) {
return "2018-06-20";
}
if (type === 2) {
return "2018年6月20日";
}
},
};
return util;
});
//2.a-util.js
define(["./util.js"], function (util) {
var aUtil = {
aGetFormatDate: function (date) {
return util.getFormatData(date, 2);
},
};
return aUtil;
});
//3.a.js
define(["./a-util.js"], function (util) {
var a = {
printDate: function (date) {
console.log(util.aGetFormatDate(date));
},
};
return a;
});
//4.main.js
require(["./a.js"], function (a) {
var date = new Date();
a.printDate(date); //2018年6月20日
});

使用 data-main

1
2
3
4
<script
src="https://cdn.bootcss.com/require.js/2.3.4/require.min.js"
data-main="./main.js"
></script>

运动

运动的 tool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
function getStyle(ele, attr) {
//获取样式
if (ele.currentStyle) {
return ele.currentStyle[attr];
} else {
return getComputedStyle(ele, false)[attr];
}
}

function startMove(ele, obj, fn) {
clearInterval(ele.timer);
ele.timer = setInterval(function () {
var bStop = true; //这一次运动就结束了――所有的值都到达了
for (var attr in obj) {
//1.取当前的值
var iCur = 0;

if (attr == "opacity") {
iCur = parseInt(parseFloat(getStyle(ele, attr)) * 100);
} else {
iCur = parseInt(getStyle(ele, attr));
}

//2.算速度
var iSpeed = (obj[attr] - iCur) / 8;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);

//3.检测停止
if (iCur != obj[attr]) {
bStop = false;
}

if (attr == "opacity") {
ele.style.filter = "alpha(opacity:" + (iCur + iSpeed) + ")";
ele.style.opacity = (iCur + iSpeed) / 100;
} else {
ele.style[attr] = iCur + iSpeed + "px";
}
}

if (bStop) {
clearInterval(ele.timer);

if (fn) {
fn();
}
}
}, 30);
}

//例子
// let div1=document.getElementById('div1')
// startMove(div1,{height:300},function(){ //高度变化300px
// cosnole.log('运动完成')
// })

vue 中 ajax

直接返回 data 数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const axios = require("axios");

module.exports = function ajax(url = "", data = {}, type = "GET") {
return new Promise(function (resolve, reject) {
let promise;

if (type === "GET") {
// 准备url query参数数据
let dataStr = ""; //数据拼接字符串
Object.keys(data).forEach((key) => {
dataStr += key + "=" + data[key] + "&";
});
if (dataStr !== "") {
dataStr = dataStr.substr(0, dataStr.lastIndexOf("&"));
url = url + "?" + dataStr;
}
// 发送get请求
promise = axios.get(url);
} else {
// 发送post请求
promise = axios.post(url, data);
}

promise
.then((response) => {
resolve(response.data);
})
.catch((error) => {
reject(error);
});
});
};

日期

根据时间获取是第几个周

1
2
3
4
5
6
7
8
9
10
function getWeekNumber(t) {
let date = t ? new Date(`${t}`) : new Date();
// 将date设置为该年的第一天(通常是1月1日)
const yearStart = new Date(date.getFullYear(), 0, 1);
// 计算date与年份第一天的天数差
const diffDays = Math.floor((date - yearStart) / (24 * 60 * 60 * 1000)); // 将毫秒转换为天数
// 计算周数,加1是因为我们从1开始计数周,而不是从0
const weekNumber = Math.ceil((diffDays + yearStart.getDay() + 1) / 7);
return weekNumber;
}