关于前端:美团前端二面必会面试题附答案

111次阅读

共计 7330 个字符,预计需要花费 19 分钟才能阅读完成。

为什么 0.1 + 0.2 != 0.3,请详述理由

因为 JS 采纳 IEEE 754 双精度版本(64 位),并且只有采纳 IEEE 754 的语言都有该问题。

咱们都晓得计算机示意十进制是采纳二进制示意的,所以 0.1 在二进制示意为

// (0011) 示意循环
0.1 = 2^-4 * 1.10011(0011)

那么如何失去这个二进制的呢,咱们能够来演算下

小数算二进制和整数不同。乘法计算时,只计算小数位,整数位用作每一位的二进制,并且失去的第一位为最高位。所以咱们得出 0.1 = 2^-4 * 1.10011(0011),那么 0.2 的演算也根本如上所示,只须要去掉第一步乘法,所以得出 0.2 = 2^-3 * 1.10011(0011)

回来持续说 IEEE 754 双精度。六十四位中符号位占一位,整数位占十一位,其余五十二位都为小数位。因为 0.10.2 都是有限循环的二进制了,所以在小数位开端处须要判断是否进位(就和十进制的四舍五入一样)。

所以 2^-4 * 1.10011...001 进位后就变成了 2^-4 * 1.10011(0011 * 12 次)010。那么把这两个二进制加起来会得出 2^-2 * 1.0011(0011 * 11 次)0100 , 这个值算成十进制就是 0.30000000000000004

上面说一下原生解决办法,如下代码所示

parseFloat((0.1 + 0.2).toFixed(10))

常⽤的 meta 标签有哪些

meta 标签由 namecontent 属性定义,用来形容网页文档的属性 ,比方网页的作者,网页形容,关键词等,除了 HTTP 规范固定了一些name 作为大家应用的共识,开发者还能够自定义 name。

罕用的 meta 标签:
(1)charset,用来形容 HTML 文档的编码类型:

<meta charset="UTF-8" >

(2)keywords,页面关键词:

<meta name="keywords" content="关键词" />

(3)description,页面形容:

<meta name="description" content="页面形容内容" />

(4)refresh,页面重定向和刷新:

<meta http-equiv="refresh" content="0;url=" />

(5)viewport,适配挪动端,能够管制视口的大小和比例:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

其中,content 参数有以下几种:

  • width viewport:宽度(数值 /device-width)
  • height viewport:高度(数值 /device-height)
  • initial-scale:初始缩放比例
  • maximum-scale:最大缩放比例
  • minimum-scale:最小缩放比例
  • user-scalable:是否容许用户缩放(yes/no)

(6)搜索引擎索引形式:

<meta name="robots" content="index,follow" />

其中,content 参数有以下几种:

  • all:文件将被检索,且页面上的链接能够被查问;
  • none:文件将不被检索,且页面上的链接不能够被查问;
  • index:文件将被检索;
  • follow:页面上的链接能够被查问;
  • noindex:文件将不被检索;
  • nofollow:页面上的链接不能够被查问。

说一下 SPA 单页面有什么优缺点?

长处:1. 体验好,不刷新,缩小 申请  数据 ajax 异步获取 页面流程;2. 前后端拆散

3. 加重服务端压力

4. 共用一套后端程序代码,适配多端

毛病:1. 首屏加载过慢;2.SEO 不利于搜索引擎抓取

const 对象的属性能够批改吗

const 保障的并不是变量的值不能改变,而是变量指向的那个内存地址不能改变。对于根本类型的数据(数值、字符串、布尔值),其值就保留在变量指向的那个内存地址,因而等同于常量。

但对于援用类型的数据(次要是对象和数组)来说,变量指向数据的内存地址,保留的只是一个指针,const 只能保障这个指针是固定不变的,至于它指向的数据结构是不是可变的,就齐全不能管制了。

JS 隐式转换,显示转换

个别非根底类型进行转换时会先调用 valueOf,如果 valueOf 无奈返回根本类型值,就会调用 toString

字符串和数字

  • “+” 操作符,如果有一个为字符串,那么都转化到字符串而后执行字符串拼接
  • “-” 操作符,转换为数字,相减 (-a, a * 1 a/1) 都能进行隐式强制类型转换
[] + {} 和 {} + []

布尔值到数字

  • 1 + true = 2
  • 1 + false = 1

转换为布尔值

  • for 中第二个
  • while
  • if
  • 三元表达式
  • ||(逻辑或)&&(逻辑与)右边的操作数

符号

  • 不能被转换为数字
  • 能被转换为布尔值(都是 true)
  • 能够被转换成字符串 “Symbol(cool)”

宽松相等和严格相等

宽松相等容许进行强制类型转换,而严格相等不容许

字符串与数字

转换为数字而后比拟

其余类型与布尔类型

  • 先把布尔类型转换为数字,而后持续进行比拟

对象与非对象

  • 执行对象的 ToPrimitive(对象)而后持续进行比拟

假值列表

  • undefined
  • null
  • false
  • +0, -0, NaN
  • “”

对盒模型的了解

CSS3 中的盒模型有以下两种:规范盒子模型、IE 盒子模型 盒模型都是由四个局部组成的,别离是 margin、border、padding 和 content。

规范盒模型和 IE 盒模型的区别在于设置 width 和 height 时,所对应的范畴不同:

  • 规范盒模型的 width 和 height 属性的范畴只蕴含了 content,
  • IE 盒模型的 width 和 height 属性的范畴蕴含了 border、padding 和 content。

能够通过批改元素的 box-sizing 属性来扭转元素的盒模型:

  • box-sizeing: content-box示意规范盒模型(默认值)
  • box-sizeing: border-box示意 IE 盒模型(怪异盒模型)

如何阻止事件冒泡

  • 一般浏览器应用:event.stopPropagation()
  • IE 浏览器应用:event.cancelBubble = true;

懒加载的概念

懒加载也叫做提早加载、按需加载,指的是在长网页中提早加载图片数据,是一种较好的网页性能优化的形式。在比拟长的网页或利用中,如果图片很多,所有的图片都被加载进去,而用户只能看到可视窗口的那一部分图片数据,这样就节约了性能。

如果应用图片的懒加载就能够解决以上问题。在滚动屏幕之前,可视化区域之外的图片不会进行加载,在滚动屏幕时才加载。这样使得网页的加载速度更快,缩小了服务器的负载。懒加载实用于图片较多,页面列表较长(长列表)的场景中。

常见的 HTTP 申请办法

  • GET: 向服务器获取数据;
  • POST:将实体提交到指定的资源,通常会造成服务器资源的批改;
  • PUT:上传文件,更新数据;
  • DELETE:删除服务器上的对象;
  • HEAD:获取报文首部,与 GET 相比,不返回报文主体局部;
  • OPTIONS:询问反对的申请办法,用来跨域申请;
  • CONNECT:要求在与代理服务器通信时建设隧道,应用隧道进行 TCP 通信;
  • TRACE: 回显服务器收到的申请,次要⽤于测试或诊断。

代码输入后果

Promise.reject('err!!!')
  .then((res) => {console.log('success', res)
  }, (err) => {console.log('error', err)
  }).catch(err => {console.log('catch', err)
  })

输入后果如下:

error err!!!

咱们晓得,.then函数中的两个参数:

  • 第一个参数是用来解决 Promise 胜利的函数
  • 第二个则是解决失败的函数

也就是说 Promise.resolve('1') 的值会进入胜利的函数,Promise.reject('2')的值会进入失败的函数。

在这道题中,谬误间接被 then 的第二个参数捕捉了,所以就不会被 catch 捕捉了,输入后果为:error err!!!'

然而,如果是像上面这样:

Promise.resolve()
  .then(function success (res) {throw new Error('error!!!')
  }, function fail1 (err) {console.log('fail1', err)
  }).catch(function fail2 (err) {console.log('fail2', err)
  })

then 的第一参数中抛出了谬误,那么他就不会被第二个参数不活了,而是被前面的 catch 捕捉到。

行内元素有哪些?块级元素有哪些?空 (void) 元素有那些?

  • 行内元素有:a b span img input select strong
  • 块级元素有:div ul ol li dl dt dd h1 h2 h3 h4 h5 h6 p

空元素,即没有内容的 HTML 元素。空元素是在开始标签中敞开的,也就是空元素没有闭合标签:

  • 常见的有:<br><hr><img><input><link><meta>
  • 鲜见的有:<area><base><col><colgroup><command><embed><keygen><param><source><track><wbr>

代码输入后果

console.log(1)

setTimeout(() => {console.log(2)
})

new Promise(resolve =>  {console.log(3)
  resolve(4)
}).then(d => console.log(d))

setTimeout(() => {console.log(5)
  new Promise(resolve =>  {resolve(6)
  }).then(d => console.log(d))
})

setTimeout(() => {console.log(7)
})

console.log(8)

输入后果如下:

1
3
8
4
2
5
6
7

代码执行过程如下:

  1. 首先执行 script 代码,打印出 1;
  2. 遇到第一个定时器,退出到宏工作队列;
  3. 遇到 Promise,执行代码,打印出 3,遇到 resolve,将其退出到微工作队列;
  4. 遇到第二个定时器,退出到宏工作队列;
  5. 遇到第三个定时器,退出到宏工作队列;
  6. 继续执行 script 代码,打印出 8,第一轮执行完结;
  7. 执行微工作队列,打印出第一个 Promise 的 resolve 后果:4;
  8. 开始执行宏工作队列,执行第一个定时器,打印出 2;
  9. 此时没有微工作,继续执行宏工作中的第二个定时器,首先打印出 5,遇到 Promise,首选打印出 6,遇到 resolve,将其退出到微工作队列;
  10. 执行微工作队列,打印出 6;
  11. 执行宏工作队列中的最初一个定时器,打印出 7。

对 this 对象的了解

this 是执行上下文中的一个属性,它指向最初一次调用这个办法的对象。在理论开发中,this 的指向能够通过四种调用模式来判断。

  • 第一种是 函数调用模式,当一个函数不是一个对象的属性时,间接作为函数来调用时,this 指向全局对象。
  • 第二种是 办法调用模式,如果一个函数作为一个对象的办法来调用时,this 指向这个对象。
  • 第三种是 结构器调用模式,如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象。
  • 第四种是 apply、call 和 bind 调用模式,这三个办法都能够显示的指定调用函数的 this 指向。其中 apply 办法接管两个参数:一个是 this 绑定的对象,一个是参数数组。call 办法接管的参数,第一个是 this 绑定的对象,前面的其余参数是传入函数执行的参数。也就是说,在应用 call() 办法时,传递给函数的参数必须一一列举进去。bind 办法通过传入一个对象,返回一个 this 绑定了传入对象的新函数。这个函数的 this 指向除了应用 new 时会被扭转,其余状况下都不会扭转。

这四种形式,应用结构器调用模式的优先级最高,而后是 apply、call 和 bind 调用模式,而后是办法调用模式,而后是函数调用模式。

什么是 DOM 和 BOM?

  • DOM 指的是文档对象模型,它指的是把文档当做一个对象,这个对象次要定义了解决网页内容的办法和接口。
  • BOM 指的是浏览器对象模型,它指的是把浏览器当做一个对象来看待,这个对象次要定义了与浏览器进行交互的法和接口。BOM 的外围是 window,而 window 对象具备双重角色,它既是通过 js 拜访浏览器窗口的一个接口,又是一个 Global(全局)对象。这意味着在网页中定义的任何对象,变量和函数,都作为全局对象的一个属性或者办法存在。window 对象含有 location 对象、navigator 对象、screen 对象等子对象,并且 DOM 的最基本的对象 document 对象也是 BOM 的 window 对象的子对象。

写代码:实现函数可能深度克隆根本类型

浅克隆:

function shallowClone(obj) {let cloneObj = {};

  for (let i in obj) {cloneObj[i] = obj[i];
  }

  return cloneObj;
}

深克隆:

  • 思考根底类型
  • 援用类型

    • RegExp、Date、函数 不是 JSON 平安的
    • 会失落 constructor,所有的构造函数都指向 Object
    • 破解循环援用
function deepCopy(obj) {if (typeof obj === 'object') {var result = obj.constructor === Array ? [] : {};

    for (var i in obj) {result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];
    }
  } else {var result = obj;}

  return result;
}

Promise.any

形容 :只有 promises 中有一个fulfilled,就返回第一个fulfilledPromise实例的返回值。

实现

Promise.any = function(promises) {return new Promise((resolve, reject) => {if(Array.isArray(promises)) {if(promises.length === 0) return reject(new AggregateError("All promises were rejected"));
            let count = 0;
            promises.forEach((item, index) => {Promise.resolve(item).then(value => resolve(value),
                    reason => {
                        count++;
                        if(count === promises.length) {reject(new AggregateError("All promises were rejected"));
                        };
                    }
                );
            })
        }
        else return reject(new TypeError("Argument is not iterable"));
    });
}

为什么 udp 不会粘包?

  • TCP 协定是⾯向流的协定,UDP 是⾯向音讯的协定。UDP 段都是⼀条音讯,应⽤程序必须以音讯为单位提取数据,不能⼀次提取任意字节的数据
  • UDP 具备爱护音讯边界,在每个 UDP 包中就有了音讯头(消息来源地址,端⼝等信息),这样对于接收端来说就容易进⾏辨别解决了。传输协定把数据当作⼀条独⽴的音讯在⽹上传输,接收端只能接管独⽴的音讯。接收端⼀次只能接管发送端收回的⼀个数据包, 如果⼀次承受数据的⼤⼩⼩于发送端⼀次发送的数据⼤⼩,就会失落⼀局部数据,即便失落,承受端也不会分两次去接管。

== 操作符的强制类型转换规定?

对于 == 来说,如果比照单方的类型 不一样 ,就会进行 类型转换。如果比照 xy 是否雷同,就会进行如下判断流程:

  1. 首先会判断两者类型是否 雷同,雷同的话就比拟两者的大小;
  2. 类型不雷同的话,就会进行类型转换;
  3. 会先判断是否在比照 nullundefined,是的话就会返回 true
  4. 判断两者类型是否为 stringnumber,是的话就会将字符串转换为 number
1 == '1'
      ↓
1 ==  1
  1. 判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断
'1' == true
        ↓
'1' ==  1
        ↓
 1  ==  1
  1. 判断其中一方是否为 object 且另一方为 stringnumber 或者 symbol,是的话就会把 object 转为原始类型再进行判断
'1' == {name: 'js'}        ↓'1' == '[object Object]'

应用 clear 属性革除浮动的原理?

应用 clear 属性革除浮动,其语法如下:

clear:none|left|right|both

如果单看字面意思,clear:left 是“革除左浮动”,clear:right 是“革除右浮动”,实际上,这种解释是有问题的,因为浮动始终还在,并没有革除。

官网对 clear 属性解释:“元素盒子的边不能和后面的浮动元素相邻”,对元素设置 clear 属性是为了防止浮动元素对该元素的影响,而不是革除掉浮动。

还须要留神 clear 属性指的是元素盒子的边不能和后面的浮动元素相邻,留神这里“后面的”3 个字,也就是 clear 属性对“前面的”浮动元素是充耳不闻的。思考到 float 属性要么是 left,要么是 right,不可能同时存在,同时因为 clear 属性对“前面的”浮动元素充耳不闻,因而,当 clear:left 无效的时候,clear:right 必然有效,也就是此时 clear:left 等同于设置 clear:both;同样地,clear:right 如果无效也是等同于设置 clear:both。由此可见,clear:left 和 clear:right 这两个申明就没有任何应用的价值,至多在 CSS 世界中是如此,间接应用 clear:both 吧。

个别应用伪元素的形式革除浮动:

.clear::after{content:'';  display: block;   clear:both;}

clear 属性只有块级元素才无效的,而::after 等伪元素默认都是内联程度,这就是借助伪元素革除浮动影响时须要设置 display 属性值的起因。

正文完
 0