Js 基础知识巩固

1,005 阅读5分钟

前言

由于很多小伙伴看了 《普通人如何进大厂》这篇文章对我的笔记比较感兴趣,所以我花时间整理提炼了一下跟大家分享,不保证内容完全正确,仅供参考哈

其他笔记传送门

原生 Js

Js 数据类型

基本类型:Number、Boolean、String、null、undefined、symbol(ES6 新增的),BigInt(ES2020) 引用类型:Object,对象子类型(Array,Function)

Object.prototype.toString.call 判断数据类型

什么是原型链

原型:

每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。

原型链:

每个构造函数都有prototype(原型)属性,而构造函数通过 new 创建的实例都能共享该原型属性,比如hasOwnProperty方法;那么是如何让实例对象访问到该方法到呢?答案就是原型链

原型链是指对象有一个__proto__指向Constructor.prototype,即 obj.proto = Constructor.prototype;当对象查找自身属性没有找到该属性时即会通过__proto__去查找构造函数的prototype,如果也没有找到,即再通过找构造函数原型的__proto__(Constructor.prototype.proto)去查找 ,不断往上游查找,查找过程就形成原型链

new 一个函数发生了什么

新建一个空对象,然后把该对象的 proto 属性指向构造函数的 prototype 属性,然后通过 apply 把 this 指向新对象,执行构造函数,返回执行结果。

function myNew () {
let obj = {}
let Con = [].shift.call(arguments)
obj.__proto__ = Con.prototype
let result = Con.apply(obj, arguments)
return result instanceof Object ? result : obj
}

什么是 Eventloop ?

事件循环机制从整体上告诉了我们 JavaScript 代码的执行顺序 Event Loop 即事件循环,是指浏览器或 Node 的一种解决 JavaScript 单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。

整个 Js 脚本是一个消息队列中的任务(宏任务)当遇到微任务时直接压到该消息队列 Js 事件任务的微任务队列中,

当遇到 setTimeout 就压倒延迟任务队列中(也是宏任务),当消息队列任务的同步代码执行结束后会去找微任务队列执行,

执行完毕微任务时,一个事件循环结束,执行到下一个宏任务 setTimeout,又是下一个事件循环。

微任务

它是跟一个宏任务绑定的,其实一个事件循环就是一个宏任务执行完成和它的微任务执行完成的过程。

它的出现是为了执行一些高效任务可以被先执行(dom 长变化),而又不影响主线程执行效率,例如 mutationObserver 就是采取微任务机制。

宏任务和微任务

async/await 原理

async/await语法糖就是使用Generator函数+自动执行器来运作的

判断数组的方法以及优缺点

  • Array.isArray(arr) :兼容性不好
  • arr instanceof Array
  • arr.proto === Array.prototype
  • arr.constructor === Array
  • Object.prototype.toString.call(arr) === '[object Array]'

js脚本加载问题,async、defer问题

  • 如果依赖其他脚本和 DOM 结果,使用 defer
  • 如果与 DOM 和其他脚本依赖不强时,使用 async

什么是作用域链?

JavaScript 引擎会沿着“当前执行上下文–>内嵌函数闭包–> 全局执行上下文”的冒泡的方式顺序查找变量,就形成了一条作用域链

this 的指向

  • 当函数作为对象的方法调用时,函数中的 this 就是该对象;
  • 当函数被正常调用时,在严格模式下,this 值是 undefined,非严格模式下 this 指向的是全局对象 window;

改变 this 指向的方式:

  • 用 call、apply、bind设置
  • 通过对象调用方法设置(指向该对象)
  • 通过构造函数中设置(构造函数this指向 new 的对象)

用过哪些设计模式

Javascript垃圾回收

当对象不再被 引用 时被垃圾回收机制回收(“对象有没有其他对象引用到它”)。

内存泄露就是不再被需要的内存, 由于某种原因, 无法被释放

  • 引用计数法:对象是否不再需要(限制:循环引入不能被回收)
  • 标记清除法:从根开始,找所有从根开始引用的对象标记,然后找这些对象引用的对象标记,把不能达到的回收(这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。)

避免内存泄漏:

  • 尽少创建全局变量
  • 手动清除计时器
  • 少用闭包
  • 使用弱引用WeakMap和WeakSet

0.1 + 0.2 === 0.3 嘛?为什么?

计算机存储以二进制的方式,而0.1 在二进制中是无限循环的一些数字,所以会出现裁剪,精度丢失会出现,0.100000000000000002 === 0.1,0.200000000000000002 === 0.2 // true 这两加起来肯定不等于0.3

解决:parseFloat((0.1 + 0.2).toFixed(10)) === 0.3 // true

es6 新特性

Proxy 有什么特点

用于修改某些操作的默认行为,(拦截对象对其内置方法进行重载)

可以直接拦截对象和数组

let target = {
    x: 10,
    y: 20
};
let hanler = {
    // obj=>target,prop =>x
    get: (obj, prop) => 42
};

target = new Proxy(target, hanler);
target.x; //42
target.y; //42
target.x; // 42

可以拦截的对象

  • get、set、has、apply、construct、ownKeys
  • deleteProperty、defineProperty、isExtensible、preventExtensions
  • getPrototypeOf、setPrototypeOf、getOwnPropertyDescriptor

实际用途:

  • 设置对象的初始值覆盖undefined
  • 缓存封装是否过期拦截

CommonJs 和 ES6 module 区别

  • 前者支持动态引入即require(${path}/xx.js),后者不支持
  • ES6 module 静态引入,即编译时引入,CommonJs 动态引入,即执行时引入
  • 前者是对模块的浅拷贝,后者是对模块的引用
  • 前者可以对导出对值赋值(改变指针),而后者不能相当于 const
  • 后者支持 tree shaking,前者不支持

什么是UMD

((root, factory) => {
    if (typeof define === 'function' && define.amd) {
        //AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        //CommonJS
        var $ = requie('jquery');
        module.exports = factory($);
    } else {
        root.testModule = factory(root.jQuery);
    }
})(this, ($) => {
    //todo
});

weak-Set、weak-Map 和 Set、Map 区别

WeakMap 是类似于 Map 的集合,它仅允许对象作为键,并且一旦通过其他方式无法访问它们,便会将它们与其关联值一同删除。

WeakSet 是类似于 Set 的集合,它仅存储对象,并且一旦通过其他方式无法访问它们,便会将其删除。

WebAssembly 是什么

WebAssembly 是一种可以使用非 JavaScript 编程语言编写代码并且能在浏览器上运行的技术方案

柯里化有什么作用

主要有3个作用: 参数复用提前返回延迟执行