JS 基础面试题

Js 有哪些数据类型,区别是什么?分别存储在什么数据结构中?

答:Js 有两种数据类型:基本类型引用类型

  • 基本类型:String / Number / Null / Undefined / Boolean / Symbol

    基本类型存储在栈内存中,它们的值都有固定的内存大小,通过按值访问,并由系统自动分配和自动释放,这样带来的好处就是,内存可以及时得到回收,相对于堆来说,更加容易管理内存空间。

  • 引用类型:Object / Array / Function

    引用类型存储在堆内存中,值大小不固定,栈内存中存放的该对象的访问地址,指向堆内存中的对象,JavaScript 不允许直接访问堆内存中的位置,因此操作对象时,实际操作对象的引用。

两种数据类型的区别在于:

栈内存堆内存
存储基础数据类型存储引用数据类型
按值访问按引用访问
存储的值大小固定存储的值大小不定,可动态调整
由系统自动分配内存空间由代码进行指定分配
空间小,运行效率高空间大,运行效率相对较低
先进后出,后进先出无序存储,可根据引用直接获取

浏览器从输入 URL 到渲染完页面这个过程发生了什么

从输入 URL 到渲染出整个页面的过程包括三个部分:

  1. DNS 解析 URL 的过程

    DNS 解析的过程就是寻找哪个服务器上有请求的资源,因为 ip 地址不容易记忆,一般会使用 URL 域名(如www.baidu.com)作为网址。DNS 解析就是将域名翻译成 IP 地址的过程。

  2. 浏览器发送请求与服务器交互的过程

    首先浏览器利用 tcp 协议通过三次握手与服务器建立连接,浏览器接收到返回的 html 页面之后,开始进行页面的渲染。

  3. 浏览器对接收到的 html 页面渲染的过程

    • 浏览器根据深度遍历的方式把 html 节点遍历成 dom 树
    • 将 css 解析成 CSS DOM 树
    • 将 dom 树 和 CSS DOM 树构造成 render 树
    • JS 根据得到的 render 树,计算所有节点在屏幕中的位置,进行布局(回流)
    • 遍历 render 树并调用硬件 API 绘制所有节点(重绘)

什么是闭包,他有什么优缺点

闭包就是一个绑定了执行环境的函数,可以访问到外部环境的变量
优点是:变量常驻内存,对实现一些类似于计时器的业务有帮助;实现私有变量,避免了命名冲突的问题。
缺点是:由于变量常驻内存,可能产生内存泄漏(可以引申问:为什么会发生内存泄露,内存泄露会发生在哪些场景)

call,apply,bind 的区别

call,apply,bind,三者都是用来改变函数的this对象的指向的。且第一个参数都是this要指向的对象,也就是想指定的上下文。
但传参的值也不同,apply后续只能传递数组,而call与bind可以传递多个参数。
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用。

JS有哪些储存

cookie:存储大小4K,每次请求都会携带在header中,有过期时间的设置,有安全和性能问题;
localstorage:本地存储,一旦设置就会永久存储,存储大小5M,不会和服务器有交互
sessionstorage:会话存储,页面关闭就被清除,存储大小5M,不会和服务器有交互

浏览器缓存

强制缓存 - 浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。
协商缓存 - 当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header 中的部分信息来判断是否命中缓存。如果命中,则返回 304 ,告诉浏览器资源未更新,可使用本地的缓存。

深拷贝和浅拷贝的区别

浅拷贝:可以通过 Object.assign;也可以通过扩展运算符(…)处理
深拷贝:简单通过 JSON.parse(JSON.stringify(object))来处理,缺点:会忽略 undefined,不能序列化函数,不能解决循环引用的对象;二是采用lodash库的深拷贝方法

事件委托和事件冒泡

事件委托

利用 js 事件冒泡的特性,将内层元素的事件委托给外层处理。

优点:

  1. 提高性能:减少每个子元素事件的注册,大量节省内存
  2. 动态监听:使用事件委托可以自动绑定动态添加的元素,无需再次对其绑定。

事件冒泡

由最开始接受元素接收,然后逐级向上传递到 DOM 最顶层节点的过程。可以形象的比喻成石头落入水中下降产生的泡泡从水底冒出水面的过程,这个就是事件冒泡阶段。

比方说在事件冒泡的概念下发生 click 事件的顺序是:

目标元素 -> body -> html -> document

阻止事件冒泡:e.stopPropagation (有的事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave 等)

什么是原型和原型链

原型:构造函数的内置对象,即 prototype ,每个构造函数都自带 prototype 属性,指向一个对象,常用实例共享属性和方法的。Prototype.constructor 会指向原构造函数

原型链:我们创建一个变量的时候,js 会给它一个默认的 _proto_ 属性,它执行创建它的函数对象的原型对象 prototype,同样的,函数对象的原型对象也有一个 _proto_ 属性,指向创建它的函数对象(Object)的原型对象, 而 Object.prototype 也有 _proto_ 属性,它的值为 null。

Person._proto_ ==> Person.prototype._proto_ ==> Obejct.prototype._proto_ ==> null

简述 JavaScript 的事件循环机制(Event loop)

详细解释:

  1. 同步任务和异步任务分别进入不同的执行环境,同步任务进入主线程,异步任务进入 Event Table 并注册函数
  2. 当指定的事情完成后,Event Table 会将这个函数移入到 Event Queue 中
  3. 主线程内的任务执行完毕,就会去 Event Queue 中读取对应的函数,进入主线程执行
  4. 上述过程不断重复,形成 Event Loop

ES6 有哪些常用特性

  1. let / const 【问他们的区别】
  2. 箭头函数 【问箭头函数和 es5 的 function 区别在哪里(答案是 this 作用域的指向,es5 是锁声明的函数体,剪头函数是全局)】
  3. 数组的扩展方法 【 map / reduce / filter / 等】
  4. set 和 map 的数据结构

const 声明的变量值是否可以改动

const 实际上保证的是变量指向的内存地址不能改动,所以对于简单数据类型而言,值就保存在变量指向的内存地址中,因此等同于常量,但是对于引用数据类型来说,变量指向的内存地址保存的只是一个指针,不是具体的值,const 只能保证这个指针是固定的,但是指针指向的数据结构是不是可变的就不是 const 能控制的了,所以我们在声明一个对象为 const 时需要非常小心。

对于前端安全了解哪些?前端常见攻击有哪些

  1. XSS - 跨网站脚本攻击,全称是 Cross Site Scripting
  2. CSRF - 跨站请求伪造(CSRF - Cross Site Request Forgery)
    看这里 - https://github.com/dwqs/blog/issues/68

http1.0 / http2.0 / http / https 的区别

http1.X 版本的缺陷概括来说是:线程阻塞,在同一时间,同一域名的请求有一定的数量限制,超过限制数目的请求会被则塞。

http1.0

缺点:浏览器和服务器只保持短暂的连接,浏览器的每次请求都需要对服务器建立一个 TCP 连接(TCP 连接的成本很高没因为每次新建都需要对服务器三次握手),服务器请求完成后立刻断开 TCP 连接,服务器也不会记录过往的每次请求。

解决方式:在请求的头信息中添加 Connection 字段并设定值为 keep-alive

http1.1 相对于 http1.0 提升了下面这些点:

  • 引入持久连接 : 即 TCP 默认不关闭,可以被多个请求复用,不用声明 keep-alive (对于同一个域名,大多数浏览器允许同时建立 6 个连接)
  • 管道机制 : 同一个 TCP 连接中,客户端可以同时发送多个请求
  • 分块传输编码 : 服务器每产生一块数据,就发送一块,用 流模式 取代 缓存模式
  • 新增请求方式

       PUT:请求服务器存储一个资源

       DELETE:请求服务器删除标识的资源

       OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项和需求

       CONNECT:保留请求以供将来使用

       TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断

但是虽然相对于 http1.0 改进了很多地方, http1.1 还是有些许缺点:

  • 队头拥塞 :虽然允许了 TCP 的多路复用,但是在同一个 TCP 连接中,所有的请求都还是按照次序执行的,服务器只有在一个请求处理完了之后才会接着处理下一个,这导致的问题是如果排在前面的请求很慢,那么后面的请求就会一直处于等待状态,这就是 队头拥塞

    那么如何来解决这个问题呢?我们可以通过 减少请求数 ,和 同时多开持久连接 来解决。

http2.0 特点

  1. 采用二进制格式而非文本格式

    http1.1 的头信息是 ASCII 编码(文本),而数据体可以使二进制也可以是文本,但是 http2.0 无论是头信息还是数据体都是二进制,统称为帧,这是因为二进制解析起来更加的高效,并且紧凑,出错率也更少。

  2. 完全的多路复用,而非 有序拥塞 的,只需要一个连接即可实现并行

    http2.0 复用 TCP 连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,避免了 队头拥塞

  3. 报头压缩,减低开销

    http 协议是没有状态,导致每次请求都必须附上所有信息。所以,请求的很多头字段都是重复的,比如 Cookie ,一样的内容每次请求都必须附带,这会浪费很多带宽,也影响速度,所以 http2.0 对于相同的头部,不必再通过请求发送,只需发送一次。

    并且引入了头信息压缩机制,使用 gzip 或 compress 压缩后再发送

    另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,产生一个索引号,之后就不发送同样字段了,只需发送索引号。

  4. 服务器端推送

    http2.0 允许服务器在未经客户端请求的情况下,向客户端发送资源

    通过推送服务器任务,客户端可以把需要的内容存储在客户端中,避免了往返的延迟。

https 和 http 的区别

  1. https 是加密传输协议,http 是明文传输协议
  2. https 需要用到 ssl 证书,http 不用
  3. https 比 http 更加的安全,对搜索引擎更加友好,利于 seo
  4. https 标准端口 443,http 标准端口 80
  5. https 基于传输层,http 基于应用层

Get 和 Post 的区别

  • get 产生一个 TCP 数据包;post 产生两个 TCP 数据包。
  • 对于 get 请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200;
    而对于 post ,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data ,服务器响应 200 ok。
  • get 请求的参数是明文显示在 url 后的,并且有长度限制,而 post 没有
  • get 请求参数会被完整保留在浏览器历史记录里,而 post 中的参数不会被保留。

js 数组去重

思路一:使用 ES6 的 set

let arr = [1, 1, 5, 3, 2, 5, 0];
return Array.from(new Set(arr));

思路二:使用 Map - 用数组的值做 key,个数做 value,循环数组,如果遇到已有的 key 值就不做任何操作,如果遇到没有的就存下来做 key 。直到循环完,最后只取 map 的 key ,就可以得到去重后的数组。

实现如下:(利用 Object 的属性值唯一)

let arr = [1, 1, 5, 3, 2, 5, 0];
let result = []; // 去重数组
let obj = {}; // 去重对象
for (let i = 0; i < arr.length; i++) {
  if (!obj[arr[i].item]) {
    result.push(arr[i].item);
    obj[arr[i].item] = i + 1;
  }
}

开放题:前端性能优化的方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值