下面XX公司的笔试题,以及我个人的答案和分析,如有理解错误,或者欠缺的地方还望大家指出来,一起学习进步
1 标准CSS盒子模型?与低版本IE盒子模型有什么不同
- 标准:margin-border-padding-content (width = content)
- IE: margin-border-padding-content(width = border+padding+contetn)
2 position有那些值?各相对于什么定位?
position
TBLR:top bottom left right
- static
不脱离标准流,无TBLR属性
- relative
脱离标准流,但是仍占据位置,以父元素content左上角定位,padding会影响TBLR,border不会影响
- absolute
脱离标准流,不占据位置,以第一个非stati的position定位,原点为padding左上角位置,如无position,则以浏览器窗口左上角
- fixed
固定定位,以浏览器左上角为原点
3 不考虑兼容性,如何上下居中一个大小不定的元素(HTML+CSS)
- 定位
top:50%
transform:translatedY(-50%)
- Flex布局
display:flex
align-items:center//单行
align-content:center//多行
4-7程序题
- 4
var a = 10;
function print() {
console.log(a);
var a = 100;
console.log(a);
}
print(); // undefined 100
//变量提升 局部作用域覆盖全局作用域
- 5
var a =1;
function addA(a){//因为这里传入的参数为a,相当于局部声明了var a
a++;//var a = a++
}
addA(a);//函数调用后,局部变量被销毁
console.log(a)//1,调用全局的a
var b = {b:1};
function addB(b){
b.b++;//全局中的b={b:2}
b={};//新建一个对象,这里的b指向堆内存中的一块新的区域
b.b=3;//给其赋值
}
addB(b);//调用
console.log(b.b);/2这里输出的是全局中所指向的那个堆内存中的b.b
- 6
var o = {
a:1,
get:function(){
console.log(this.a)
}
};
o.get();//1 这里的this指向o
var get = o.get;
get();//这里相当于Window.get(),全局中无a属于所以undefined
- 7
var arr = [1,2,3,4,5]
var arr1 = arr.forEach(function(a){
setTimeout(function(){
console.log(a);
},1000);
});
// console.log(arr1)//1,2,3,4,5--因为,setTimeout会将其放入事件队列来执行,遍历的值不会改变
for(var i = 0; i<arr.length;i++){
setTimeout(function(){
console.log(arr[i])//5个undefined ,主线程运行完,再执行异步(即事件队列),此时i=5,arr[5]为undefined
},1000)
}
console.log(i)//5
console.log(i)//5
console.log(i)//5
console.log(i)//5
console.log(i)//5
8 编写一个函数count 每执行一次返回比上一次+1的数,如:1,2,3,4,5(除count外,不可有全局变量)
function count(){
var num = 0;
//运用闭包
return function test(){
num += 1;
console.log(num)
}
}
var obj = new count()//调用count返回一个函数,所以得实例化
obj()//1
obj()//2
obj()//3
obj()//4
#### 9 实现深度拷贝
>```
function deepCopy(data){
if(data instanceof Array){
var newArr = data.concat();
return newArr
}else if(data instanceof Object){
var newObj = {};
for(var key in data){
newObj[key] = typeof data[key] === 'object'?deepCopy(data[key]):data[key];
return newObj;
}
}else{
return newData = data;
}
}
10 New操作符具体干了些什么
- 1、创建了一个新的实例对象,并将this指向他
- 2、实例对象的proto指向他的构造函数的原型,因此继承了构造函数的属性方法等
11 绑定DOM事件有几种方式?各自优缺点?解释事件代理及其好处?
function say(){
console.log('hi')
* 内联式
<button id='btn' onclick="say()">Hello</button>
* 属性式
<button id='btn'>Hello</button>
var btn = document.getElementById('btn')
btn.onclick = say()
* 监听事件(事件代理)
<button id='btn'>Hello</button>
var btn = document.getElementById('btn')
btn.addEventListener('clcik',say,false)
***
###### 优缺点分析
> * 内联式:DOM中绑定两个‘onclick’事件只会执行第一个;
* 属性式:!匿名函数!绑定时只会执行最后一个事件
* 事件监听:可以减少DOM操作(效率低,解析满,内存占用量过高),提高性能
#### 12 解决跨域问题?
> * 服务器添加请求头
* iframe
* window.postMessage
* AJAX解决跨域问题方法
* jsop--动态插入一个《script》
* websocket
* cors
####13 减少页面加载时间
> * AJAX请求时用get代替post(发送两次请求)
* 压缩代码,空格,换行不利于传输
* 减少DOM操作(如事件代理,div代理冗余的table)
* JS脚本执行效率低,文件末尾放置JS文件
* CSS、js文件较大时,从外部引用,因为浏览器本身会对其缓存
* 减少HTTP请求
#### 14 一个页面从输入URL到页面加载显示完成,这个过程都发生了什么?
>此题解析来自知乎: https://zhuanlan.zhihu.com/p/23155051
还有史上最详细解释:http://fex.baidu.com/blog/2014/05/what-happen/
***
#### 简述
* 根据域名找出对应IP地址
* 根据IP地址与服务器建立起socket链接
* 连接好了:浏览器发送请求,服务器响应请求
* 浏览器与服务器断开连接
***
**概念解释**
* **IP 地址**: IP 协议为互联网上的每一个网络和每一台主机分配的一个逻辑地址。IP 地址如同门牌号码,通过 IP 地址才能确定一台主机位置。服务器本质也是一台主机,想要访问某个服务器,必须先知道它的 IP 地址;
* **域名( DN )**:IP 地址由四个数字组成,中间用点号连接,在使用过程中难记忆且易输入错误,所以用我们熟悉的字母和数字组合来代替纯数字的 IP 地址,比如我们只会记住 [www.baidu.com**](http://link.zhihu.com/?target=http%3A//www.baidu.com/)(百度域名) 而不是 220.181.112.244(百度的其中一个 IP 地址);
* **DNS**: 每个域名都对应一个或多个提供相同服务服务器的 IP 地址,只有知道服务器 IP 地址才能建立连接,所以需要通过 DNS 把域名解析成一个 IP 地址。
知道了上面的概念,大概就知道了想要获得服务器的门牌号码,需要先将域名转换成 IP 地址。转换过程如下(以查询 [www.baidu.com**](http://link.zhihu.com/?target=http%3A//www.baidu.com/) 的 IP 地址为例,其中2、3、4步均在上一步未查询成功的情况下进行):
查找过程
浏览器搜索自己的 DNS 缓存(维护一张域名与 IP 地址的对应表);
搜索操作系统中的 DNS 缓存(维护一张域名与 IP 地址的对应表);
搜索操作系统的 hosts 文件( Windows 环境下,维护一张域名与 IP 地址的对应表);
操作系统将域名发送至 LDNS(本地区域名服务器,如果你在学校接入互联网,则 LDNS 服务器就在学校,如果通过电信接入互联网,则 LDNS 服务器就在你当地的电信那里。)LDNS 查询自己的 DNS 缓存(一般查找成功率在 80% 左右),查找成功则返回结果,失败则发起一个迭代 DNS 解析请求;
LDNS 向 Root Name Server (根域名服务器,其虽然没有每个域名的的具体信息,但存储了负责每个域,如 com、net、org等的解析的顶级域名服务器的地址)发起请求,此处,Root Name Server 返回 com 域的顶级域名服务器的地址;
LDNS 向 com 域的顶级域名服务器发起请求,返回 [baidu.com**](http://link.zhihu.com/?target=https%3A//www.baidu.com) 域名服务器地址;
LDNS 向 [baidu.com**](http://link.zhihu.com/?target=https%3A//www.baidu.com) 域名服务器发起请求,得到 [www.baidu.com**](http://link.zhihu.com/?target=http%3A//www.baidu.com/) 的 IP 地址;
LDNS 将得到的 IP 地址返回给操作系统,同时自己也将 IP 地址缓存起来;
操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来;
至此,浏览器已经得到了域名对应的 IP 地址。
***
**补充说明1**
域名与 URL 是两个概念:域名是一台或一组服务器的名称,用来确定服务器在 Internet 上的位置;URL 是统一资源定位符,用来确定某一个文件的具体位置,例如,[zhihu.com](https://www.zhihu.com/) 是 知乎的域名,根据这个域名可以找到知乎的服务器,[zhihu.com/people/CompileYouth](https://www.zhihu.com/people/CompileYouth) 是 URL ,可以根据这个 URL 定位我的知乎主页;
IP 地址与域名不是一一对应的关系:可以把多个提供相同服务的服务器 IP 设置为同一个域名,但在同一时刻一个域名只能解析出一个 IP地址;同时,一个 IP 地址可以绑定多个域名,数量不限;
#####建立连接--三次握手
知道了服务器的 IP 地址,下面便开始与服务器建立连接了。
通俗地讲,通信连接的建立需要经历以下三个过程:
主机向服务器发送一个建立连接的请求(您好,我想认识您);
服务器接到请求后发送同意连接的信号(好的,很高兴认识您);
主机接到同意连接的信号后,再次向服务器发送了确认信号(我也很高兴认识您),自此,主机与服务器两者建立了连接。
**补充说明2**
TCP 协议:三次握手的过程采用 TCP 协议,其可以保证信息传输的可靠性,三次握手过程中,若一方收不到确认信号,协议会要求重新发送信号。
网页请求与显示
当服务器与主机建立了连接之后,下面主机便与服务器进行通信。网页请求是一个单向请求的过程,即是一个主机向服务器请求数据,服务器返回相应的数据的过程。
浏览器根据 URL 内容生成 HTTP 请求,请求中包含请求文件的位置、请求文件的方式等等;
服务器接到请求后,会根据 HTTP 请求中的内容来决定如何获取相应的 HTML 文件;
服务器将得到的 HTML 文件发送给浏览器;
在浏览器还没有完全接收 HTML 文件时便开始渲染、显示网页;
在执行 HTML 中代码时,根据需要,浏览器会继续请求图片、CSS、JavsScript等文件,过程同请求 HTML ;
####断开连接--四次挥手
主机向服务器发送一个断开连接的请求(不早了,我该走了);
服务器接到请求后发送确认收到请求的信号(知道了);
服务器向主机发送断开通知(我也该走了);
主机接到断开通知后断开连接并反馈一个确认信号(嗯,好的),服务器收到确认信号后断开连接;
**补充说明**
为什么服务器在接到断开请求时不立即同意断开:当服务器收到断开连接的请求时,可能仍然有数据未发送完毕,所以服务器先发送确认信号,等所有数据发送完毕后再同意断开。
第四次握手后,主机发送确认信号后并没有立即断开连接,而是等待了 2 个报文传送周期,原因是:如果第四次握手的确认信息丢失,服务器将会重新发送第三次握手的断开连接的信号,而服务器发觉丢包与重新发送的断开连接到达主机的时间正好为 2 个报文传输周期。