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= '+ funcNamedocument.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指向,否则指定windowcontext.fn =thisconst args =[...arguments].slice(1)//入参删除contextconst result = context.fn(...args)delete context.fnreturn result
}
★★★★ 手写 apply
Function.prototype.myApply=function(context){context = context || windowcontext.fn =this//给传入的上下文对象添加一个fn方法,这个fn方法即为myApply调用者let result if(arguments[1]){result = context.fn(...arguments[1])}else{result = context.fn()}delete context.fnreturn 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的时候返回truereturn 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 ={}//定义空对象objobj = 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 =truek = 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}
1、概述
(1)DOM代表文档对象模型,是 HTML 和 XML 文档的接口(API)
(2)当浏览器第一次读取(解析)HTML文档时,会创建一个基于 HTML 文档的大对象,…