# 常见代码实现

# 数组去重

1、双层for循环,定义一个res空数组,把不重复的元素推进去,如果外层循环中的元素和res数组的元素相等就break出去,不相等执行完循环后j的值就和res的长度一样,通过这个判断添加到res数组中。

var arr = [1, 1, '1', 3, 'a', 'b', true, true, false, 'true'];

function unique(arr) {
  var res = [];
  for(var i = 0; i < arr.length; i++) {
    for(var j = 0; j < res.length; j++) {
      if (arr[i] === res[j]) break; // 跳出循环,j的值就不能和res.length相等了
    }
    // 用循环后j的值和res.length比较,如果一样就说明没有相等的。
    if (j === res.length) res.push(arr[i])
  }
  return res
}

2、使用空的obj对象。声明一个空的对象和空的数组,for循环遍历数组,将数组里面的元素作为空对象的属性属性值随便取,用对象的属性作为判断条件,如果为真,就不操作,如果为false,就将数组的元素 push到声明空数组中

var arr = [1, 1, '1', 3, 'a', 'b', true, true, false, 'true'];
function unique(arr) {
  var res = []
  var obj = {}
  for (var i = 0; i < arr.length; i++) {
    if (!obj[arr[i]]) {
      res.push(arr[i])
      obj[arr[i]] = 1 // 随便赋值一个不为false的值
    }
  }
  return res
}
unique(arr) // [1, 3, "a", "b", true, false]

可以看出,虽然去重了,但是1和‘1’都去掉了,因为对象的键值只能是字符串,我们可以根据typeof item + item作为key值来进行重新去重。

var arr = [1, 1, '1', 3, 'a', 'b', true, true, false, 'true'];
function unique(arr) {
  var res = []
  var obj = {}
  for (var i = 0; i < arr.length; i++) {
    if (!obj[typeof arr[i] + arr[i]]) { // typeof + item
      res.push(arr[i])
      obj[typeof arr[i] + arr[i]] = 1 
    }
  }
  return res
}
unique(arr) // [1, "1", 3, "a", "b", true, false, "true"]

利用这种思想,我们还可以用允许各种类型为属性的map来替代。

3、indexOf()方法

新建一个空数组res,遍历一次arr数组,如果res使用indexOf方法能找到arr中的值就啥也不干,找不到就把值push到res中。

var arr = [1, 1, '1', 3, 'a', 'b', true, true, false, 'true'];
function unique(arr) {
  var res = []
  for (var i = 0; i < arr.length; i++) {
    if (res.indexOf(arr[i]) === -1) res.push(arr[i])
  }
  return res
}

unique(arr) // [1, "1", 3, "a", "b", true, false, "true"]

4、includes() 方法 和indexOf方法类似

var arr = [1, 1, '1', 3, 'a', 'b', true, true, false, 'true'];
function unique(arr) {
  var res = []
  for (var i = 0; i < arr.length; i++) {
    if (!res.includes(arr[i])) res.push(arr[i])
  }
  return res
}

unique(arr) // [1, "1", 3, "a", "b", true, false, "true"]

5、利用filter方法,通过indexOf方法返回和当前index值一样的元素,如果重复就会获取之前重复的值,和当前的index值不一样。

var arr = [1, 1, '1', 3, 'a', 'b', true, true, false, 'true'];
function unique(arr) {
  return arr.filter((item, index) => arr.indexOf(item) === index)
}

unique(arr) // [1, "1", 3, "a", "b", true, false, "true"]

6、ES6的map和set方法。

set去重转为数字:

var arr = [1, 1, '1', 3, 'a', 'b', true, true, false, 'true'];
function unique(arr) {
  // return Array.from(new Set(arr))
  return [...new Set(arr)]
}

map类似json那种思想:

var arr = [1, 1, '1', 3, 'a', 'b', true, true, false, 'true'];
function unique(arr) {
  var res = []
  var map = new Map();
  for (var i = 0; i < arr.length; i++) {
    if (!map.get(arr[i])) {
      res.push(arr[i])
      map.set(arr[i], 111)
    }
  }
  return res
}
unique(arr) // [1, "1", 3, "a", "b", true, false, "true"]

# 实现防抖函数和节流函数

防抖函数:

function debounce(fn, wait) {
  var timer = null;
  return function() {
    var _this = this;
    var args = arguments;
    if (timer) clearTimeout(timer)
    timer = setTimeout(function() {
      fn.apply(_this, args);
    }, wait)
  }
}
function handle(arg) {
  console.log(arg)
}
var debounceCallback = debounce(handle, 1000);
window.addEventListener('scroll', function(e) {
  debounceCallback(e)
})

节流函数:

// 时间戳版
function throttle(fn, delay) {
  var start = Date.now();
  return function() {
    var _this = this;
    var args = arguments;
    var end = Date.now();
    if (end - start > delay) {
      fn.apply(_this, args);
      start = end;
    }
  }
}

// 定时器版
function throttle(fn, delay) {
  var timer = null;
  return function() {
    var _this = this;
    var args = arguments;
    if (!timer) {
      timer = setTimeout(function() {
        fn.apply(_this, args);
        timer = null;
      }, delay)
    }
  }
}

function handle(arg) {
  console.log(arg)
}
var debounceCallback = throttle(handle, 1000);
window.addEventListener('scroll', function(e) {
  debounceCallback(e)
})

# 实现深拷贝

function deepClone(target) {
  if (typeof target === 'object') {
    var cloneTarget =  Array.isArray(target) ? [] : {};
    for(var key in target) {
      cloneTarget[key] = deepClone(target[key])
    }
    return cloneTarget
  } else {
    return target
  }
}

# 封装一个Ajax

function ajax(params) {
  return new Promise(function (resolve, reject) {
    var xhr = null;
    xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
    var data = "";
    if (params.data) {
      for (var key in params.data) {
        data += key + "=" + params.data[key] + "&"
      }
      var i = data.lastIndexOf("&");
      data = data.substring(0, i);
    }
    if (data && params.method == "get") {
      params.url = params.url + "?" + data;
    }
    xhr.open(params.url, params.method, true);
    //send
    if (params.method == "get") {
      xhr.send();
    } else {
      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      xhr.send(data);
    }
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        resolve(JSON.parse(xhr.responseText))
      } else {
        reject(new Error(xhr.responseText))
      }
    };
  })
}

ajax(params).then(function (data) {
  console.log(data)
  return ajax(data)
}, function (err) {
  console.log(err)
}).then(function (data) {
  console.log(data)
})

# 手写call、apply、bind

# 实现promise

# jsonp的实现

# 实现new

# sleep函数