手写xxx并不是说一定要在开发中去用才有意义,也不是为了覆盖原生提供的方法,而是培养自己的思维方式,学习下这种实现思路,让自己对方法的运用更加通透
bind,call,apply的实现;
需要注意的是,bind的一种特别用法:
通过bind改变完this指向后返回的函数,调用的参数也算在内的哦
function fn(a, b) {
console.log(a, b)
console.log(arguments)
}
var newFn = fn.bind(this, 1, 2)
newFn(34,23)
代码如下:
Function.prototype.mycall = function(obj, ...args) {
//处理obj为null 和 undefined 的情况
if(obj === undefined || obj === null) {
obj = window
}
//执行函数,但是this没改变
//this(...args)
//给obj添加方法,这样this就指向obj了
obj.tempFn = this
const result = obj.tempFn(...args)
//执行完后删除obj上的tempFn
delete obj.tempFn
return result
}
Function.prototype.myapply = function(obj, args) {
//同理
if(obj === undefined || obj === null) {
obj = window
}
obj.tempFn = this
const result = obj.tempFn(...args)
delete obj.tempFn
return result
}
Function.prototype.mybind = function(obj, ...args) {
let res = null
return(...args2) => {
res = this.call(obj, ...args, ...args2)
return res
}
}
function fn(a, b) {
console.log(a, b)
console.log(arguments.length)
}
var newFn = fn.mybind(this, 1, 2)
newFn(34,23)
当然,内部实现远远没有这么简单啦,只是简单实现一下
数组常用方法:
-
map
-
filter
-
some
-
every
-
reduce
-
find
-
findIndex
简单实现如下:
<script type="text/javascript">
Array.prototype.myMap = function(callback) {
var arr = []
for(var i = 0; i < this.length; i++) {
arr.push(callback(this[i], i))
}
return arr
}
var arr = [13, 2, 4, 2, 42]
let newArr = arr.myMap(item => {
return item + 10
})
console.log(newArr) //[23, 12, 14, 12, 52]
Array.prototype.myReduce = function(callback, init) {
var preTotal = init
for(var i = 0; i < this.length; i++) {
preTotal = callback(preTotal, this[i], i)
}
return preTotal
}
var arr2 = [1, 2, 3, 4, 5]
let total = arr2.myReduce((preTotal, item, index) => {
return preTotal + item
}, 0)
console.log(total) //15
Array.prototype.myFilter = function(callback) {
var arr = []
for(var i = 0; i < this.length; i++) {
if(callback(this[i], i)) {
arr.push(this[i])
}
}
return arr
}
var arr3 = [1, 2, 3, 4, 5, 6, 7, 8]
let newArr3 = arr3.myFilter((item) => {
return item > 4
})
console.log(newArr3) //[5, 6, 7, 8]
Array.prototype.myFind = function(callback) {
for(var i = 0; i < this.length; i++) {
if(callback(this[i], i)) {
return this[i]
}
}
}
var arr4 = [{
name: "zhangsan",
id: 1
}, {
name: "lisi",
id: 2
}]
let newArr4 = arr4.myFind((item) => {
return item.id == 2
})
console.log(newArr4) //{name: "lisi", id: 2}
Array.prototype.myFindIndex = function(callback) {
for(var i = 0; i < this.length; i++) {
if(callback(this[i], i)) {
return i
}
}
return -1
}
var arr5 = [{
name: "zhangsan",
id: 1
}, {
name: "lisi",
id: 2
}]
let index = arr5.findIndex((item) => {
return item.id == 3
})
console.log(index) //-1
Array.prototype.myEvery = function(callback) {
for(var i = 0; i < this.length; i++) {
if(!callback(this[i], i)) {
return false
}
}
return true
}
var arr6 = [3, 4, 2, 3, 5, 3, 7, 8]
let bool = arr6.myEvery((item) => {
return item > 2
})
console.log(bool) //false
Array.prototype.mySome = function(callback) {
for(var i = 0; i < this.length; i++) {
if(callback(this[i], i)) {
return true
}
}
return false
}
var arr7 = [3, 4, 2, 3, 5, 3, 7, 8]
let bool2 = arr7.mySome((item) => {
return item > 10
})
console.log(bool2) //false
</script>
防抖和节流:
时间频繁触发可能造成的问题?
1,一些浏览器时间,window.onresize,window.mousemove等,触发的频率
非常高,会造成浏览器性能问题
2.如果向后台发送请求,频繁触发,对服务器造成不必要的压力
如何限制事件处理函数的频繁调用
1.函数节流
2.函数防抖
函数节流(throttle):间隔时间内只触发一次
1.理解:
在函数需要频繁触发时,函数执行一次后,只有大于设定的执行周期后才会
执行第二次,适合多次事件按时间做平均分配触发
2.场景:
窗口调整(resize)
页面滚动(scroll)
DOM元素的拖拽功能实现(mousemove)
抢购疯狂点击(click)
函数防抖(debounce):只让最后一次执行生效
1.理解:
在函数需要频繁触发时,在规定时间内,只让最后一次生效,前面的不生效
适合多次事件一次响应的情况
2.场景:
输入框搜索
简单实现下: 注意哦,不同于上面的实现,防抖和节流在开发中可是会使用到的哦
<script type="text/javascript">
//方法一:setTimeout 控制时间
function throttle(callback, delay) {
var flag = true
return function(event) {
if(!flag) return
//this是事件源
callback.call(this, event)
flag = false
setTimeout(() => {
flag = true
}, delay)
}
}
//方法二:Date.now()控制时间
function throttle(callback, delay) {
var pre = 0
return function(event) {
var current = Date.now()
if(current - pre > delay) {
//this是事件源
callback.call(this, event)
pre = current
}
}
}
//方法一:setTimeout控制
function debounce(callback,delay){
var timeId = null
return function(event){
if(timeId) clearTimeout(timeId)
timeId = setTimeout(()=>{
callback.call(this,event)
},delay)
}
}
function test() {
console.log(1)
}
// document.onmousemove = throttle(test, 500)
document.onmousemove = debounce(test, 200)
</script>