JavaScript日常学习

JavaScript日常学习,第1张

javascript 的new 原理
// Func 为构造函数,args表示传参
function myNew(Func,...args){
	// 在内存中创建一个新对象
	const obj = {}
	if(Func.prototype){
	// 把新对象的原型指向Func构造函数的原型
		Object.setPrototypeOf(obj,Func.prototype)
		}
	// 改变this指向,并执行构造函数
		const result = Func.apply(obj,args)
	// 判断执行结果的类型,如果是基本类型则直接返回obj
	// 如果是function或者 object 则返回result,否者不执行,直接返回
		if(typeof result === 'function' || typeof result === 'object' && result !== null{
			return result
		}
		    return obj
	  }
			// 测试
			function Person(name){
				this.name = name
			}
			Person.prototype.sayName = function (){
				alert(`my name is ${this.name}`)
			}
			let ming = myNew(Person,'xiaoming')
			console.log(ming);
			ming.sayName()
bind
//要手写一个bind函数的话,我们需要知道bind拿了什么参数,
			//干了什么:1、接收一个对象(this);2、接受n个参数;3、返回函数。
			Function.prototype.myBind = function() {
				// 保存当前的调用者(普通函数this指向调用者)
				let self = this
				// 不确定bind的参数传几个,我们所知道的只是第一个参数是this要指的对象
				// 第二个一直到最后一个参数我们都不确定,所以我们没法一个一个接收参数,
				// 所以要将第一个参数this对象和后面的参数分离。
				// 这里的this就是调用myBind的函数
				// 参数我们通过arguments获取,arguments可以获取一个函数的所有参数。
				// arguments是一个列表的形态(叫:类数组,伪数组),不是真正数组,不好处理,所以我们要把它拆解为数组。
				// slice是Array.prototype上的方法,这块可以理解为将arguments这个类数组赋予数组的slice功能
				const args = Array.prototype.slice.call(arguments)
				//  Array.from想要转换成数组的伪数组对象或可迭代对象
				// const args = Array.from(arguments)
				// 获取this (及数组的第一项)
				// const args0 = args.slice(1)
				// shift方法将数组的第一项从数组中剔除,改变了原数组,返回了被剔除的这个元素
				const _this = args.shift()
				// 需要返回一个函数
				return function(){
					return self.apply(_this,args)
				}
			}
			function fn1(a,b,c){
				console.log(this)  // this 指向obj
				console.log(this.num*a*b*c)
			}
			const obj = {num:10}
			const fn2 = fn1.myBind(obj,1,2,3)
			fn2()
数组扁平化
// 方案1,递归实现
			let arr =[1,[2,[3,4,5]]];
			function flatten(arr){
				const result = []
				for(let i = 0;i<arr.length;i++){
					if(Array.isArray(arr[i])){
						result = result.concat(flatten(arr[i]))
					} else {
						result.push(arr[i])
					}
				}
				return result
			}
// 方案2,reduce 函数迭代

			let arr =[1,[2,[3,4,5]]];
			function flatten2(arr=[]){
			//reduce() 方法对数组中的每个元素按序执行一个由您提供的 reducer 函数,
			//每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
				return arr.reduce((prev,next)=>{
				// prev(前一次调用 callbackfn 得到的返回值)
				// next(数组中正在处理的元素)
				// Index(数组中正在处理的元素的索引)
					return prev.concat(Array.isArray(next) ? flatten2(next) : next)
				},[]) //第一次执行回调函数时,不存在“上一次的计算结果”,所以用一个空数组去接收。
			}
// 方案3 split 和 toString
// 实现数组扁平化,由于数组会默认带⼀个 toString 的⽅法,所以可以把数组直接转换成逗号分
// 隔的字符串,然后再⽤ split ⽅法把字符串重新转换为数组,如下⾯的代码所⽰:
			let arr =[1,[2,[3,4,5]]];
			function flatten3(arr=[]){
				return arr.toString().split(',')
			}
//方案4、ES6 中的 flat
			//法来实现数组扁平化。flat方法的语法:arr.flat ( [depth] )
			//其中 depth 是 flat 的参数,depth 是可以传递数组的展开深度(默认不填、数值是 1)
			// 即展开一层数组。
			//如果层数不确定,参数可以传Infinity,代表不论多少层都要展开
			function flatten(arr=[]){
				return arr.flat(Infinity)
			}
异步Promise 并发限制
/*
			new promise一经创建立即执行
			使用promise.resolve().then()可以把任务加入到微任务队列,防止立即执行迭代方法
			微任务处理过程中,产生新的微任务,会在同一事件循环内,追加到微任务队列里
			在完成某个任务时,继续追加任务,保持任务的最大并发数进行执行
			任务完成后,从任务队列里移除
			promise.all方法可以执行多个promise,你给他多少个他就执行多少个,而且是一起执行,也就是并发执行。
			*/
		   // limit限制并发数,array接收一个数组,所有的并发,iteratorFn执行函数
			function asyncPool(limit,array,iteratorFn){
				let i = 0
				const tasks = []
				const doingTasks = [] // 用于保存正在执行的promise
				const enqueue = ()=>{
					// 空数组处理
					if(array.length === 0){
						return Promise.resolve()
					}
					// 每调用一次,初始化一个promise
					const task = Promise.resolve().then(()=>{
						iteratorFn(array[i++])
					})
					// 将初始化的promise放入tasks数组
					tasks.push(task)
					// promise执行完毕后,从doingTasks数组中删除
					const doing = task.then(()=>{
						doingTasks.splice(doingTasks.indexOf(doing),1)
					})
					doingTasks.push(doing)
					// 使用promise.race 获得doingTasks中promise的情况
					// 如果正在执行的promise数量高于limit就执行一次
					// 否则继续实例化新的Promise,直到达到limit时执行
					const result = doingTasks.length >= limit ? Promise.race(doingTasks) : Promise.resolve()
					
					// 递归,直到遍历完array
					return result.then(enqueue)
					
				}
				// 所有的promise 都执行完了,调用Promise.all返回
				return enqueue().then(()=>{
					Promise.all(tasks)
				})
			}
			//异步并发测试shadowscoks
			const fn = i=> new Promise(resolve=>{
				setTimeout(()=> resolve(i),i)
			})
			asyncPool(2,[1000,1000,1000,1000],fn).then(res=>{
				console.log(res)
			})

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1322505.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-12
下一篇 2022-06-12

发表评论

登录后才能评论

评论列表(0条)

保存