前端-你需要掌握的 javascript 基础

2,382 阅读4分钟

前言

这段时间复习了 js 的基础,梳理了一下自己的整个知识掌握情况。 实现不一定是最优解,欢迎姐妹们讨论和指正,大家一起进步呀。

js 基础

包括:防抖、节流、闭包、柯里化、new、bind、apply、call、this、作用域、数据类型、常用数组&字符串&正则方法、排序、去重、拍平数组、深拷贝、跨域解决方案、promise

1. 防抖

function debounce_y(func, delay) {
  let timer = null;
  return function (...args) {
    timer && clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}

2. 节流

function trottle_y(func, delay) {
  let start = new Date();
  let timer = null;
  return function (...args) {
    timer && clearTimeout(timer);
    if (new Date() - start >= delay) {
      func.apply(this, args);
      start = new Date();
    } else {
      timer = setTimeout(() => {
        func.apply(this, args);
      }, delay);
    }
  };
}

3. 闭包

function count() {
  let count = 0;
  return function () {
    count++;
    console.log(count);
  };
}

4. 柯里化

function curry_y(func) {
  return function curried(...args) {
    if (args.length >= func.length) {
      func.apply(this, args);
    } else {
      return function (...args2) {
        curried.apply(this, args.concat(args2));
      };
    }
  };
}

5. new 操作符

function new_y(func) {
  let obj = {};
  obj.__proto__ = func.prototype;
  let res = func.apply(this);
  if (res instanceof Object) {
    return res;
  } else {
    return obj;
  }
}

6. 手写 bind

// 基础版
Function.prototype.bind_y = function (obj) {
  let that = this;
  return function (...args) {
    that.apply(obj, args);
  };
};
// 加强版-考虑bind还可以传入更多的参数作为函数的参数
Function.prototype.bind_y = function (obj, ...args0){
  let that = this;
  return function (...args){
    that.apply(obj, args0.concat(args));
  }
}
// 考虑到bind可以不传target,不传时默认为window
Function.prototype.bind_y = function (){
  let that = this; 
  let target = arguments[0];
  let args0 = Array.prototype.slice.call(arguments, 1);
  return function (...args){
    that.apply(target, args0.concat(args));
  }
}

7. 手写 apply

// 借用bind实现
Function.prototype.apply_y = function (obj) {
  return function (...args) {
    this.bind(obj)(args);
  };
};
// 不使用bind实现
Function.prototype.apply_y = function (target, args) {
  !target && (target = window);
  let fn = Symbol();
  target.fn = this;
  args ? target.fn(...args) : target.fn();
  delete target.fn;
};

8. 手写 call

Function.prototype.call_y = function (obj) {
  return function (...args) {
    this.bind(obj)(...args);
  };
};

9. this

// 普通函数中,this指向调用函数的对象,在调用时绑定
var name = "y";
var cat = { name: "miao" };
function a() {
  console.log(this.name);
}
a(); // y
a.apply(cat); // miao

// 箭头函数中,this继承自父函数,在声明时绑定
var name = "y";
var cat = { name: "miao" };
var a = () => {
  console.log(this.name);
};
a(); // y
a.apply(cat); // y

10. 作用域

// 变量声明提升
console.log(a); // 1
console.log(b); // Uncaught ReferenceError: b is not defined
console.log(c); // Uncaught ReferenceError: c is not defined
var a = 1;
let b = 2;
const c = 3;

// 函数声明提升
console.log(y); // ƒ y(){console.log("nice to meet you!")}
function y() {
  console.log("nice to meet you!");
}

11. 数据类型

基本类型存于栈内存,引用类型存于堆内存,从存取频率上可理解。
  • 基本类型 Number、 Boolean、String、Undefined、Null、BigInt、Symbol

  • 引用类型 Object、Array、Function、Date、RegExp

typeof 方法可以判断基本类型和函数;instanceof 方法可以判断引用类型;Object.prototype.toString.call()方法可以精确判断所有数据类型。

12. 常用数组&字符串& 正则方法

// 字符串方法
"abc".split("");
"abc".indexOf("a");
"abc".charAt(0);
"abc".replace("a", 1);
"abc".match("a");
"abc".matchAll("a");

// 数组方法
[1, 2, 3].join("");
[1, 2, 3].indexOf(1);
[1, 2, 3].findIndex((item) => item > 1);
[(1, 2, 3)][0];
[1, 2, 3].reduce((acc, item, index, arr) => {
  return acc + item;
});
[1, 2, 3].map((item, index) => {});
[1, 2, 3].forEach((item, index) => {});
[1, [2, 3]].flat(2);
[1, 2, 3].fill("a");
[1, 2, 3].includes(1);

// 正则方法
/[a-z]/.test("abc");
/([a-z])(?!\1)([a-z])/.exec("aac");

13. 排序

//  sort
[1, 3, 5, 2, 4, 6].sort((a, b) => {
  return a - b;
});

// 快速排序
function quickSort(arr) {
  if (arr.length < 2) return arr;
  let left = [];
  let right = [];
  let flag = arr.splice(arr.length - 1, 1)[0];
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] > flag) {
      right.push(arr[i]);
    } else {
      left.push(arr[i]);
    }
  }
  return quickSort(left).concat(flag, quickSort(right));
}

// 冒泡排序
function bubbleSort(arr) {
  for (let i = 0; i < arr.length - 1; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] > arr[j]) {
        [arr[i], arr[j]] = [arr[j], arr[i]];
      }
    }
  }
  return arr;
}

// 选择排序 
function selectSort(arr) {
  let min = 0;
  for (let i = 0; i < arr.length - 1; i++) {
    min = i;
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[min]) {
        min = j;
      }
    }
    [arr[i], arr[min]] = [arr[min], arr[i]];
  }
  return arr;
}

14. 去重

// new Set
new Set([1, 2, 1, 2]);

// 遍历
function uniq(arr) {
  for (let i = 0; i < arr.length - 1; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] === arr[j]) {
        arr.splice(j, 1);
        i--;
      }
    }
  }
  return arr;
}

15. 拍平数组

// flat
[1, [1, [3, 4]]].flat(3);

// 递归
function flat_y(arr) {
  let res = [];
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      res = res.concat(flat_y(arr[i]));
    } else {
      res.push(arr[i]);
    }
  }
  return res;
}

16. 深拷贝

function deepClone_y(obj, map = new Map()) {
  let type = Object.prototype.toString.call(obj);
  if (
    [
      "[object String]",
      "[object Number]",
      "[object Undefined]",
      "object Boolean",
    ].includes(type)
  )
    return obj;
  if (type === "[object Array]") {
    if (map.get(obj)) return map.get(obj);
    let arr = [];
    map.set(obj, arr);
    for (let i = 0; i < obj.length; i++) {
      arr.push(deepClone_y(obj[i], map));
    }
    return arr;
  }
  if (type === "[object Object]") {
    if (map.get(obj)) return map.get(obj);
    let res = {};
    map.set(obj, res);
    for (let key in obj) {
      res[key] = deepClone_y(obj[key], map);
    }
    return res;
  }
  // 函数类型新建函数方法:new Function('参数','函数体')
}

17. 跨域解决方案

域名协议端口都相同才叫做同源
  • jsonp 借助script标签实现跨域 ps: 已经过时了为什么还要考

  • webpack-dev-server proxy


proxy: {
    '/api': {
        target: 'http://127.0.0.1:7001/',
        changeOrigin: true,
        pathRewrite: {
            '^/api': '/api'
        }
    }
}
  • cors
Access-Control-Allow-Origin: http://www.test.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
  • node server请求转发

18. 手写 promise

class promise_y{
    constructor(executor){
        this.status = 'pending';
        this.value = undefined;
        this.reason = undefined;
        this.successCallbacks = [];
        this.failCallbacks = [];
        let resolve = (data) => {
            if(this.status === 'pending'){
                this.status = 'fullfilled';
                this.value = data;
                this.successCallbacks.forEach(func => func());
            }
        };
        let reject = (data) => {
            if(this.status === 'pending'){
                this.status = 'rejected';
                this.reason = data;
                this.failCallbacks.forEach(func => func());
            }
        }
        try{
            executor(resolve,reject);
        }catch(e){
            reject(e);
        }
    }
    then(onFullfilled, onRejected){
            if(this.status === 'fullfilled'){
                onFullfilled(this.value);
            }
            if(this.status === 'rejected'){
                onRejected(this.reason);
            }
            if(this.status === 'pending'){
                this.successCallbacks.push(() => {
                    onFullfilled(this.value);
                });
                this.failCallbacks.push(() => {
                    onRejected(this.reason)
                })
            }
    }
}

知识点还不完善,可以作为复习目录,后面会继续完善和更新,欢迎点赞和关注呀。写代码的女孩不容易,但请不要放弃,因为你不是一个人在战斗,加油。