# 12 道腾讯前端面试真题及答案整理

# 谈谈你对 dns-prefetch 的理解

DNS 是什么 —— Domain Name System,域名系统,作为域名和 IP 地址互相映射的一个分布式数据库。

# DNS Prefetching

浏览器根据自定义的规则,提前去解析后面可能用到的域名,来加速网站的访问速度。简单来说就是提前解析域名,以免延迟。

# 使用方式

<link rel="dns-prefetch" href="//wq.test.com" />

这个功能有个默认加载条件,所有的 a 标签的 href 都会自动去启用 DNS Prefetching,也就是说,你网页的 a 标签 href 带的域名,是不需要在 head 里面加上 link 手动设置的。但 a 标签的默认启动在 HTTPS 不起作用。

这时要使用 meta 里面 http-equiv 来强制启动功能。

<meta http-equiv="x-dns-prefetch-control" content="on" />

# 总结一下

  1. DNS Prefetching 是提前加载域名解析的,省去了解析时间。a 标签的 href 时可以在 Chrome、Firefox 包括高版本的 IE,但是在 HTTPS 下不起作用,需要 meta 来强制开启功能;
  2. 这是 DNS 的提前解析,不是 css、js 等文件缓存,大家不要混淆两个不同的概念;
  3. 如果直接做了 js 的重定向,或者在服务端做了重定向,没有在 link 中手动设置,是不起作用的;
  4. 这个对淘宝这种网页中大量引用其他域名的资源的网站起的作用明显,如果你的所有资源都在你当前域名下,那基本不起作用。

# get / post 请求参数长度有什么特点

我们经常说 get 请求参数的大小存在限制,而 post 请求的参数大小是无限制的。这是一个错误的说法,实际上 HTTP 协议上从未规定 GET / POST 请求的长度限制是多少。对 GET 请求参数的限制是来自于浏览器或 Web 服务器,浏览器和 Web 服务器限制了 URL 的长度。为了明确这个概念,我们必须再次强调一下几点:

  1. HTTP 协议从未规定 GET 和 POST 请求的长度限制;
  2. GET 的长度限制是因为浏览器和 Web 服务器限制了 URL 的长度;
  3. 不同的浏览器和 Web 服务器限制的最大长度是不一样的;
  4. 要支持 IE,则最大长度为 2084 byte;若只支持 Chrome,则最大长度 8182 byte。

# 前端需要注意哪些 SEO

  1. 合理的 TDK(title、description、keywords):搜索对三项的权重逐个减少。title 强调重点即可,重要关键词不要出现超过 2 次,而且要靠前;不同页面的 title 要有所不同;description 把页面内容高度概括,长度适合,不要过分堆砌关键词,不同页面的 description 有所不同;keywords 列举出重要关键词即可;
  2. 语义化 HTML 代码,符合 W3C 规范:语义化代码让搜索引擎容易理解网页;
  3. 重要内容 HTML 代码放最前面:搜索引擎抓取 HTML 顺序是从上到下,有的搜索引擎对抓取长度有限制,保证重要内容一定会被抓取;
  4. 重要内容不要用 js 输出:爬虫不会执行 js 获取内容;
  5. 少用 iframe(搜索引擎不会抓取 iframe 中的内容);
  6. 非装饰性图片必须加上 alt;
  7. 提高网站速度(网站速度是搜索引擎排序的一个重要指标)。

# 实现一个页面操作不会整页刷新的网站,并且能在浏览器前进、后退时正确响应

参考 react-router,实现思路是 hash 或者是 H5 的 history。

# 如何优化 SPA 应用的首屏加载速度慢的问题

参考性能优化

# Reflect 对象创建目的

  1. 将 Object 对象的一些明显属于语言内部的方法(如:Object.defineProperty ,放到 Reflect对象上);
  2. 修改某些 Object 方法的返回结果,让其变得更合理;
  3. 让 Objecty 操作都变成函数行为;
  4. Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。这就让 Proxy 对象可以方便地调用对应的 Reflect 方法,完成默认行为,作为修改行为的基础。

也就是说,不管 Proxy 怎么修改默认行为,你总可以在 Reflect 上获取默认行为。

# 内部属性[[Class]] 是什么

所有 typeof 返回值为 "object" 的对象(如数组)都包含一个内部属性 [[Class]](我 们可以把它看作一个内部的分类,而非传统的面向对象意义上的类)。这个属性无法直接访问, 一般通过 Object.prototype.toString(..) 来查看。例如:

Object.prototype.toString.call( [1,2,3] );  // "[object Array]" 
Object.prototype.toString.call( /regex-literal/i ); //"[object RegExp]"

多数情况下,对象的内部[[class]]属性和创建该对象的内建原生构造函数相对应,不过也不总是这样。2.基本类型值的[[class]]属性

虽然Null()和Undefined()这样的原生构造函数并不存在,但是内部[[class]]属性仍然是“Null”和“Undefined”。

console.log(Object.prototype.toString.call(null)); //[object Null]

console.log(Object.prototype.toString.call(undefined)); //[object Undefined]

其他基本类型值的情况有所不同:

console.log(Object.prototype.toString.call("abc")); //[object String]

console.log(Object.prototype.toString.call(42));  //[object Number]

console.log(Object.prototype.toString.call(true)); //[object Boolean]

基本类型值被各自的封装对象自动包装,所以他们的内部[[class]]属性分别为“String”,“Number”和“Boolean”。3.封装对象

由于基本类型值没有.length和.toString()这样的属性和方法,需要通过封装对象才能访问,此时Javascript引擎会自动为基本类型值包装一个封装对象。

//封装对象包装

var b = 'abc';
console.log(b.length);
console.log(b.toUpperCase());
// ```js
// 一般不直接使用封装对象(即通过new操作创建基本类型值),优先考虑使用“abc”和“42”这样的基本类型值,而不是new String("abc") 和 new Number(42)。4.拆封

// 如果想要得到封装对象中的基本类型值,可以使用valueOf()函数。 
// ```js
//封装对象的拆封
var s = new String( "abc" );
var n = new Number( 42 );
var b = new Boolean( true );

console.log(s.valueOf());
console.log(n.valueOf());
console.log(b.valueOf());

# 什么是堆?什么是栈?它们之间有什么区别和联系?

堆和栈的概念存在于数据结构中和操作系统内存中。在数据结构中,栈中数据的存取方式为 先进后出 ,而堆是一个优先队列,按优先级来进行排序,优先级可以按照大小来规定,完全二叉树是堆的一种实现方式。在操作系统中,内存被分为栈区和堆区,栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构中的栈。堆区内存一般由程序员分配释放,若程序员不释放,程序结束时可能有垃圾回收机制回收。

# isNaN 和 Number.isNaN 的区别

函数 isNaN 在接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的值都会返回 true,因此非数字传入也会返回 true,会影响 NaN 的判断。

函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字在继续判断是否为 NaN,这种方法对 NaN 的判断更准确。

# 什么情况下会发生布尔值的隐式类型转换

  1. if(...) 条件判断语句;
  2. for(...;...;...) 语句中的条件判断表达式(第二个);
  3. while(...)do...while(...) 循环中的条件判断表达式;
  4. 三目运算中的条件判断表达式;
  5. 逻辑运算符 ||&& 左边的操作数。

# undefined 和 undeclared 的区别

已在作用域中声明但还没有赋值的变量,是 undefined 的。相反,还没有在作用域中声明 过的变量,是 undeclared 的。

对于 undeclared 变量的引用,浏览器会报引用错误,如 ReferenceError: b is not defined 。但是我们可以使用 typeof 的安全防范机制来避免 报错,因为对于 undeclared(或者 not defined )变量,typeof 会返回 "undefined"。

# 如何封装一个 JavaScript 的类型判断函数