1. 数组去重
function quChong(arr) {
return [...new Set(arr)]
}
Array.from(new Set(array))
2. 数组扁平化
function flat(arr) {
let stack = [...arr]
let res = []
while(stack.length){
const next = stack.pop()
if(Array.isArray(next)) {
stack.push(...next)
} else {
res.unshift(next)
}
}
return res
}
3. 二分查找
function twoSort(arr,target){
let left = 0;
let right = arr.length - 1;
while(left<=right) {
let mid = Math.floor((left + right) / 2)
// let mid = (left + right) >> 1
if(arr[mid] == target) {
return mid
} else if(arr[mid] < target) {
left = mid + 1
} else {
right = mid - 1
}
}
return -1;
}
console.log(twoSort([1,2,3,4,5],2))
4. 节流
function thorrle(fn, delay) {
let preTime = Date.now()
return function() {
let that = this
let args = arguments
let nowTime = Date.now()
if(preTime - nowTime >= delay) {
preTime = Date.now();
fn.apply(that,args)
}
}
5. 防抖
function debounce(fn, delay) {
let time = null
return function() {
// 绑在在dom上,否则绑定在window上
let args = arguments
let that = this
if(time) {
clearTimeout(time)
time = null
}
timer = setTimeout(()=>{
fn.apply(that,args)
},delay)
}
}
6. promise封装ajx
const getJson = function(url){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest();
xhr.open('GET',url)
xhr.setRequestHeader("Content-Type",'application/json')
xhr.onreadystatechange = function() {
if(xhr.readyState !== 4) {
return;
}
if(xhr.status === 200 || xhr.status === 304) {
resolve(xhr.responseText)
} else {
reject(new Error(xhr.responseText))
}
};
xhr.send()
})
7. 手写instanceof
// 构造函数的原型对象是否在原型链上,对返回true,否则false
function myInstanceof(left, right) {
while(true) {
if(left == null) {
return false;
}
if(left.__proto__ === right.prototype){
return true
}
else {
left = left.__proto__;
}
}
}
8. 手写promise.all和race
function all(arr){
let count = 0
let result = []
return new Promise((resolve,reject)=>{
for(let i = 0;i < arr.length;i++ ){
Promise.resolve(arr[i]).then(
(res) => {
result[i] = res
count++
if(count === arr.length) {
resolve(result)
}
},
(err) => {
reject(err)
}
)
}
})
}
function race(arr){
return new Promise(function (resolve, reject) {
promises.forEach(p =>
Promise.resolve(p).then(data => {
resolve(data)
}, err => {
reject(err)
})
)
})
}
9.洗牌
function randomNumber(arr){
let len = arr.length - 1
let t
for(let i = 0; i < len; i++) {
let index = parseInt(Math.random() * (len + 1 - i))
t = arr[index]
arr[index] = arr[len - i]
arr[len - i] = t;
}
return arr
}
10. 深拷贝
// 深拷贝的实现
function deepCopy(object) {
// 补全代码
if(!(typeof target=='object'))
return target
let copyOne=Array.isArray(target)?[]:{}
for(let key in target){
let value=target[key]
if(typeof value=='object'){
copyOne[key]=_sampleDeepClone(value)
}else{
copyOne[key]=value
}
}
return copyOne
}
11. bind
-
判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
-
保存当前函数的引用,获取其余传入参数值。
-
创建一个函数返回
-
函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
Function.prototype.myBind=function(context){ if(typeof this!="function"){ throw new TypeError("Error") } let args = [...arguments].slice(1) let fn = this return function Fn(){ return fn.apply( this instanceof Fn ? this:context, args.concat(...arguments) ) } }
12.new
function myNew(fn, ...args) {
let obj = Object.create(fn.prototype);
let res = fn.call(obj, ...args);
if (res && (typeof res === "object" || typeof res === "function")) {
return res;
}
return obj;
}
13. 发布订阅模式
// 发布订阅模式
class EventEmitter {
constructor() {
// 事件对象,存放订阅的名字和事件
this.events = {}
}
// 订阅事件的方法
on(eventName, callback) {
if (!this.events[eventName]) {
// 注意是数据,一个名字可以订阅多个事件函数
this.events[eventName] = [callback]
} else {
// 存在则push到指定数组的尾部保存
this.events[eventName].push(callback)
}
}
// 触发事件的方法
emit(eventName) {
// 遍历执行所有订阅的事件
this.events[eventName] && this.events[eventName].forEach((cb) => cb())
}
// 移除订阅事件
removeListener(eventName, callback) {
if (this.events[eventName]) {
this.events[eventName] = this.events[eventName].filter(
(cb) => cb != callback
)
}
}
// 只执行一次订阅的事件,然后移除
once(eventName, callback) {
// 绑定的时fn, 执行的时候会触发fn函数
let fn = () => {
callback() // fn函数中调用原有的callback
this.removeListener(eventName, fn) // 删除fn, 再次执行的时候之后执行一次
}
this.on(eventName, fn)
}
}
14. 12345
for(let i=1;i<=5;i++){
setTimeout(function(){
console.log(i)
},i*1000)
}
for(var i=1;i<=5;i++){
(function(i){
setTimeout(function(){
console.log(i)
},i*1000)
})(i)
}
15. 组合继承
原型式继承:利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型。
function father(name,age) {
this.name = age
}
function son(){
// 不能继承方法
father.call(this,"big",22)
}
let erzi = new son();
son.prototype = new father()
// son的构造函数指向了父类
son.prototype.constructor = son
console.log(erzi.name);
原型式继承:利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型。
function object(obj){
function F(){}
F.prototype = obj;
return new F();
}
16. jsonp
function Jsonp(url){
let script = document.createElement('script')
script.src = url
script.type = "text/javascript"
document.body.appendChild(script)
}
Jsonp("http:www.123.com?callback=handres")
function handres(res){
console.log(res)
}
handres({a:1,b:2})
17.settimeout实现setinterval
function mySetInterval(fn,time){
let timer = null
function interval() {
fn();
timer =setTimeout(interval,time);
}
interval()
}
function mySetTimeOut(fn,time){
let time = null
let timer = setInterval(() => {
clearInterval(timer)
fn()
},
time);
}
18.科利华
var args = [...arguments];
console.log(args);
var fn=function(){
args.push(...arguments);
return fn
};
fn.toString=function(){
return _args.reduce(function (a, b) {
return a + b;
});
};
return fn
}
19.apply
Function.prototype.myApply = function(context) {
// 判断调用对象是否为函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
let result = null;
// 判断 context 是否存在,如果未传入则为 window
context = context || window;
// 将函数设为对象的方法
context.fn = this;
// 调用方法
if (arguments[1]) {
result = context.fn(...arguments[1]);
} else {
result = context.fn();
}
// 将属性删除
delete context.fn;
return result;
};
20.call
// call函数实现
Function.prototype.myCall = function(context) {
// 判断调用对象
if (typeof this !== "function") {
console.error("type error");
}
// 获取参数 处理传入的参数,截取第一个参数后的所有参数。 let args = [...arguments].slice(1),
result = null;
// 判断 context 是否传入,如果未传入则设置为 window
context = context || window;
// 将调用函数设为对象的方法
context.fn = this;
// 调用函数
result = context.fn(...args);
// 将属性删除
delete context.fn;
return result;
};