JS手写(二)

88 阅读2分钟

1.实现一个深拷贝

var deepClone = (target) => {
    if (typeof target === 'object'  && target !== null) {
        const cloneTarget = Array.isArray(target) ? [] : {};
        for (let prop in target) {
            if (target.hasOwnProperty(prop)) {
                cloneTarget[prop] = deepClone(target[prop]);
             }
        }
        return cloneTarget;
     } else {
         return target;
     }
}

测试代码:

const a = {val:'4',b:{deepVal:'5'}};
let newA = deepClone(a);
console.log(newA)//{val:'4',b:{deepVal:'5'}

2.实现一个Ajax请求

// 创建一个XMLHttpRequest对象
let xhr = new XMLHttpRequest();
// 使用open方法创建一个Http请求
xhr.open("GET",url,true)
// 可以设置监听函数
// 比如可以设置onreadystatechange,当状态变化时会触发这个事件
xhr.onreadystatechange = function(){
    if(xhr.readyState ===4 & xhr.status === 200){
        console.log("Success")
    }
}
// 发送Http请求,可以传入参数作为发送的数据体
xhr.send(null)

3.函数柯里化

// 函数柯里化:柯里化是把接受多个参数的函数转变为接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术。
// 面试题:add(1)(2)(3)=6  ; add(1,2,3)(4)=10  ; add(1)(2)(3)(4)(5)=15 ;
function add(){
    let args = Array.prototype.slice.call(arguments); //转化为数组,方面后面进行数组操作
    let inner = function(){
        args.push(...arguments);
        // 实现任意延迟输入函数,利用递归的方法实现函数延迟绑定
        return inner;
     }
     // 改写toString方法
    inner.toString = function(){
        return args.reduce(function (prev,cur){
            return prev+cur;
         })
    }
     return inner;
}

方法二:

function currying() {
    let args = Array.prototype.slice.call(arguments)
    return function inner(...newArgs) {
        console.log("newArgs",newArgs);
        if (newArgs.length) {
            args = [...args,...newArgs]
            return inner;
        } else {
       // 调用这个函数
          let result = args.reduce((pre,cur)=>pre+cur,0)
          args = [];
          return result;
      }
    }
}

4.Array.prototype.flat()

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

function myFlat(arr,depth){
    if(!Array.isArray(arr) || depth<=0){
        return arr;
    }

    // 嵌套
    return arr.reduce((pre,cur)=>{
        if(Array.isArray(cur)){
            return pre.concat(myFlat(cur,depth-1))
        }else{
            return pre.concat(cur);
        }
    },[])
}

测试

const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(myFlat(arr2,2)) 

image.png

5.Array.prototype.filter()

filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。

Array.prototype.myFilter=function (func) {
    let arr = this;
    let result = []
    len = arr.length;
    for (let i = 0; i < len; i++) {
        if (func(arr[i])) {
            result.push(arr[i])
        }
    }
    return result;
}

// 测试
data = [1, 2, 3, 4, 5, 6]
const res = data.myFilter(function (num) {
    return num % 3 == 0;
})
console.log(res) //3,6

6.Array.prototype.map()

map() 方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。

Array.prototype.myMap = function(func){
    const result = [];
    let arr = this;
    let len = arr.length;
    for (let i =0 ; i<len ; i++){
        result.push(func(arr[i]));
    }
    return result;
}
// 测试
arr = [1,2,3,4,5,6]
const res = arr.myMap(function(num){
    return num = num -1;
})
console.log(res) //[0,1,2,3,4,5]

7.打印红绿灯

const traffic_light=(color,delay)=>{
    return new Promise((resolve,reject)=>{
      console.log(`现在是${color}灯`);
      setTimeout(()=>{
          resolve()
      },delay)
    })
  }
  
 const main=()=>{
      Promise.resolve()
      .then(()=>{
          return traffic_light('红',3000)
      })
      .then(()=>{
          return traffic_light('黄',1000)
      })
      .then(()=>{
          return traffic_light('绿',2000)
      })
      .then(()=>{
          main();
      })
  }
  
main()
  

8. 异步加载图片

function loadImage(src){
    const img = document.createElement('img')
    img.src = src
    return new Promise((resolve,reject)=>{
        img.onload = function(){
            resolve(img)
        }
        img.onerror = function(){
            const error = new Error("picture error")
            reject(error)
        }
    })
}

loadImage(url).then(img =>{
    console.log(img)
})