总结一下在工作中经常遇到的一些js处理方法。
# 数组去重
var deduped = [ 1, 1, 'a','a' ].filter(function (el, i, arr) {
return arr.indexOf(el) === i;
});
console.log(deduped); // [ 1, 'a']
# es6
var deduped = [ 1, 1, 'a','a' ].filter( (el, i, arr) => arr.indexOf(el) ===i );
# Objects
当元素为对象(Object)时,我们就不能用这种办法了, 因为对象存储的是引用而原始变量存储的是值。
{ a: 1 } === { a: 1 } // false
function dedup(arr) {
var hashTable = {};
return arr.filter(function(el) {
var key = JSON.stringify(el);
var match = Boolean(hashTable[key]);
return (match ? false : hashTable[key] = true);
});
}
var deduped = dedup([
{ a: 1 },
{ a: 1 },
[ 1, 2 ],
[ 1, 2 ]
]);
console.log(deduped); // [ {a: 1}, [1, 2] ]
# 多维数组扁平化
var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]];
// 期望值[1, 2, 3, 4, 5, 6, 7, 8, 9]
# 使用concat()和apply()
var newArray = [].concat.apply([], myArray);
# 使用reduce()
var newArray = myArray.reduce(function (prev, curr) {
return prev.concat(curr);
};
# for循环
var newArray = [];
for (var i = 0; i < myArray.length; ++i) {
for (var j = 0; j < myArray.length; ++j) {
newArray.push(myArray[i][j]);
}
}
# ES6展开符
var newArray = [].concat(...myArray);
# 扁平多维数组
function flattern(arr) {
return arr.reduce((prev, next) => {
return prev.concat(Array.isArray(next) ? next : flattern(next));
}, [])
}
# 数组平均值&&中位数
# 平均值
let values = [2, 56, 3, 41, 0, 4, 100, 23];
let sum = values.reduce((prev, curr) => curr += prev);
let avg = sum / values.length;
// avg = 28
# 中位数
let values = [2, 56, 3, 41, 0, 4, 100, 23];
values.sort((a, b) => a - b);
let lowMiddle = Math.floor((values.length - 1) / 2);
let highMiddle = Math.ceil((values.length - 1) / 2);
let median = (values[lowMiddle] + values[highMiddle]) / 2;
// median = 13.5
如果是对象的话,JavaScript将引用按值传递。
# JS监听document是否加载完成
if (document.readyState === 'complete') {
// 页面已完全加载
}
使用document.readyState === 'interactive'监听DOM是否加载完成。
# 判断数据元素是否重复
var isRepeat = function(arr){
var hash = {};
for(var i in arr) {
if(hash[arr[i]]) return true;
hash[arr[i]] = true;
}
return false;
}
# 生成随机数
function randombetween(min, max) {
return min + (Math.random() * (max - min + 1));
}
# javascript对象浅拷贝&深拷贝
;(function(){
var obj = { a: 1, b: { c: 2} };
var copy = Object.assign({}, obj); // 拷贝源对象自身的并且可枚举的属性
console.log(copy); // { a: 1, b: { c: 2} }
var deepCopy = JSON.parse(JSON.stringify(obj));
copy.a = 2;
copy.b.c = 3;
console.log(obj); // { a: 1, b: { c: 3} }
console.log(copy); // { a: 2, b: { c: 3} }
console.log(deepCopy); // { a: 1, b: { c: 2} }
deepCopy.a = 4;
deepCopy.b.c = 5;
console.log(obj); // { a: 1, b: { c: 3} }
console.log(copy); // { a: 2, b: { c: 3} }
console.log(deepCopy); // { a: 4, b: { c: 5} }
}());
function deepCopy(obj) {
if(typeof obj !== 'object') return;
let newObj = obj instanceof Array ? [] : {};
for(let k in obj) {
if(obj.hasOwnProperty(k)) {
newObj[k] = typeof obj[k] === 'object' ? deepCopy(obj[k]) : obj[k];
}
}
}
# 判断变量是否为数组
// es5方法 Array.prototype.isArray();
// 通用判断类型方法
function isArray(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
// [[NativeBrand]]内部属性的值一共有十几种.分别是:"Array", "Boolean", "Date", "Error", "Function", "Math", "Number", "Object", "RegExp", "String","JSON","Arguments". // es6: "Map","Set","Symbol"
}
# 打乱数租
# 方法一
function isArray(a) {
return Object.prototype.toString.call(a) === '[object Array]';
}
/**
* sort方法在 arr.length < 10 的情况下是采用插入排序,超过10的情况下使用快速排序和插入排序的混合排序。所以并不是真正所有概率相同的乱序。
*/
function shuffle(arr) {
if(!isArray(arr)) return;
return arr.sort(() => 0.5 - Math.random());
}
shuffle([1,2,3,4,5]);
# 方法二
function shuffle(arr) {
for(let i = arr.length;i;i--) {
let j = Math.floor(Math.random() * i);
[arr[i - 1], arr[j]] = [arr[j], arr[i - 1]];
}
return arr;
}
# 判断 NaN 和 NaN 为相等
function eq(a, b) {
if(a !== a) return b !== b;
}
eq(NaN, NaN); // true
# 判断 0 和 -0 不等
0 === -0; // true
function eq(a, b) {
if(a === b) return a !== 0 || 1 / a === 1 / b;
return false;
}
eq(0, 0); // true
eq(0, -0); // false
# 防抖
/**
* 持续触发事件,在事件触发 delay ms 后才执行,如果在一个事件触发的 delay ms 内又触发了这个事件,那就以新的事件的时间为准, delay ms 后才执行。
* @param fun 要执行的函数
* @param delay 延迟时间
*/
function debounce(fun, delay) {
var timeout;
return function() {
var context = this;
var args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
fun.apply(context, args);
}, delay);
}
}
# 节流
/**
* 持续触发事件,每隔一段时间,只执行一次事件。
* @param fun 要执行的函数
* @param delay 延迟时间
* @param time 在 time 时间内必须执行一次
*/
function throttle(fun, delay, time) {
var context, args;
var timeout;
var previous = +new Date();
return function() {
var now = +new Date();
context = this;
args = arguments;
clearTimeout(timeout);
if(now - previous >= time) {
fun.apply(context, args);
previous = now;
} else {
timeout = setTimeout(fun, delay);
}
}
}
# 继承
function create (obj) {
function F() {}
F.prototype = obj
return new F()
}
function inherit (child, parent) {
const prototype = create(parent.prototype)
prototype.constructor = child
child.prototype = prototype
}
# polyfill
# call
Function.prototype.call2 = (context) {
var context = context || window;
context.fn = this;
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
}
var result = eval('context.fn(' + args + ')');
delete context.fn;
return result;
}
# apply
Function.prototype.apply2 = (context, arr) {
var context = context || window;
context.fn = this;
var result;
if(!arr) {
result = context.fn();
} else {
var args = [];
for(var i = 1, len = arr.length; i < len; i++) {
args.push('arr[' + i + ']');
}
result = eval('context.fn(' + args + ')');
}
delete context.fn;
return result;
}
# bind
Function.prototype.bind2 = (context) {
if(typeof this !== 'function') {
throw new Error('what is trying to be bound is not callable');
}
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
# new
function new2() {
var obj = new Object();
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
return obj;
}
# Object.create()
function create(obj) {
function F() {};
F.prototype = obj;
return new F();
}