目录
1. 数组去重
1.1 indexOf
var arr=[3,5,1,6,1,3,5,6,9];
var result=[];
arr.forEach(item=>{
if(result.indexOf(item)==-1){
result.push(item);
}
})
console.log(result);
1.2 ES6 Set
var arr=[3,5,1,6,1,3,5,6,9];
var result=Array.from(new Set(arr));
console.log(result);
2. 快速排序
2.1 冒泡排序
function bubbleSort(nums){
//每轮循环都从最后一个元素开始,比较并交换 一次循环会把最小的数顶到最上面
for(let i=0;i<nums.length-1;i++){//只是控制次数为n-1
for(let j=nums.length-1;j>i;j--){
if(nums[j]){
//交换
let temp=nums[j];
nums[j]=nums[j-1];
nums[j-1]=temp;
}
}
}
//test
nums=[5,1,4,3,5];
bubbleSort(nums);
consloe.log(nums);
2.2 sort
升序x-y
var a=[3,5,2,6];
a.sort(function(x,y){
return x-y;
})
console.log(a);
降序y-x
var a=[32,3,2,5,21];
a.sort(function(x,y){
return y-x;
});
console.log(a);
3. 防抖和节流
//防抖函数
function debounce(fn,delay){
var timeout;
return function(){
if(timeout)clearTimeout(timeout);
timeout=setTimeout(function(){
fn();
},delay);
}
}
//节流 定时器
function throttle(fn,wait){
var timer;
return function(){
if(!timer){
timer=setTimeout(function(){
timer=null;
fn();
},wait)
}
}
}
4. 浅拷贝和深拷贝
//浅拷贝
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
}
};
var o = {};
Object.assign(o, obj);
console.log(o);
o.msg.age = 20;
console.log(obj);
//深拷贝
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
},
color: ['pink', 'red']
};
var o = {};
// 封装函数
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
// 判断我们的属性值属于那种数据类型
// 1. 获取属性值 oldobj[k]
var item = oldobj[k];
// 2. 判断这个值是否是数组
if (item instanceof Array) {
newobj[k] = [];
deepCopy(newobj[k], item)
} else if (item instanceof Object) {
// 3. 判断这个值是否是对象
newobj[k] = {};
deepCopy(newobj[k], item)
} else {
// 4. 属于简单数据类型
newobj[k] = item;
}
}
}
deepCopy(o, obj);
console.log(o);
var arr = [];
console.log(arr instanceof Object);
o.msg.age = 20;
console.log(obj);
5. 事件委托
<ul id="ul">
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<button id="btn">点我添加一个li</button>
// 事件委托具体实现
var ul = document.getElementById("ul");
ul.onclick = function (event) {
event = event || window.event;
var target = event.target;
// 获取目标元素
if (target.nodeName == 'LI') {
alert(target.innerHTML);
}
}
// 为按钮绑定点击事件
var btn = document.getElementById('btn');
btn.onclick = function () {
var li = document.createElement('li');
// 新增li的内容为ul当前子元素的个数
li.textContent = ul.children.length;
ul.appendChild(li);
6. instanceof
instanceof:左边是对象,右边是类;
- 当对象是右边类或子类所创建对象时,返回true;否则,返false。
- 类的实例包含本身的实例,以及所有直接或间接子类的实例
- instanceof左边显式声明的类型与右边操作元必须是同种类或存在继承关系,也就是说需要位于同一个继承树,否则会编译错误
function myInstanceof(target,Fn){
let proto = target.__proto__;
while(true){
if(proto===Fn.prototype){
return true;
}
if(proto===null){
return false;
}
proto = proto.__proto__;
}
7. call、apply、bind
他们每个都有自己的特点,比如call和apply是立即执行,而bind是绑定this后不立即执行。再有就是apply是第二个参数是数组,而call是依次传入参数。
//call
Function.prototype.myCall = function(cont){
let context = cont ||window
let args = [...arguments].slice(1)
context._fn = this;
let res = context._fn(...args);
delete context._fn;
return res;
}
//apply
Function.prototype.myCall = function(cont){
let context = cont ||window
let args = [...arguments].slice(1)
context._fn = this;
let res = context._fn(...args);
delete context._fn;
return res;
}
//bind
Function.prototype.MyApply = function (cont){
let context = cont || window;
if(typeof this != 'function'){
throw new Error('this is not a function!')
}
const _this = this;
return function (){
_this.call(context,...arguments);
}
8. promise
all 、 race 、allsettled 。
- all 是所有promise完成;
- race是一个完成,但是有rejected 他俩就结束;
- allsettled是所有都结束,不管是哪个状态。
8.1 promise.all
//promise.all
function myPromiseAll (promiseArr){
return new Promise(function(resolve,reject){
let result = []
let count = 0;
for(let i =0;i<promiseArr.length;i++){
promiseArr[i].then(res=>{
//注意这里是按照输入数组的顺序,而不是push
result[i]=res;
count++;
if(count==promiseArr.length){
resolve(result);
}
},err=>{
reject(err)
})
}
})
}
8.2 promise.race
function myPromiseRace (promiseArr){
return new Promise(function(resolve,reject){
for(let i =0;i<promiseArr.length;i++){
promiseArr[i].then(res=>{
resolve(res)
},err=>{
reject(err)
})
}
})
}
8.3 promise.allsettled
function myAllSetteld (promiseArr){
return new Promise(function(resolve,reject){
let count = 0;
let result = [];
for(let i =0;i<promiseArr.length;i++){
promiseArr[i].then(res=>{
result[i]= {'status':'fulfilled','value':res};
count++;
if(count==promiseArr.length) resolve(result)
},err=>{
result[i] = {'status':'rejected','reason':err};
count++;
if(count==promiseArr.length) resolve(result)
})
}
})
}
9. new
function myNew (constructor,...args){
/* 1. 创建一个新对象
2. 将构造函数原型上的方法复制给新对象
3. 传入参数执行构造函数,并获取执行结果
4. 判断返回值是是否为对象,不为对象返回执行结果
*/
let newObj = Object.create(constructor.prototype);
let result = constructor.apply(newObj,args);
return typeof result ==='object' ? result : newObj;
10. 发布订阅模式
class EventEmitter {
constructor(){
// 是一个对象来记录事件名和相应的触发函数
this.events = {}
}
// 绑定一个事件的事件处理函数
on(event,fcCallBack){
if(!this.events[event]){
this.events[event] = [fcCallBack]
}else{
this.events[event].push(fcCallBack)
}
}
//触发函数
emit(event,...args){
if(this.events[event]){
this.events[event].forEach(el=>{
el.apply(this,args);
})
}
}
//停止某个事件的事件处理函数
off (event,fcCallBack){
if(!this.events[event]) return;
this.events[event].filter(item=> item!= fcCallBack)
}
//绑定单次执行事件处理函数
once (event,fcCallBack){
function fn(){
fcCallBack();
this.off(event,fcCallBack)
}
this.on(event,fn)
}
}
11. 观察者模式
/*
描述
请补全JavaScript代码,完成"Observer"、"Observerd"类实现观察者模式。要求如下:
1. 被观察者构造函数需要包含"name"属性和"state"属性且"state"初始值为"走路"
2. 被观察者创建"setObserver"函数用于保存观察者们
3. 被观察者创建"setState"函数用于设置该观察者"state"并且通知所有观察者
4. 观察者创建"update"函数用于被观察者进行消息通知,该函数需要打印(console.log)数据,数据格式为:小明正在走路。其中"小明"为被观察者的"name"属性,"走路"为被观察者的"state"属性
注意:
1. "Observer"为观察者,"Observerd"为被观察者
*/
class Observerd {
constructor(name,state='走路'){
this.name = name;
this.state = state;
this.observers = [];
}
setObserver(observer){
this.observers.push(observer);
}
setState(state){
this.state = state;
this.observers.forEach(item=>item.update(this))
}
}
class Observer {
update(observerd){
console.log(`${observerd.name}正在${observerd.state}`)
}
}
12.函数柯里化
实现累加
function add(a,b,c){
console.log(a+b+c)
}
function curry (fn,...args){
let len = fn.length;
return function(){
let _args= [...args,...arguments]
if(_args.length<len){
return curry.call(this,fn,..._args);
}
return fn.apply(this,_args)
}
}
let tmp = curry(add);
tmp(3)(1)(4);
13.图片懒加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
img {
display: block;
width: 100%;
height: 300px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
<img data-src="mao.jpg" alt="">
</body>
<script>
var imgs = document.querySelectorAll('img');
//获得元素距离页面顶部的距离
function getTop(e) {
var T = e.offsetTop;
while (e = e.offsetParent) {
T += e.offsetTop;
}
return T;
}
function lazyLoad(imgs) {
//获取可视区高度
var H = window.innerHeight || document.documentElement.clientHeight;
//获取被卷页面高度
var S = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
for (let i = 0; i < imgs.length; i++) {
if (H + S > getTop(imgs[i])) {
imgs[i].src = imgs[i].getAttribute('data-src');
}
}
}
window.onload = window.onscroll = function () {
lazyLoad(imgs);
}
</script>
</html>
14.数组拉平
es6的flat
[1, [2, [3]]].flat(Infinity); // [1, 2, 3]
arr.toString().split(’,’)
var arr= [11, [22, 33], [44, 55], 66];
var newArr=arr.toString().split(','); //["11", "22", "33", "44", "55", "66"]
arr.join().split(’,’)
const arr = [11, [22, 33], [44, 55], 66];
const flatArr = arr.join().split(','); // ["11", "22", "33", "44", "55", "66"]