手写一切(updating...)

1.手写ajax基本过程

var xhr;
if(window.XMLHttpRequest){
    //code for IE7+,Firefox,Chrome,Opera,Safari
    xhr = new XMLHttpRequest();
}else{
    // code for IE6, IE5
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
var xhr = new XMLHtpRequest();		//创建对象
xhr.open('post','demo.html',true)	
xhr.send();
xhr.onreadystatechange = function(){
	if(xhr.readyState === 4 && xhr.status === 200){
	/* 
       0:请求还没有建立(open执行前)
       1:请求建立了还没发送(执行了open)
       2:请求正式发送(执行了send)
       3:请求已受理,有部分数据可以用,但还没有处理完成
       4:请求完全处理完成
    */
		alert(xhr.responseText);
	}
}

2.手写函数柯里化


函数柯里化,是将有多个参数的函数,即多元函数分为n个一元函数
function curry(fn, ...args){
	//如果所传入的参数长度大于原函数的参数长度,那么就直接返回原函数
	if([...args].length >= fn.length){
		return fn(...args);
	}else{
		//反之,则返回一个参数长度为n - [...args].length的fn,并以递归方式依次传入剩下的参数,
		return (...params) => {	
			return curry(fn, ...args, ...params);
		}
	}
}

3.手写call,apply,bind

相同:三者都是改变函数的调用对象(即改变this指向),注意是对函数使用!
call和bind的不同:唯一不同的是call接收的是一系列参数,apply接收的是参数数组
call和apply的不同:唯一不同是call和bind都是直接执行函数,apply是返回一个新的函数。
简述:能够让a对象,使用b对象的方法,并将this指针指向A。

Function.prototype.Mycall = function(context, ...params){
	//创建一个_this使其等同调用对象。
	const _this = typeof context === object ? context || window : window;
	const key = Symbol();
	//将this(此时的this指向的是有该方法的对象b)设置为_this的属性
	_this[key] = this;
	const result = _this[key](...params)	//此时t函数内this指向的就是调用者A了
	delete _this[key];
	return result;
}
Function.prototype.MyApply = function(context, params){
	return this.Mycall(context, ...params);
	//也可写成,因为此时this === function.Prototype;
	return function.Prototype.Mycall(context, ...params);
}

Function.prototype.MyBind = function(context, ...params){
	//注,其返回的是一个新的函数,因此需要创建临时内部指针_this
	const _this = this;
	return function(...args){
		return _this.Mycall(context, ...[...parmas, ...args]);
	}
}

4.手写new

	function myNew(){
		//1.创建一个对象obj
		var obj = new Object();
		//2.将该对象的__proto__指向构造函数的prototype
		Constructor = [].shift.call(arguments);
		obj.__proto__ = Constructor.prototype;
		//绑定this
		Constructor.apply(obj, arguments);
	}
	function person(name,age){
        this.name = name;
        this.age = age;
        this.sex = 'male';
    }
	var newn =  myNew(person, 'hahaha', '20');

5.手写reduce

	Array.prototype.myReduce = function(fn,initialValue){
		var arr = [].slice.call(this);
		if(initalValue){			//如果有初始值,则将它插入到数组第一个位置
			arr.unshift(initalValue);
		}
		var result = arr[0];
		for(let i = 1; i < arr.length; i++){
			if(!arr.hasOwnProperty(i)){	//防止稀疏数组(也就是值为undefined的下标)
				continue;
			}
			result = fn(null, result, arr[i], i, this);
		}
	}

6.手写map

map:对数组的每一个元素操作,并最终返回一个操作后的数组。

Array.prototype.myMap = function(fn, context){
	var arr = [].slice.call(this);
	var arrMap = [];
	for(let i = 0; i < arr.length; i++){
		if(!arr.hasOwnproperty){
			continue;
		};
		arrMap.push(fn.call(context, arr[i], i, this));
	}
	return arrMap;
}

7.手写异步并发限制请求

function asyncPool(max, array, callBack){
	let i = 0;
	const running = [];     //当前正在执行的任务列表
	
	const enqueue = function(){
	    //递归,边界考虑,如果i等于array长度,则所有任务都已经放入running。
	    if(i === array.length){
	        return Promise.resolve();
	    }
	    //取出一个任务,然后再添加至running
	    const item = heavyWorker(array[i++]);
	    running.push(item);
	    item.then(()=>{     //当它执行完成后,则从running中删除掉
	        running.splice(running.indexOf(item), 1);
	    });
	
	    //一旦running的长度大于max,则调用promise.race
	    //当running中的有一个任务执行完毕,则用p继续调用enqueue去加入下一个任务。
	    let p = Promise.resolve();
	    if(running.length >= max){
	        p = Promise.race(running);
	    }
	    return p.then(() => enqueue());
	
	} 
	//此时running可能做多还剩下max个任务,且之后已经没有新的任务了,
	//所以用promise.all等到running中所有的任务执行完毕,再执行callback。
	//切记必须等到enqueue执行完后再执行,所以写在enqueue().then里面。
	enqueue().then(()=>{
	    Promise.all(running).then(()=>{
	        callBack();
	    })
	});
	
	}
asyncPool(3, tasks, ()=>{console.log('finish')});

8.手写Promise.all和Promise.race

Promise.all接收一个promise对象数组,如果数组内所有对象都resolve时,
新对象的状态变为fulfilled,所有对象的resolve的value值依次添加组成一个新的数组,
作为新对象resolve的value。
一旦数组内对象有一个reject时,新对象状态变为rejected,返回的值也是该对象reject的reason。
function promiseAll(arr){
 	if(!Array.isArray(arr)){
       console.log('must be an array');
    }
//返回promise实例
	return new Promise((resolve, reject)=>{
	   let count = 0;
	   let res = new Array(arr.length);
	   for(let i = 0; i< arr.length; i++){
	       Promise.resolve(heavyWorker(arr[i]).then((value)=>{
	           count++;
	           res[i] = value;
	           if(count === arr.length){
	               return resolve(res);
	           }
	
	       },rej => reject(rej)));
	
	   }
	  
	})
}
console.log(promiseAll(tasks));
promise.race同样接收一个promise对象数组,只要对象数组内的一个对象的resolve时
新状态则为fullfilled,返回的值即为该对象resolve的value。
function promiseRace(arr){
   if(!Array.isArray(arr)){
       console.log('must be an array');
   }
   return new Promise((resolve,reject)=>{
       arr.forEach((e)=>{
           Promise.resolve(heavyWorker(e)).then(data => {
               return resolve(data);
           },err => {
               reject(err);
           })

       })
   })
}
console.log(promiseRace(tasks));

9.递归版深拷贝

  你变它变,浅拷贝;都指向同一个地址
  你变它不变,深拷贝;两个不同的地址
function deepClone(obj){
    let res = Array.isArray(obj) ? []: {};
    for(let key in obj){
        if(obj[key] && typeof obj[key] === 'object'){
            res[key] = deepClone(obj[key])
        }else{
            res[key] = obj[key];

        }
    }
    return res;
}
let obj1 = deepClone(obj);
obj1.name = '8888';
console.log(obj1);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值