防抖
function debounce(fn, delay) {
var timer = null;
return function(...arg) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arg);
}, delay || 500);
};
}
// 不断触发一个函数,在规定时间内只让最后一次生效,前面都不生效
// 注意点:
// 如何在vue中使用 https://zhuanlan.zhihu.com/p/72363385
// 理解工作原理 this指向 参数
节流
function throttle(fn, delay) {
var timer = null;
return function(...args) {
if (!timer) {
fn.apply(this, args);
timer = setTimeout(function() {
timer=null
}, delay || 500);
}
};
}
// 不断触发一个函数后,执行第一次,只有大于设定的执行周期后才会执行第二次
// 防抖和节流的区别 应用场景
// 函数防抖和函数节流都是防止某一时间频繁触发
// 函数防抖是单位事件内 只执行最后一次触发的事件
// 函数节流是单位时间间隔内 只执行一次触发事件
// 比如:
// LOL技能cd就是用的 节流,
// 购物车提交订单就是用的 防抖
深拷贝
function deepClone(obj) {
// 1.先判断是否为对象类型
let isObject = (arg) => typeof arg === "object" && arg !== null
// 2.如果不是,则返回本身
if (!isObject(obj)) return obj;
// 3.定义一个变量,判断是数组还是对象
let cloneObj = Array.isArray(obj) ? [] : {};
// 4.循环每一个元素,如果满足是自身属性,则每一个值再判断是否为对象类型,如果是则继续递归调用,否则返回本身
for (let key in obj) {
cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key];
}
// 5.返回创建的变量值
return cloneObj;
}
浅拷贝
function shallowClone(obj) {
if (typeof obj !== 'object' || obj === null) return obj
// 3.定义一个变量,判断是数组还是对象
let cloneObj = Array.isArray(obj) ? [] : {};
// 4.循环每一个元素,
for (let key in obj) {
cloneObj[key] = obj[key]
}
// 5.返回创建的变量值
return cloneObj;
}
new
function _new(Fn, ...arg) {
//基于fn的prototype构建对象的原型
const thisObj = Object.create(Fn.prototype);
//将thisObj作为fn的this,继承其属性,并获取返回结果为result
const result = Fn.apply(thisObj, arg);
//根据result对象的类型决定返回结果
return result instanceof Object ? result : thisObj
}
call
Function.prototype.myCall = function(obj, ...args) {
// console.log(obj);
// console.log(this);
// if(obj==null||obj==undefined) obj=window //为空时,指向window
const ctx=obj || window
ctx.fn = this // this指向调用call的对象,即我们要改变this指向的函数
return ctx.fn(...args) // 执行函数并return其执行结果
delete ctx.fn //删除该方法,不然会对传入的对象造成污染,添加了该方法
}
apply
Function.prototype.myApply = function(obj, args) {
// console.log(obj);
// console.log(this);
// if(obj==null||obj==undefined) obj=window //为空时,指向window
const ctx=obj || window
ctx.fn = this // this指向调用call的对象,即我们要改变this指向的函数
return ctx.fn(...args) // 执行函数并return其执行结果
delete ctx.fn //删除该方法,不然会对传入的对象造成污染,添加了该方法
}
bind
Function.prototype.myBind = function(thisArg, ...args) {
var self = this //保存当前this,指的是当前fn调用者
const fn = function(...fnArgs) {//提取调用时候的参数
return self.apply(this instanceof self ? this : thisArg, [...args, ...fnArgs])
}//且有返回值
fn.prototype = this.prototype; //继承原型上的属性和方法
return fn
}
// 输入:接受一个或者多个参数,第一个是要绑定的上下文,额外参数当作绑定函数的前置参数。
// 输出:返回原函数的拷贝,即返回一个函数,这个函数呢具备原函数的功能
instanceof
// instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
function myInstanceof(left, right) {
// 左侧是实例对象
// 右侧是某个构造函数
if (typeof left !== 'object' || left === null) return false // 基本数据类型直接返回false
let RP = right.prototype; // 构造函数的原型对象
let LP = Object.getPrototypeOf(left) // 优先用这个方法 去查找实例对象的隐式原型对象
while (true) {
if (LP === null) return false;
if (LP === RP) return true;
LP = Object.getPrototypeOf(LP) // 沿着原型链重新赋值
}
}
数组去重
数组乱序
继承
睡眠函数(sleep)
// 1
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
// 2
function sleep(delay) {
var start = (new Date()).getTime();
while ((new Date()).getTime() - start < delay) {
continue;
}
}
// (async function() {
// console.log('Do some thing, ' + new Date());
// await sleep(3000);
// console.log('Do other things, ' + new Date());
// })();
函数柯里化(Currying)
/**
* @description: 将函数柯里化的工具函数
* @param {Function} fn 待柯里化的函数
* @param {array} args 已经接收的参数列表
* @return {Function}
*/
const currying = function(fn, ...args) {
// fn需要的参数个数
const len = fn.length
// 返回一个函数接收剩余参数
return function (...params) {
// 拼接已经接收和新接收的参数列表
let _args = [...args, ...params]
// 如果已经接收的参数个数还不够,继续返回一个新函数接收剩余参数
if (_args.length < len) {
return currying.call(this, fn, ..._args)
}
// 参数全部接收完调用原函数
return fn.apply(this, _args)
}
}
数组扁平化(flat)
let result = [];
let fn = function(ary) {
for(let i = 0; i < ary.length; i++) }{
let item = ary[i];
if (Array.isArray(ary[i])){
fn(item);
} else {
result.push(item);
}
}
}
lazyMan
filter
jsonp
function jsonp (url) {
/*声明一个唯一的回调函数并挂载到全局上
*创建一个script标签地址 指向 请求服务器 将回调函数名作参数带到服务器
*服务器拿到回调名称 并返回前端 该回调的调用 把返回结果当作参数传入
*/
let script = document.createElement('script')
let uniqueName = `jsonpCallback${new Date().getTime()}`
script.src = `url${url.indexOf('?') > -1 ? '&': '?'}callback=${uniqueName}`
document.body.appendChild(script)
window[uniqueName] = (res) => {
cb && cb(res)
document.body.removeChild(script)
delete window[uniqueName]
}
}
// 调用
jsonp('getList', (res) => {
console.log(res)
})
// 服务器端
1. 获取参数, 拿到回调函数名称
2. 返回参数名的前端回调的调用 并 把要返回的参数作为实参调用
/*弊端 - 只支持get请求,并且不安全,需要服务器支持*/
function jsonp ({url, query}) {
let script = document.createElement("script");
let cb = `jsonpCallBack${new Date().getTime()}${Math.floor(Math.random(5)*100000)}`
let params = {...query, cb}
let arr = []
for (let key in params) {
arr.push(`${key}=${params[key]}`)
}
script.src = `${url}?${arr.join("&")}`
document.body.appendChild(script)
return new Promise((resolve, rej) => {
window[cb] = function (res) {
resolve(res)
document.body.removeChild(script)
delete window[cb]
}
})
}
jsonp({
url:'/getList',
query: {name: 'ys',age: 19}
}).then((res) => {
console.log(res)
})
promise
promise.all
发布订阅(EventEmitter)