js-高级

1、闭包:  

闭包:函数内部的函数,内部函数持有外部函数内变量的引用

面试官:谈谈对JS闭包的理解及常见应用场景(闭包的作用)_ LYFlied的博客-CSDN博客_前端面试谈谈对闭包理解

闭包 - JavaScript | MDN

优点:

避免全局变量的污染
能够读取函数内部的变量
可以在内存中维护一个变量
缺点:

1.闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

闭包中的this:(99条消息) 闭包中的this(难点)_微辣-的博客-CSDN博客_闭包中的this

应用:

setTimeout传参(原生的setTimeout传递的第一个函数不能带参数)

为dom节点循环绑定click事件

用户事件上(点击或者按键)绑定的回调函数

封装变量(将操作的变量或对象隐藏起来,只允许特定的方法才能访问和修改)

javascript闭包和立即执行函数的作用 - carrie_zhao - 博客园 (cnblogs.com)

 function count(){
       var i=0;
       return function () {
           return ++i;
       }
   } 
   c1 = count();
   console.log(c1());  //print1
   console.log(c1());  //print2
   c2 = count();
   console.log(c2());  //print1

闭包就是创建了内部变量,不能被外部随意的修改,但是能够通过特定的接口来获取。

一般来说闭包会和立即执行函数配合使用,来创建一个单例的,有着私有成员的对象。jquery中的封装便是使用了闭包和立即执行函数的思想

立即执行函数

这是一个被称为 自执行匿名函数 的设计模式,主要包含两部分。第一部分是包围在 圆括号运算符 () 里的一个匿名函数,这个匿名函数拥有独立的词法作用域。这不仅避免了外界访问此 IIFE 中的变量,而且又不会污染全局作用域。

第二部分再一次使用 () 创建了一个立即执行函数表达式,JavaScript 引擎到此将直接执行函数。

用途:立即执行函数可以产生一个私有作用域,避免函数内变量暴露全局,避免改污染局变量;执行完立即释放。

立即执行函数能够对函数实现封装,从而达到避免污染全局变量的目的。立即执行函数可以在函数前用!+ - =等符号来实现,但是建议使用双括号包裹来实现,从而实现块级结构,再多人开发中不会互相影响。
使用情况: 需要控制变量作用范围时、需要单独封装某些独立模块时候。
注意:多个立即执行函数之间要加分号,只有函数表达式才能被执行符号执行

var a=2;
function fun(){
    console.log(this);
    console.log(this.a);
}
var o={a:3, fun:fun};
var p={a:4};
o.fun();
(p.fun=o.fun)();
(p.fun)();

2、JS作用域 

作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域、函数作用域和块作用域。

function foo() {
    foo.abc = function() {console.log('456');};
    this.def = this.abc;
    this.abc = function() { console.log('def'); };
    abc = function() { console.log('@@@@@@');}
    var abc = function() { console.log('$$$$$$');}
}
foo.abc = function() { console.log('123');};
foo.prototype={
    abc:function() { console.log('abc');}
}
foo.abc();
var f = new foo();
f.def();
f.abc();
foo.abc();

如何理解javascript的作用域? - 知乎 (zhihu.com)

JavaScript中的执行上下文和变量对象 - SegmentFault 思否

Javascript中的词法作用域、动态作用域、函数作用域和块作用域(四) - youyi2016 - 博客园 (cnblogs.com)

 词法作用域:在词法阶段定义的作用域,也就是说词法作用域在代码书写时就已经确定了。

动态作用域:在函数调用时确定的 

     js中其实只有词法作用域,并没有动态作用域,this的执行机制让作用域表现的像动态作用域,this的绑定是在代码执行的时候确定的。

通过eval和with都可以用来修改词法作用域。

函数作用域和块作用域

      1、创建作用域的方式

          a)通过函数创建局部作用域

              1、通过函数声明的方式创建

              2、通过函数表达式创建:

              匿名函数表达式和具名函数表达式

              区别函数表达式和函数声明的方式就是看声明的第一个关键字是否是function开头

          b)通过with、try...catch、let和const创建块作用域

              值得提的是let和const定义的块作用域

              let在声明变量时,会将变量附加在一个已经存在的块作用域上,一般是{}(隐式附加),let声明的变量是在js运行的时候才存在的。

函数B在执行的时候,是会引用函数A的作用域的。所以,像这种函数作用域的嵌套就组成了所谓的函数作用域链。当在自身作用域内找不到该变量的时候,会沿着作用域链逐步向上查找,若在全局作用域内部仍找不到该变量,则会抛出异常。

3、垃圾回收:

内存管理 - JavaScript | MDN

JavaScript中的垃圾回收机制_白纸一样的博客-CSDN博客_js垃圾回收机制

一些优化:

  • 分代回收——对象分为两组:“新对象”和“旧对象”。许多对象出现,完成它们的工作并迅速结 ,它们很快就会被清理干净。那些活得足够久的对象,会变“老”,并且很少接受检查。
  • 增量回收——如果有很多对象,并且我们试图一次遍历并标记整个对象集,那么可能会花费一些时间,并在执行中会有一定的延迟。因此,引擎试图将垃圾回收分解为多个部分。然后,各个部分分别执行。这需要额外的标记来跟踪变化,这样有很多微小的延迟,而不是很大的延迟。
  • 空闲时间收集——垃圾回收器只在 CPU 空闲时运行,以减少对执行的可能影响。 
  • 并发标记与并行标记

标记紧缩法: 压缩内存成连续的空间

4、原型链

es6中的class真正的本质是一个语法糖!class的本质还是function

在js中对象分为两种:普通对象(Object)和函数对象(Function)。

所有的引用类型都具有隐式原型属性(__proto__),只有函数对象有显式原型属性(prototype--原型对象)。

原型链:原型链是针对原型对象的,在查找实例属性时,先在实例中查找,如果没有找到,再到obj.__proto__(=f1.prototype)原型对象,再到f1.prototype.__proto__(=f2.prototype),依次向上查找。

原型、原型对象和原型链_cpsxn的博客-CSDN博客

原型(prototype属性)和原型链。 重要!!! - 全情海洋 - 博客园

原型和原型链 prototype和proto的区别_小丞同学-CSDN博客_原型和原型链区别

原型继承 - 廖雪峰的官方网站

**一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。

5、JS 常见的 6 种继承方式

一篇文章理解JS继承——原型链/构造函数/组合/原型式/寄生式/寄生组合/Class extends-阿里云开发者社区 (aliyun.com)

(88条消息) JS实现继承的6种方式_尘埃丶落定的博客-CSDN博客_js继承的6种方式

寄生组合实现:

function Super(foo) {
  this.foo = foo;
}
Super.prototype.printFoo = function () {
  console.log(this.foo);
};
function Sub(bar) {
  this.bar = bar;
  // 调用父类的构造函数
  Super.call(this);
}
// 将子类是原型绑定在父类原型的复制对象上,之后修改子类原型就不会影响父类原型
Sub.prototype = Object.create(Super.prototype);
// 让子类原型的构造函数指向子类构造函数
Sub.prototype.constructor = Sub;

ES6-class实现:

class Super {
  constructor(foo) {
    this.foo = foo;
  }
  printFoo() {
    console.log(this.foo);
  }
}
class Sub extends Super {
  constructor(foo, bar) {
    Super(foo);//注意子类必须要有super()函数
    this.bar = bar;
  }
}

6、宏任务、微任务和事件循环

浏览器的tab标签页(一个页面)就是一个进程, 一个页面(进程)中又同时可以存在多个线程
下面就给大家介绍浏览器的线程

1、GUI 渲染线程 (可以理解为html css渲染的线程)
负责渲染浏览器界面HTML元素,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。在Javascript引擎运行脚本期间,GUI渲染线程都是处于挂起状态的,也就是说被”冻结”了.
想要了解浏览器渲染流程可以看看另一篇文章,浏览器渲染原理浏览

2、JS 引擎线程
JS内核,负责处理Javascript脚本主程序。一直等待着任务队列(下面会将什么是任务)中任务的到来,然后解析Javascript脚本,运行代码。浏览器中的一个Tab标签页(一个页面,也就是一个进程)中无论什么时候都只有一个JS线程在运行JS程序。GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。

3、定时器触发线程

定时器setInterval与setTimeout所在线程
浏览器定时计数器并不是由JavaScript引擎计数的 因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确, 因此通过单独线程来计时并触发定时是更为合理的方案。
定时器到时间后就会把回调函数放到任务队列中,等待js引擎处理
4、浏览器事件线程

用来控制事件,JS引擎自己忙不过来,需要浏览器另开线程协助
当JS引擎执行代码块如鼠标点击click、onload等等事件,会将对应任务添加到事件触发线程中
当对应的事件符合触发条件被触发时,该线程会把事件对应的函数添加到待处理任务队列的队尾,等待JS引擎的处理
由于JS的单线程关系,所以这些待处理任务队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)
5、http 请求线程
在XMLHttpRequest在连接后是通过浏览器新开一个线程请求, 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript引擎的任务队列中等待处理。
上面说了很多次的任务队列,那什么是任务队列呢,为什么要有任务队列呢?
大家现在都知道了js是单线程的语言,所有的任务都在一个线程上面执行,任务排成一队,形成了队列,所以我们就称为任务队列注释:这里说的任务,其实就是我们程序员写的每一行代码, 或者每个代码块
排在前面的任务就先执行,排在后面的任务就要等前面的任务执行完成了,才能执行,这样就很容易造成阻塞,因此引入了事件循环(EventLoop)机制。
原文链接:https://blog.csdn.net/weixin_34873494/article/details/113085313

渲染过程

页面并不是时时刻刻被渲染的,浏览器会有固定的节奏去渲染页面,称为 render steps。它内部分为 3 个小步骤,分别是

  • Structure - 构建 DOM 树的结构
  • Layout - 确认每个 DOM 的大致位置(排版)
  • Paint - 绘制每个 DOM 具体的内容(绘制)

requestAnimationFrame

是一个特别的异步任务,只是注册的方法不加入异步队列,而是加入渲染这一边的队列中,它在渲染的三个步骤之前被执行。通常用来处理渲染相关的工作。

宏任务、微任务

macro-task(Task):

  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI rendering

micro-task(Job): 

  • process.nextTick
  • promises
  • Object.observe
  • MutationObserver

微任务、宏任务与Event-Loop - 贾顺名 - 博客园

宏任务和微任务到底是什么? - 简书

JS浏览器事件循环机制 - 街边微凉小悲伤 - 博客园

7、浏览器缓存:

 深入理解浏览器的缓存机制 - 简书 (jianshu.com)

浏览器缓存 - 掘金 (juejin.cn)

前端缓存——Service Worker(重点介绍)_、妤的博客-CSDN博客_service worker缓存

浏览器中js运行在单一主线程中,同一时间只能做一件事情。 如果一段代码运算太过耗时,就会一直占用浏览器主线程,造成性能下降。基于这个问题,W3C提出了web Worker,将耗时太长的任务交给web worker,然后通过post Message告诉主线程,主线程通过onMessage得到结果。但是web Worker是临时的,每次运行的结果不能持久的保持下来,下次有复杂的运算,还需要重新计算一次。为了解决这个问题,推出了Service Worker,相对于web worker增加了离线缓存能力。
Service Worker是一个事件驱动worker,运行在一个单独的后台进程,是PWA(ProgressiveWeb App)运行的基础。主要用于代理网页请求,可缓存请求结果;可实现离线缓存功能,也拥有单独的作用域范围和运行环境。我们以后把Service Worker简称为SW。
链接:https://www.jianshu.com/p/cc506d408d69

8、Cookie、Session、Token、JWT

Springboot之登录模块探索(含Token,验证码,网络安全等知识) - 简书 (jianshu.com)

还分不清 Cookie、Session、Token、JWT? - 简书

JWT

五分钟带你了解啥是JWT - 知乎JSON Web Token 入门教程 - 阮一峰的网络日志

jwt存储:https://segmentfault.com/a/1190000022038919你的JWTs存储在哪里 - 简书

jwt单点登录:使用JWT实现单点登录(完全跨域方案)_Helon的博客-CSDN博客_jwt

9、页面加载过程

第一步:DNS解析

将用户输入的域名转化成IP

第二步:浏览器向服务器发起TCP连接请求

经过TCP三次握手,建立TCP连接。

第三步:服务器返回数据

服务器会判断访问者能不能访问,比如:访问者IP是不是合法,是不是在黑名单里等等。
可以访问的话,服务器会返回响应的数据包。

第四步:浏览器加载和渲染页面

包括HTML的解析,静态资源的加载,CSS的渲染,JS 脚本的运行等。

具体步骤如下:
1. 输入URL后,首先进行DNS解析得到IP地址。
DNS:Domain Name System,是一个域名系统。DNS解析的过程就是寻找哪个服务器上有请求的资源。因为ip地址不容易记忆,一般会使用URL域名(如www.baidu.com)作为网址。DNS解析就是将域名翻译成IP地址的过程。
首先会查询缓存,如果缓存不存在则到dns服务器查询对应的ip地址。会有以下几个步骤:
  1). 查询浏览器中是否有缓存:浏览器会按照一定的频率 缓存DNS记录;
  2).查询本机操作系统中是否有缓存:如果浏览器缓存中找不到需要的DNS记录,就会去操作系统中找;
  3).查询路由器缓存:路由器中也有DNS缓存;
  4).ISP的DNS服务器:ISP有专门的DNS服务器应对DNS查询请求
  5)根服务器:ISP的DNS服务器找不到之后,就要向根服务器发出请求,进行递归查询。
2. 浏览器根据IP地址与服务器进行连接,期间利用TCP协议进行三次握手
3.浏览器根据解析到的IP地址和端口号发起http的get请求
http请求包括header和body。header中包括请求的方式(get和post)、请求的协议 (http、https、ftp)、请求的地址ip、缓存cookie。body中有请求的内容。
4.服务器接收到http请求之后,开始搜索html页面,并使用http返回响应报文
5.浏览器解析响应数据,并渲染页面
6.由上向下解析 HTML 文档,以 字节 – 字符 – 标签 – 节点 – 树 的转化顺序将文档同步构建为 DOM 树和 CSSOM 树
原文链接:https://blog.csdn.net/qq_38705158/article/details/117808840

浏览器页面渲染过程

  1)浏览器根据深度遍历的方式把html节点遍历成dom 树

  2)将css解析成CSS DOM树

  3)将dom树和CSS DOM树构造成render树

  4)JS根据得到的render树 计算所有节点在屏幕中的位置,进行布局(回流)

  5)遍历render树并调用硬件API绘制所有节点(重绘)

     补充: 构造render渲染树的过程

  1. 从DOM树的根节点开始遍历每个可见的节点。
  2. 对于每个可见的节点,找到CSS树中的对应的规则,并且应用他们。
  3. 根据每个可见的节点及其对应的样式,组合生成渲染树。

HTML页面渲染及优化详解:HTML页面渲染及优化详解 - 简书

10、TCP三次握手、四次挥手 

面试题:TCP协议三次握手 - 阿善9 - 博客园

经典面试题之 TCP三次握手 和 TCP四次挥手过程----详解_孤城286的博客-CSDN博客_http三握手四挥手面试题

11、前端性能优化

前端性能优化可以分为三个level:静态资源优化、接口访问优化、页面渲染速度优化

前端性能优化的三个维度_青梅主码的博客-CSDN博客
具体操作  

前端性能优化汇总 - 会飞的猪~~ - 博客园

12、浏览器兼容性问题

1. IE不支持substr(-2);substr(负数)是从后往前计算截取,-1 指字符串中最后一个字符。substring()参数不能为负数,若强行传递负数,在执行时会被当成0处理。

2. IE解析日期字符串时不支持以下标准时间格式的第一种用-连接的时间格式的;谷歌都支持。

标准时间格式有:

1.YYYY-MM-DD 2000-01-01 01:01:01 | 2000-1-1 1:1:1
2.MM-DD-YYYY 01-01-2000 01:01:01 | 1-1-2011 1:1:1
3.YYYY/MM/DD 2000/01/01 01:01:01 | 2000/1/1 1:1:1
4.MM/DD/YYYY 01/01/2000 01:01:01 | 1/1/2000 1:1:1

13、HTTP请求头中各字段解释

HTTP请求头中各字段解释 - JamelAr - 博客园

总结HTTPS传输过程
客户端先从服务器获取到证书,证书中包含公钥
客户端将证书进行校验
客户端生成一个对称密钥,用证书中的公钥进行加密,发送给服务器
服务器得到这个请求后用私钥进行解密,得到该密钥
客户端以后发出后续的请求,都使用这个对称密钥进行加密。
服务器收到这个密文也用这个密钥进行解密。

14、简述https的几种加密方式

简述https的几种加密方式_田维常-CSDN博客

15、对称加密和非对称加密介绍和区别

对称加密和非对称加密介绍和区别 - liluxiang - 博客园

非对称加密算法:RSA,DSA/DSS     需要两个密钥:公开密钥和私有密钥;公开密钥与私有密钥是一对。如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。主要是用来保护传输客户端生成的用于对称加密的随机数私钥
对称加密算法:AES,RC4,3DES,IDEA     特点是文件加密和解密使用相同的密钥加密;对称加密算法使用起来简单快捷,密钥较短,且破译困难。除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高。
HASH算法:BASE64、MD5、SHA、HMAC 是一种单向算法,用户可以通过hash算法对目标信息生成一段特定长度的唯一hash值,却不能通过这个hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。比如在确认握手消息没有被篡改时使用 ;
常用Java加密算法/HASH算法:

1.BASE64 (严格来说属于编码格式,而非加密算法):是网络上最常见的用于传输8bit字节代码的编码方式之一。base64编码可用于在http环境下传递较长的标识信息,采用base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。

2.MD5(信息摘要算法):用于确保信息传输完整一致,又名杂凑算法,摘要算法、哈希算法;将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理。广泛用于加密和解密技术,常用于文件校验,不管文件多大,经过md5后都能生成唯一的MD5值。比如ISO校验,把ISO经过MD5后产生的MD5值,一般下载linux-ISO会看到下载链接旁边放着MD5的串,就是用来验证文件是否一致。

MD5算法具有以下特点:

1>压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2>容易计算:从原数据计算出MD5值很容易。
3>抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4>弱抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
5>强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。

3.SHA(安全散列算法):主要适用于数字签名标准里面定义的数字签名算法。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可理解为取一串输入码,并把他们转为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。散列函数值可以说是对明文的一种“指纹”或“摘要”所以对散列值的数字签名就可以视为对此明文的数字签名。

SHA-1与MD5的比较:二者均由MD4导出,SHA-1和MD5彼此很相似。但还有以下几点不同:

1>对强行攻击的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。SHA-1对强行攻击有更大的强度。

2>对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。

3>速度:在相同的硬件上,SHA-1的运行速度比MD5慢。

4.HMAC(散列消息鉴别码):基于密钥的Hash算法的认证协议,它实现的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传出,接收方利用与发送方共享的密钥进行鉴别认证等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值