手写bind(),call(),apply(),防抖和节流实现,及常用的数组api

手写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>

猜你喜欢

转载自blog.csdn.net/fesfsefgs/article/details/107696190
今日推荐