Record and learn at any time(js)

178 阅读6分钟

解构赋值

数组或者对象解构赋值并设置默认值
资料见

const { name: assign = 'lisi'} = { name: 'zs', age: 18 }
const { sex: hasDefaultValue = 'lisi'} = { name: 'zs', age: 18 }
const [ arrFirstValue = 'first-value' ] = []
const [ , arrsecondValue = 'second-value' ] = ['red', 'yellow']
console.log('assign:', assign) // assign: zs
console.log('hasDefaultValue:', hasDefaultValue) // hasDefaultValue: lisi
console.log('arrFirstValue', arrFirstValue) // arrFirstValue: first-value
console.log('arrSecondValue', arrsecondValue) // arrFirstValue: first-value

decodeURIComponent()

作用:对编码后的url进行解码

decodeURIComponent('http%3A%2F%2Fwww.w3school.com.cn%2FMy%20first%2F')
// "http://www.w3school.com.cn/My first/"

this指向问题

  • 谁调用this就指向谁(直接调用者)
const obj = {
   a: 10,
   b: {
      a: 12,
      fn: function() {
        console.log(this.a)
      }
   }
}
obj.b.fn() // 12 <=直接调用者
  • 箭头函数没有作用域,指向上一层
var id = 1
function fn() {
  setTimeout(() => {
     console.log(this.id)
  })
}
fn({id: 66}) // 1
// 想要改变,可以使用call(),apply(),bind(),用法待补充todo
  • var 定义的变量会挂载到window上 => window.变量名 = 值
  • let 定义的变量不会
var usernames = 'zs'
function fn() {
  console.log(this.usernames);
}
fn() // zs

let username = 'zs'
function fn() {
  console.log(this.username);
}
fn() // undefined

new关键字

防抖和节流

防抖:触发事件后n秒才执行函数,如果在n秒内触发了事件,则会重新计算函数执行时间。

function debounce(fn, wait) {
    let timer = null;
    return function() {
        const context = this;
        const args = arguments;
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
             fn.apply(this, args);
        }, wait);
    }
}

节流:连续触发事件但在n秒内只执行一次

// 时间戳版本
function throttle(fn, wait) {
    let perv = 0;
    return function() {
        const now = Date.now();
        const content = this;
        const args = arguments;
        if (now - prev > wait) {
            fn.apply(this, args);
            perv = now;
        }
    }
}

// 定时器版本
funciton throttle(fn, wait) {
    let timer = null;
    return function() {
        const context = this;
        const args = arguments;
        if (!timer) {
            timer = setTimeout(() => {
                timer = null;
                fn.apply(context, args);
            }, wait)
        }
    }
}

线程和进程

进程:一个进程就是一个程序的运行实例,启用一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码,运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程。

线程:多线程可以并行处理任务,但是线程是不能单独存在的,它是由进程来启动和管理的,线程是依附于进程的。

image.png

进程和线程之间的关系

  • 进程中的任意一线程执行出错,都会导致整个进程的崩溃
  • 线程之间共享进程中的数据
  • 当一个进程关闭之后,操作系统会回收进程所占用的内存
  • 进程之间的内容相互隔离

image.png

从输入URL到页面展示,这中间发生了什么?

image.png 关注点:从进程间考虑

  1. 浏览器进程收到用户输入的url请求,通过进程间通信(IPC)把URL发送到网络进程
  2. 网络进程会首先在本地查找资源,如果本地有缓存直接将资源返回给浏览器进程
  3. 如果没有,进程网络请求流程
  4. 首先进程DNS域名解析,获取请求域名的服务器IP地址
  5. 利用IP地址和服务器进行TCP连接,建立连接之后,浏览器端会构建请求行、请求头等信息,并把该域名相关的cookie等数据附加到请求头中,然后向浏览器发送构建的请求信息
  6. 在接收到相应信息后,网络进程开始解析响应头,如果返回的是301、302则表示服务器需要浏览器重定向到其他URL,网络进程会读取重定向的地址,重新发起请求
  7. 会根据响应头返回的信息Content-Type中来对应处理
  8. 如果Content-Type返回的是html,则进行渲染进程的处理
  9. 浏览器进程在收到网络进程返回的响应数据之后,便向渲染进程发送‘提交文档’的消息
  10. 渲染进程收到消息之后,便向网络进程建立起管道
  11. 待文档数据处理完成后,渲染进程便向浏览器进程发送‘确认提交的消息
  12. 浏览器进程收到渲染进程的‘确认提交’的信息之后,会更新浏览器页面状态,包括安全状态、地址栏的URL、前进后退的历史状态,更新WEB页面。
  13. 渲染进程对文档进行页面解析和子资源加载,HTML 通过HTM 解析器转成DOM Tree(二叉树类似结构的东西),CSS按照CSS 规则和CSS解释器转成CSSOM TREE,两个tree结合,形成render tree(不包含HTML的具体元素和元素要画的具体位置),通过Layout可以计算出每个元素具体的宽高颜色位置,结合起来,开始绘制,最后显示在屏幕中新页面显示出来

函数柯里化

定义:一个函数原本有多个参数,只传入一个参数,生成一个新的函数,由新函数接收剩下的参数来运行得到结构。

【对对象属性访问的解析方法】 其他解析方法可以参数lodash源码

function fnByPath(path) {
   return funciton fnByObj(obj) {
     const paths = path.split('.');
     let res = obj;
     let prop = '';
     while(prop = paths.shift()) {
         res = res[prop];
     }
     return res;
   }
}

箭头函数

箭头函数和普通函数的区别:

  1. this指向的是上一层执行环境的this,同时super,arguments,new.target这些值都是由外层的函数决定
  2. 不能通过new关键字调用,箭头函数没有construct方法,不能作为构造函数
  3. 没有原型,不存在prototype属性
  4. 不可以改变this的绑定
  5. 没有自己的arguments对象,如果要获取自己的,可以通过命名参数和不定参数(...reset)这两种形式访问函数的参数
  6. 不支持重复的命名参数

link和@import的区别

  1. 加载资源的限制:link是xhtml标签,除了加载css文件外,还可以加载RSS等其他事务,如加载模板等,而@import只能加载css文件
  2. 加载顺序:link会和页面并行加载,而@import会等页面加载完毕之后,再载入css文件
  3. 兼容性:link是xhmtl标签,没有兼容性问题,而@import不支持低版本的浏览器
  4. 改变样式:link标签是DOM标签,支持通过js控制DOM和修改样式,@import不支持。

常见的浏览器内核有哪些

  1. Trident: IE
  2. WebKit: Safari,旧版的Chrome
  3. Blink: Chrome,Opera
  4. Gecko: Firefox

ES5/ES6的继承除了写法之外还有什么区别?

  1. class声明会提升。但是不会初始化赋值。(类似于let、const)声明变量;
  2. class声明内部会启用严格模式;
  3. class的所有方法(包括静态方法和实例方法)都是不可枚举;
  4. class的所有方法(包括静态方法和实例方法)都没有原型对象,所以也没有constructor,不能通过new来调用;
  5. 必须通过new来调用class;
  6. class内部无法重写类型;

手写bind、call、apply

Array.prototype.MyCall = function(context) {
    const args = [...arguments].slice(1);
    context.fn = this;
    const result = context.fn(...args);
    delete context.fn;
    return result;
}
Array.prototype.MyApply = function(context) {
    const args = arguments[1] || [];
    context.fn = this;
    const result = context.fn(...args);
    delete context.fn;
    return result;
}
Array.prototype.MyBind = function(context) {
    const args = [...arguments].slice(1);
    return function () {
        context.MyApply(context, args);
    }
}