实现防抖
1.搜索,就应该用防抖,当我连续不断输入时,不会发送请求;当一段时间内不输入了,才会发送一次请求;如果小于这段时间继续输入的话,时间会重新计算,也不会发送请求。
2.钮提交场景:防止多次提交按钮,只执行最后提交的一次
function debounce (fn, wait=150){
let timer = 0
return function (...arguments) {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this,arguments)
}, wait);
}
}
实现节流
在第一次触发时不会执行,而是在 delay 秒之后才执行,当最后一次停止触发后,还会再执行一次函数,比例滚动
function throttle(fn, t) {
let isRun = false
return function (...arguments) {
if(isRun){
return
}
isRun = true
setTimeout(() => {
fn.apply(this,arguments)
isRun = false
}, t);
}
}
实现instanceOf
function _instanceOf(a,b){
if(typeof a !== 'object' || a == null) {
return false
}
// 因为 Object.getPrototypeOf(a) = a.__proto__
let apro = Object.getPrototypeOf(a)
// let apro = a.__proto__ //等同于上面一句
while (apro) {
if(apro == b.prototype){
return true
}
apro = Object.getPrototypeOf(apro)
// apro = apro.__proto__ //等同于上面一句
}
return false
}
new的实现
- 1.创建一个全新的对象obj,
- 2.继承构造函数的原型:这个对象的__proto__要指向构造函数的原型prototype
3.执行构造函数,使用 call/apply 改变 this 的指向(将obj作为this)
4.返回值为object类型则作为new方法的返回值,否则返回新创建的对象obj
function myNew(fn,...args) {
let obj = {}
obj.__proto__ = fn.prototype
let result = fn.apply(obj, args)
// 等同于下面一句
// result instanceof Object ? result: obj
return typeof result === 'object' ? result: obj
}
// 使用
function Names(name,age) {
this.name = name
this.age = age
}
let res = myNew(Names, 'xiao', 2)
console.log('res', res)
call的实现
在新对象内部创建一个 fn 函数,将 当前 this 赋值给 fn 函数
调用新对象中的 fn 函数执行
完成后将新对象中的 fn 函数删除(避免占用内存)
Function.prototype.call2 = function (obj, ...args) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
obj.fn = this;
// 如果接收...args就不用下面这句,如果不接受参数需要获取参数
// const args = [...arguments].slice(1) // 获取参数,第一个参数是this,从第二个开始
let res = obj.fn(...args)
delete obj.fn
return res
}
测试
var foo = {
value: 1
}
function bar(name,age) {
console.log('name',name);
console.log('age',age);
}
bar.call2(foo,'susu',18);
大致思想一致:
apply的实现
改变 this 指向
传递一个参数数组
调用函数执行
Function.prototype.Myapply = function (context, arg) {
context = context || window
context.fn = this
let res
if(!arg) {
result = context.fn()
} else {
result = context.fn(arg)
}
delete context.fn
return result
}
调用
function bar(...args) {
console.log('...args',...args);
}
bar.Myapply(foo,['susu',18]);
Call/apply可以写成一样的,注意call和apply只有参数 不一样
function myCall(context=window, ...args) {
if(context !== 'object'){
context = new Object(context)
}
let fn = Symbol()
context.fn = this
let res = context.fn(...args)
delete context.fn
return res
}
function myApply(content=window, args) {
if(content !== 'object'){
content = new Object(content)
}
let fn = Symbol()
content.fn = this
let res = content.fn(...args)
delete content.fn
return res
}
bind的实现
1.改变 this 指向;
2.接收多个参数;
3.返回一个新的函数
Function.prototype._bind = function (obj, ...args) {
let self = this
let fBound = function (...innerArgs) {
return self.apply(this instanceof fBound ? this:obj, args.concat(innerArgs))
}
fBound.prototype = Object.create(this.prototype)
return fBound
}
function myBind(content) {
let args = Array.prototype.slice.call(arguments,1)
let that = this
//简版
// return function () {
// let innerArg = Array.prototype.slice.call(arguments)
// return that.apply(content,args.cancat(innerArg))
// }
//区别了new
function Bind() {
let innerArg = Array.prototype.slice(arguments)
return that.apply(
this instanceof that? this: content
,
args.concat(innerArg)
)
}
Bind.prototype = this.prototype
return Bind
}
深拷贝
function deepCopy(obj) {
if (typeof obj !== 'object' || obj == null) {
return obj
}
let copy = Array.isArray(obj) ? [] : {}
for (let key in obj) {
if(obj.hasOwnProperty(key)){
copy[key] = deepCopy(obj[key])
}
}
return copy
}
测试
let obj = { a: 1, b: { c: 2 } };
let copy = deepCopy(obj);
console.log(copy);