js常使用的工具函数
序列号格式化输出
1  | /**  | 
查找数组中是否存在某个属性值,存在就返回
1  | /**  | 
jQuery如何扩展自定义方法
1  | (jQuery.fn.myMethod=function () {  | 
冒泡排序
1  | /**  | 
判断一个字符串中出现次数最多的字符,统计这个次数
1  | let str = 'asdfssaaasasasasaa';  | 
去掉一个数组的重复元素
- 计数排序变形
 - 使用 Set
 - 使用 WeakMap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 方法1
let arr = [2, 3, 4, 4, 5, 2, 3, 6];
function getNewArr(arr) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) < 0) {
newArr.push(arr[i]);
};
};
console.log('新的数组' + newArr);
}
getNewArr(arr);
// 方法2
let newArr = arr.filter(function(ele, index, self) {
return self.indexOf(ele) === index;
}); 
去除字符串前后的空格
1  | String.prototype.trim = function() {  | 
判断一个数字是不是整数
1  | function isInt(num) {  | 
获取浏览器的地址参数
1  | function getUrlParams(url) {  | 
JS递归算法1+ 2+3…..100的和
1  | function num(n) {  | 
找出一组数据中的奇数和偶数,偶数乘以2,并从小到大排列,奇数从大到小排列,最后合并数组
1  | var arr = [4, 3, 8, 6, 2, 9, 1];  | 
根据json对象的某一属性对其进行排序
https://www.cnblogs.com/ygtq-island/p/6512728.html
1  | var json = {  | 
js返回两个数组的差异值
1  | // 普通算法  | 
某年某月的1号为星期几
1  | var weekDay = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];  | 
数据的排序 123454321 23456765432
1  | // 方法1  | 
首字母大写
1  | /**  | 
深拷贝
- 递归
 - 判断类型
 - 检查环(也叫循环引用)
 - 需要忽略原型
理解深浅拷贝,需了解 
- 基本类型–名值存储在栈内存中,例如let a=1

 - 引用数据类型–名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14function deepCopy(obj) {
// 判断是否是简单数据类型,
if (typeof obj == 'object') {
//复杂数据类型
var result = obj.constructor == Array ? [] : {};
for(let i in obj) {
result[i] = typeof obj[i] == 'object' ? deepCopy(obj[i]) : obj[i];
}
} else {
//简单数据类型 直接 == 赋值
var result = obj;
}
return result;
} 
将类数组转化为数组
1  | function trigger() {  | 
使用 Array的 slice 进行数组复制( 浅复制)
1  | var items = [1, 2, 3];  | 
使用 for-in 循环时需要避免对象从原型链上继承来的属性也被遍历出来,因此保险的做法是对 key 是否是对象自身的属性进行验证
1  | // good  | 
if(a === 1 || a === 2 || a === 3){}推荐写法
1  | [1, 2, 3].indexOf() || /^(1|2|3)$/.test()  | 
三位数字分离与合并的相互转化
1  | function numSplit(val) {  | 
抽离出相同类型的数据
1  | // es6  | 
1  | let _typeArr = []; // 枢纽展示类型  | 
1  | // es5的处理  | 
函数防抖和函数节流
节流(一段时间执行一次之后,就不执行第二次)
注意 认为节流函数不是立刻执行的,而是在冷却时间末尾执行的(相当于施法有吟唱时间),那样说也是对的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function throttle(fn, delay) {
let canUse = true;
return function() {
if (canUse) {
fn.apply(this, arguments);
canUse = false;
setTimeout(() => {
canUse = true;
}, delay)
}
}
}
const throttled = throttle(() => console.log('hi'));
throttled();
throttled();防抖(一段时间会等,然后带着一起做了)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function debounce(fn, delay) {
let timerId = null;
return function() {
const context = this;
if (timerId) {
window.clearTimeout(timerId);
}
timerId = setTimeout(() => {
fn.apply(context, arguments);
timerId = null;
}, delay)
}
}
const debounced = debounce( () => console.log('hi'))
debounced()
debounced()
手写AJAX
1  | var request = new XMLHttpRequest();  | 
事件委托
1  | // 简单版本  | 
用 mouse 事件写一个可拖曳的 div
快速看到效果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
28var dragFlag = false;
var position = null;
drag.addEventListener('mousedown', function(e) {
  dragFlag = true;
  position = [e.clientX, e.clientY];
})
// mousemove 与 mouseup 不能监听在元素上 快速拖到会有问题
document.addEventListener('mousemove', function(e) {
 if (dragFlag) {
    return;
  }
  const x = e.clientX;
  const y = e.clientY;
  const deltaX = x - position[0];
  const deltaY = y - position[1];
  // parseInt('')空转为 NaN
  // drag.style.left初始值为'0px'
  const left = parseInt(drag.style.left || 0, 10);
  const top = parseInt(drag.style.top || 0, 10);
  drag.style.left = left + deltaX + 'px';
  drag.style.top = top + deltaY + 'px';
  position= [x, y];
})
document.addEventListener('mouseup', function() {
    dragFlag = false;
})
filter方法
- 不会对空数组进行检测,会跳过那些空元素
1
2
3
4
5
6
7
8
9
10
11let arr = [0, 3, 5];
arr[10] = 10;
arr.filter((val) => {
return val === undefined;
});
// 初始化
let array = [0, 3, 5, undefined, undefined, null, 123];
array[10] = 10;
array.filter((val) => {
return val === undefined;
}); 
join()
- javascript 在定义数组的时候允许最后一个元素后跟一个,(分号)
1
2let str = [,,,].join(); // ,,
let str = [,,1,].join('.').length; 
普通函数与箭头函数的区别
- this指向的问题,会捕获其所在上下文的this值,作为自己的this值
 箭头函数不绑定arguments,取而代之用reset参数解决
1
2
3
4
5
6
7
8
9
10// 箭头函数
let foo = (...args) => {
return args[0];
}
console.log(foo(1));
// 普通函数
fun() {
console.log(argument[0]);
}
console.log(fun(1, 34));箭头函数不能用作构造器,和new一起用就会抛出错误
- 箭头函数没有原型属性
1
2var foo = () => {};
console.log(foo.prototype) // undefined 
js常见的自认为正确的问题
1  | var array = [];  | 
- 解决问题为什么不是0,1,2
 - var声明变量,三个箭头函数体中的每个i,都指向相同的绑定,所以它们在循环结束时返回相同的值3
 - 解决方法1,把var改为let(let 声明一个具有块级作用域的变量,每个循环迭代创建一个新的绑定)
 - 解决方式2,使用闭包
1
2
3
4
5
6
7
8
9
10var array = [];
for(var i = 0; i <3; i++) {
array[i] = (function(x) {
return function() {
return x;
}
})(i);
}
var newArray = array.map(el => el());
console.log(newArray); // [3, 3, 3] 
找出字符串中第一次只出现一次的字母
1  | String.prototype.firstAppear = function () {  | 
获得滚动条的滚动距离
1  | function getScrollOffset() {  | 
获得视口的尺寸
- To Learn More…
1
2
3
4```
##### 简短函数调用
* 三元操作符来实现多个函数调用 
// Longhand
function test1() {
  console.log(‘test1’);
};
function test2() {
  console.log(‘test2’);
};
var test3 = 1;
if (test3 == 1) {
  test1();
} else {
  test2();
}
// Shorthand
(test3 === 1? test1:test2)();1
2
3
##### switch 简化
* 将条件保存在键值对象中,并根据条件来调用它们
// Longhand
switch (data) {
  case 1:
    test1();
  break;
  case 2:
    test2();
  break;
  case 3:
    test();
  break;
  // And so on…
}
// Shorthand
var data = {
  1: test1,
  2: test2,
  3: test
};
data[something] && datasomething;1
2
##### 延展操作符简化
//longhand
// joining arrays using concat
const data = [1, 2, 3];
const test = [4 ,5 , 6].concat(data);
//shorthand
// joining arrays
const data = [1, 2, 3];
const test = [4 ,5 , 6, …data];
console.log(test); // [ 4, 5, 6, 1, 2, 3]1
* 延展操作符进行克隆
//longhand
// cloning arrays
const test1 = [1, 2, 3];
const test2 = test1.slice()
//shorthand
// cloning arrays
const test1 = [1, 2, 3];
const test2 = […test1];1
2
* 如何将浮点数点左边的数每三位添加一个逗号,如 12000000.11 转化为『12,000,000.11』?
// 方法一
function format(number) {
  return number && number.replace(/(?!^)(?=(\d{3})+.)/g, “,”);
}
// 方法二
function format1(number) {
  return Intl.NumberFormat().format(number)
}
// 方法三
function format2(number) {
  return number.toLocaleString(‘en’)
}1
2
##### 求和,最小值和最大值
const array  = [5,4,7,8,9,2];
array.reduce((a, b) => a + b); // 输出: 35
array.reduce((a, b) => a > b ? a : b); // 输出: 9
array.reduce((a, b) => a < b ? a : b); // 输出: 21
2
3
##### 排序字符串,数字或对象等数组
* 内置的方法sort()和reverse()来排序字符串
const stringArr = [“Joe”, “Kapil”, “Steve”, “Musk”]
stringArr.sort();
// 输出 [“Joe”, “Kapil”, “Musk”, “Steve”]
stringArr.reverse();
// 输出 [“Steve”, “Musk”, “Kapil”, “Joe”]1
* 数字数组排序
const array  = [40, 100, 1, 5, 25, 10];
array.sort((a,b) => a-b);
// 输出 [1, 5, 10, 25, 40, 100]
array.sort((a,b) => b-a);
// 输出 [100, 40, 25, 10, 5, 1]1
* 对象数组排序
const objectArr = [
  { first_name: ‘Lazslo’, last_name: ‘Jamf’     },
  { first_name: ‘Pig’,    last_name: ‘Bodine’   },
  { first_name: ‘Pirate’, last_name: ‘Prentice’ }
];
objectArr.sort((a, b) => a.last_name.localeCompare(b.last_name));
// 输出
(3) [{…}, {…}, {…}]
0: {first_name: “Pig”, last_name: “Bodine”}
1: {first_name: “Lazslo”, last_name: “Jamf”}
2: {first_name: “Pirate”, last_name: “Prentice”}
length: 31
2
##### 从数组中过滤到虚值 (0, undefined, null, false, "", '')
const array = [3, 0, 6, 7, ‘’, false];
array.filter(Boolean);
// 输出 [3, 6, 7]`