资讯专栏INFORMATION COLUMN

【腾讯面试题】web开发工程师职位

khlbat / 2120人阅读

摘要:介绍以及它的状态码是一个它为客户端提供了在客户端和服务器之间传输数据的功能。的节点绑定事件后如果直接删除,但事件未被删除,这也会造成泄露。回流当元素改变的时候,将会影响文档内容或结构,或元素位置,此过程称为。通过响应头部指定。

JavaScript XMLHttpRequest介绍以及它的readyState状态码

XMLHttpRequest 是一个API, 它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。

readyState属性, 共有以下5种状态

状态 描述
0 UNSENT 未调用 open()方法
1 OPENED open()已被调用, 未调用send()方法
2 HEADERS RECEIVED send()方法已调用, 响应的状态和头部已返回
3 LOADING 加载响应体, responseText中已经获取了部分数据
4 DONE 整个请求过程已经完毕

如何形容js的闭包

需要提到作用域,作用域分全局作用域和局部作用域,外部变量属于全局作用域,函数内部变量属于局部作用域。 函数作用域是定义时确定的。 内部函数可以访问外部函数的变量, 参数, 其它函数声明。 如果这个内部函数允许在包含的这个函数外被调用,就会形成一个闭包。

利用闭包生成一个自增id函数

function createIncId (seed) {
    seed = parseInt(seed) || 0;
   return function () {
        return seed++;
   }
}

var incFn1 = createIncId(100);
var incFn2 = createIncId(10);
incFn1(); // 100
incFn1(); // 101
incFn2(); // 10
incFn2(); // 11
js闭包的内存如何释放

首先,闭包是由于执行函数后返回的对象或函数拥有对外部函数的变量,参数和函数声明具有访问权。因此,在js的回收机制上,是会被标记这些变量,参数,函数声明引用(在定义时确定哪些变量会被添加标记),在定时回收的时候不会考虑将这些占用的内存回收。如果我们将返回的对象或函数设置为null, 那么就失去了对内部变量的控制,就会被回收。

下面是一个简单的例子 在线测试

var createClouse = function () {
    var args = [].slice.call(arguments, 0);
    return {
      // 保存了对 args 的 引用
      getValue: function (index) {
        return args[index] || undefined;
    },
    getIndex: function (val) {
        return args.findIndex(function (arg) {
          return val === arg;
      });
    }
  }
}

var clouse = createClouse({}, [], "", null, undefined, false, 0);

alert(clouse.getIndex(undefined));

// 一旦clouse的引用不存在, 则该对象被标记为回收状态
clouse = null;
JavaScript的内存回收机制

采用 Mark-and-sweep(标记扫描)算法

创建"根"列表, 保存引用的全局变量。 在浏览器中, window 对象总是存在的, window对象下的对象变量总是存在,所以不会被标记回收。

从“根”可到达的一切子节点不会被标记回收。

所有未被标记为活动的内存块都可以被标记,交由垃圾回收器进行回收。

JavaScript什么情况下会出现内存溢出, 如何防范

要了解如何预防内存泄漏,需要了解对象的基本生命周期。对象生命周期, JS为引用类型分配适当的内存, 从分配的开始起垃圾回收器会不断对该对象进行评估,检查是否属于有效的对象。
垃圾回收器定期扫描对象, 会将引用数量为0或将对象唯一引用是循环到对象进行回收。

内存泄露方式1: 闭包

  var theThing = null;
  var replaceThing = function () {
    var originalThing = theThing;
    var unused = function () {
      if (originalThing) {
      
        console.log("hi");
      }
    };
    theThing = {
      longStr: new Array(1000000).join("*"),
      someMethod: function () {
        console.log("some message");
      }
    };
    // 显示标记释放内存
    // originalThing = null;
  };
  setInterval(replaceThing, 1000);

如果一直执行的话,可以在chrome工具栏 memory下给 Heap 拍几张快照,会发现内存会每隔1s钟不断增加

原因在于theThingsomeMethodunused 都为同一个父作用域, unused 引用了originalThingsomeMethodunsued 共享闭包范围. 则对originalThing引用强制保持活动状态防回收.

如果在replaceThing 后面加入 originalThing = null, 则循环后不会使内存增长

内存泄露方式2: 意外的全局变量

function foo () {
    // 意外的绑定在全局 window.bar 变量上
    bar = "global value";
}
foo();

一般来说,尽量少用全局变量. 而多用户函数声明运行创建一个私有的函数作用域. 局部变量会在执行后进行释放. 使用 "use strict" 防止出现隐式定义全局变量的情况

内存泄露方式3: 被遗忘的计时器或回调函数

  var someResource = getData();
  var interval = setInterval(function() {
    var node = document.getElementById("Node");
    if(node) {
      // Do stuff with node and someResource.
      node.innerHTML = JSON.stringify(someResource));
    } else {
      // clearInterval(interval);
    }
  }, 1000);

一旦node节点不存在, someResource则成为了不需要的引用,由于setInterval定时器仍然存在的关系, 则无法回收someResource的数据. 解决办法, 使用clearInterval回收定时器

内存泄露方式4: 脱离 DOM 的引用

  var elements = {
    button: document.getElementById("button"),
    image: document.getElementById("image"),
    text: document.getElementById("text")
  };
  function doStuff() {
    image.src = "http://some.url/image";
    button.click();
    console.log(text.innerHTML);
    // Much more logic
  }
  function removeButton() {
    // The button is a direct child of body.
    document.body.removeChild(document.getElementById("button"));
    // At this point, we still have a reference to #button in the global
    // elements dictionary. In other words, the button element is still in
    // memory and cannot be collected by the GC.
  }

DOM的引用在文档中被删除,但是在js内还有存在被引用, 则也不会产生垃圾回收。
DOM的节点绑定事件后如果直接删除DOM,但事件未被删除,这也会造成泄露。

常见跨域方式有哪些

首先要了解一下同源策略,是浏览器核心,基本的安全功能更。限制了一个源中的文本合伙脚本加载来自其他源的资源.
同源的意思: 同一个协议, 同一个域名, 同一个端口.

跨域方式1: 主域相同两个子域进行跨域. 设置 document.domain

比如: http://m.liylblog.comhttp://www.liylblog.com
设置 http://m.liylblog.com/a.htmlhttp://m.liylblog.com/b.htmldocument.domainliylblog.com

www.html 脚本

var getDomainIframe = (function (domain, src) {
  document.domain = domain;
  var ifr = document.createElement("iframe");
  ifr.src = src;
  ifr.style.display = "none";
  document.body.appendChild(ifr);
  var promise = new Promise (function (resolve, reject) {
    ifr.onload = function () {
      ifr.onload = null;
      resolve(ifr.contentWindow);
    };
  });
  return function () {
    return promise;
  }
})("liylblog.com", "http://m.liylblog.com/public/examples/2017/cros_domain/diff_subdomain/m.html");


function getData (xhr, fn) {
  xhr.open("GET", "http://m.liylblog.com/public/examples/2017/cros_domain/diff_subdomain/m_data.json", true);
  xhr.onreadystatechange = function () {
    if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
      fn && fn(xhr.responseText);
    }
  }
  xhr.send();
}

document.querySelector("#btn").addEventListener("click", function () {
  getDomainIframe().then(function (win) {
    var xhr = new win.XMLHttpRequest();
    getData(xhr, function (data) {
      document.querySelector("#console").innerHTML = data;
    });
  });
}, false);

m.html 脚本

 document.domain = "liylblog.com";

原理:
获取到 m.html 的window对象, 则可以利用这个window对象下的 XMLHttpRequest API对 m.liylblog.com的资源进行ajax请求

在线演示地址

跨域方式2: window.postMessage
HTML5新增的postMessage方法, 可以实现跨文档消息传输, 通过绑定window.addEventListner("message") 事件来监听发送文档消息传输内容。

跨域方式3: proxy 服务端代理
将要请求的地址以参数的方式发送给同域的服务器,由服务器代理请求目标地址

跨域方式4: jsonp 动态插入脚本
利用script脚本动态插入并执行的特性, 将请求地址存放至scriptsrc属性中,当onload加载完毕后执行脚本。

跨域方式5:CORS

跨域资源共享( CORS )机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险。
跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。
规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法, 进行OPTIONS方法 预检查请求(preflight request)

重绘(repaint)与回流(reflow)

重绘
重绘是在一个元素的外观被改变,但没有改变布局的情况下发生的,如改变了visibility、outline、background等。当repaint发生时,浏览器会验证DOM树上所有其他节点的visibility属性。

回流
当元素改变的时候,将会影响文档内容或结构,或元素位置,此过程称为 Reflow。

什么时候会导致回流发生:

改变窗口大小

改变文字大小

添加/删除样式表

内容的改变,(用户在输入框中写入内容也会)

激活伪类,如:hover

操作class属性

脚本操作DOM

计算offsetWidth和offsetHeight

设置style属性

PS: 回流必定引起重绘

setTimeout, setInterval, requestAnimationFrame 区别

setTimeoutsetInterval 主要通过定时任务的方式,执行修改DOM UI的代码, 从而交给UI线程进行处理渲染. 如果前面有了任务队列,则执行完前面的任务队列后再执行动画任务。

requestAnimationFrame 采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

requestAnimationFrame 优点:

requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率

在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量

requestAnimationFrame 是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销

HTTP协议 协议介绍
请求过程:
- 请求行 HTTP版本号
- 请求首部 

响应过程:
- 响应HTTP版本号 响应状态码 响应状态
- 响应首部
- 响应实体
HTTP 1.0

每一个请求打开一个连接,请求结束后会关闭连接. 响应的对象本省可以是任何类型, HTML 文件,文本文件,图片,其它格式内容。 通过响应头部Content-Type 指定。

简单的请求

# telnet website.org 80
> GET /rfc/rfc1945.txt HTTP/1.0
> 两次回车
HTTP 1.1

相比于HTTP1.0, HTTP1.1多了比较多的性能优化。

持久连接

分块编码传输

字节范围请求

增强缓存机制

传输编码请求管道

第一次HTTP请求文档成功后, 还会利用现有的连接发送一次请求获取 favicon.png 网站缩略图标. 如果任意一方想要中止连接,都可以发送 Connection: closed 关闭连接。

HTTP 2.0
协议升级方式

ALPN协议(应用层协商协议)
浏览器在建立TLS连接时,告诉服务器自身支持HTTP1.1HTTP2.0协议. 服务器端得到信息后,也告诉浏览器自身支持HTTP2.0协议。于是将协议转换成HTTP2.0。接下来通过HTTP2.0进行通信。

基于HTTP的协商过程

HTTP Upgrade request
GET / HTTP/1.1
host: nghttp2.org
connection: Upgrade, HTTP2-Settings
upgrade: h2c        /*发起带有HTTP2.0 Upgrade头部的请求*/       
http2-settings: AAMAAABkAAQAAP__   /*客户端SETTINGS净荷*/
user-agent: nghttp2/1.9.0-DEV

HTTP Upgrade response    
HTTP/1.1 101 Switching Protocols   /*服务端同意升级到HTTP 2.0*/
Connection: Upgrade
Upgrade: h2c

HTTP Upgrade success               /*协商完成*/
帧通信
缓存方式

HTTP协议的缓存方式 主要分为强制缓存协商缓存

- Pragma 1.0
- Expires
- Cache-Control
浏览器缓存头部和服务器缓存头部 网络 介绍一下 OSI七层模型和 TCP/IP四层模型

OSI七层模型

协议层 传输方式
物理层 传输二进制比特流
数据链路层 数据帧 (frame)
网络层 数据包 (packet)
传输层 数据段 (segment)
会话层 管理主机之间的会话进程(socket)
表示层 数据的加密、压缩、格式转换
应用层 报文消息(message)

TCP/IP 协议栈

协议层 传输方式
网络接口层 以太网, WIFI
网络互连层 IP, 对应主机IP, 发送数据包
传输层 TCP, UDP ,对应端口,
应用层 HTTP,FTP, DNS
TCP与UDP区别

TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议

面向连接

传输可靠

保准传输顺序

UDP(用户数据报协议)是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。

面向非连接

传输不可靠

速度非常快

HTTP,FTP,TELENET, SSH 属于TCP, ping命令属于 UDP

解释一下TCP的三次握手和四次挥手

Linux 查找端口服务对应的进程

lsof 查找哪些端口占用的进程

sudo lsof -i:80 查找使用80端口的进程

lsof -u www 查找用户www的进程打开的文件

netstat 显示与IP、TCP、UDP和ICMP协议相关的统计数据

netstat -lntp 查看开启了哪些端口

查看内存占用和CPU使用的命令

top 查看CPU显示状况

top -u www 查看用户www的的CPU 内存使用情况

pmap 根据进程查看内存情况

free 可用内存大小

free -m MB为单位

free -g GB为单位

PHP 单例模式 实现远程加载图片资源, 考虑refer的情况 PHP的内存回收机制 算法

常见排序算法

快速排序算法的时间复杂度

如何实现二分排序

引用文章

了解 JavaScript 应用程序中的内存泄漏

HTTP访问控制(CORS)

-------------------------分割线-------------------------
问题的答案会不定期补全
欢迎大家指正,能学到东西就是好的

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/25692.html

相关文章

  • 腾讯面试web开发程师职位

    摘要:介绍以及它的状态码是一个它为客户端提供了在客户端和服务器之间传输数据的功能。的节点绑定事件后如果直接删除,但事件未被删除,这也会造成泄露。回流当元素改变的时候,将会影响文档内容或结构,或元素位置,此过程称为。通过响应头部指定。 JavaScript XMLHttpRequest介绍以及它的readyState状态码 XMLHttpRequest 是一个API, 它为客户端提供了在客户端...

    Object 评论0 收藏0
  • 程序语言

    摘要:一面应该还问了其他内容,但是两次面试多线程面试问题和答案采访中,我们通常会遇到两个主题采集问题和多线程面试问题。多线程是关于并发和线程的。我们正在共享重要的多线程面试问题和答案。。 2016 年末,腾讯,百度,华为,搜狗和滴滴面试题汇总 2016 年未,腾讯,百度,华为,搜狗和滴滴面试题汇总 【码农每日一题】Java 内部类(Part 2)相关面试题 关注一下嘛,又不让你背锅!问:Ja...

    mtunique 评论0 收藏0
  • 程序语言

    摘要:一面应该还问了其他内容,但是两次面试多线程面试问题和答案采访中,我们通常会遇到两个主题采集问题和多线程面试问题。多线程是关于并发和线程的。我们正在共享重要的多线程面试问题和答案。。 2016 年末,腾讯,百度,华为,搜狗和滴滴面试题汇总 2016 年未,腾讯,百度,华为,搜狗和滴滴面试题汇总 【码农每日一题】Java 内部类(Part 2)相关面试题 关注一下嘛,又不让你背锅!问:Ja...

    stefan 评论0 收藏0
  • 技术甜品店 - 收藏集 - 掘金

    摘要:前端切图神器前端掘金安装前端的基础工作就是把设计师的设计稿还原成前端页面,所以切图是作为一个前端的基本技能。 腾讯 Web 工程师的前端书单 - 阅读 - 掘金作者:link 2014年一月以来,自己接触web前端开发已经两年多了,记录一下自己前端学习路上看过的,以及道听途说的一些书,基本上按照由浅入深来介绍。 JavaScript 入门 《JavaScript权威指南(第六版)》 ★...

    Gilbertat 评论0 收藏0

发表评论

0条评论

khlbat

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<