functioninstanceOf(left,right){let proto = left.__proto__
let prototype = right.prototype
while(true){if(proto ===null)returnfalseif(proto === prototype)returntrue
proto = proto.__proto__;}}
functionjsonp(url,data,callback){var funcName ='jsonp_'+Date.now()+Math.random().toString().substr(2,5)//如果有其他参数需要拼接if(typeof data==='object'){var tmpArr =[]for(let key in data){let value =data[key]
tmpArr.push(key+'='+value)}
data = tmpArr.join('&')}let script = document.createElement('script')
script.src = url +'?'+ data +'&callback= '+ funcName
document.body.appendChild(script)
window[funcName]=function(data){callback(data)//清除标签delete Window[funcName]
document.body.removeChild(script)}}
★★★★ 手写深拷贝
//乞丐版functiondeepCopy(obj){return obj.JSON.Parse(JSON.Stringify(obj))}//面试够用版functiondeepCopy(obj){if(typeof obj)if(typeof obj =='object'){//判断是否为复杂数据源类型var result = obj.constructor == Array?[]:{}//数组还是对象for(let i in obj){
result[i]=typeof obj[i]=='object'?deepCopy(obj[i]):obj[i]}}else{//简单数据类型 var result = obj;}return result
}
Function.prototype.myCall=function(context){
context=context||window //传入参数的话,就指定context为this指向,否则指定window
context.fn =thisconst args =[...arguments].slice(1)//入参删除contextconst result = context.fn(...args)delete context.fn
return result
}
★★★★ 手写 apply
Function.prototype.myApply=function(context){
context = context || window
context.fn =this//给传入的上下文对象添加一个fn方法,这个fn方法即为myApply调用者let result
if(arguments[1]){
result = context.fn(...arguments[1])}else{
result = context.fn()}delete context.fn
return result
}
★★★ 手写模拟 object.create
function _create (obj){
function F(){} //创建一个构造函数
F.prototype = obj //将构造函数的原型对象赋值
return new F()
}
★★★ 手写模拟 Object.is
function _is(x, y) {
if (x === y) {
//运行到1/x === 1/y的时候x和y都为0,但是1/+0 = +Infinity, 1/-0 = -Infinity, 是不一样的
return x !== 0 || y !== 0 || 1 / x === 1 / y
} else {
//NaN===NaN是false,这是不对的,我们在这里做一个拦截,x !== x,那么一定是 NaN, y 同理
//两个都是NaN的时候返回true
return x !== x && y !== y
}
}
console.log(is(+0, -0))
console.log(is(NaN, NaN))
★★★ 手写 new
//new的实现过程(实际上就是调用这个构造函数,同时将构造函数的prototype上的属性方法挂上去。)//1. 新建一个对象//2. 对象 继承 构造函数的 原型链//3. 将构造函数的this指向这个对象//4. 根据构造函数的返回值的返回结构functionmyNew(fn){let obj ={}//定义空对象obj
obj = Object.create(fn.prototype)//将传入的构造函数的prototype属性方法复制到obj里面let args =Array.prototype.slice.call(arguments,1)// 获取除去fn之外的参数//或者 [...arguments].slice(1)let result =fn.call(obj,...args)// 调用传入的构造函数,矫正this为obj,并传入argsreturntypeof result ==='object'||result instanceofFunction? result : obj;//如果构造函数返回引用类型,直接返回,否则返回obj}classFoo{constructor(){this.name ='ciel'this.arg = arguments[0]}callname(){
console.log(this.name)}}// 测试let test =myNew(Foo,'hhh','123','saf')
test.callName()
console.log(test.arg)
★★★ 手写对象扁平化
exportfunctionjsonFlatten(data){var result ={}functionrecurse(cur, prop){if(Object(cur)!== cur){
result[prop]= cur
}elseif(Array.isArray(cur)){for(var i =0, l = cur.length; i < l; i++){recurse(cur[i], prop +'['+ i +']')}if(l ===0){ result[prop]=[]}}else{var isEmpty =truefor(var p in cur){
isEmpty =falserecurse(cur[p], prop ? prop +'.'+ p : p)}if(isEmpty && prop){ result[prop]={}}}}recurse(data,'')return result
}
★★★ 手写数组扁平化
//第一种 正则表达式functionflatten(arr){let str =JSON.stringify(arr);return str.replace(/(\[\]))/g,'').split(',')}//第二种 递归functionflatten(arr, result =[]){if(!Array.isArray(arr)){
result.push(arr)return result
}for(let value of arr){flatten(value, result)}return result
}//第三种 数组字符串方法functionflatten(arr){return arr.toString().split(',').map(ele=>parseInt(ele))}//第四种functionflatten(arr){while(arr.some(item=> Array.isArray(item))){
arr =[].concat(...arr);}return arr;}
★★★ 手写数组去重
//1.ES6的Setfunctionunique(arr){
ruturn Array.from(newSet(arr))}//2. 双层for循环functionunique(arr){let result =[]for(let i =0, len = arr.length; i < len; i++){//第一层遍历let flag =false//进行标记for(let k = i +1, len = arr.length; k < len; k++){if(arr[i]=== arr[k]){//如果后面有重复的就跳过
flag =true
k = arr.length
}}if(!flag) result.push(arr[i])//没有重复的,添加到数组中}return result
}//3. 利用数组的indexOf方法 functionunique(arr){let result =[]for(let i =0, len = arr.length; i < len; i++){if(result.indexOf(arr[i])===-1) result.push(arr[i])}return result
}//4. 利用类似桶排序的方法functionunique(arr){let result =[]let bucket =[];//创建一个桶for(let i =0, len = arr.length; i < len; i++){
bucket[arr[i]]=1//将有些桶标记}for(key in bucket){//取出有标记的桶的下标
console.log(key);
result.push(Number(key))}return result
}//5. 利用filter方法functionunique(arr){return arr.filter((ele, index)=>(arr.indexOf(ele)=== index))//过滤}//6. 利用map方法functionunique(arr){return arr.map((ele, index)=>{if(arr.indexOf(ele)=== index)return ele
})}//7.排序后进行数组functionunique(arr){
arr.sort()let result =[]
arr.forEach((ele, index)=>{if(ele !== arr[index +1]) result.push(ele)})return result
}