【前端】面试题 html/css/js基础知识篇

一、CSS面试题

1、display: none 与 visibility: hidden 的区别。

相同: 它们都能让元素不可见
区别:

  • display:none会让元素完全从渲染树中消失,渲染的时候不占据任何空间;visibility: hidden不会让元素从渲染树消失,渲染树元素继续占据空间,只是内容不可见;
  • display: none是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示;visibility:hidden是继承属性,子孙节点消失由于继承了 hidden,通过设置 visibility: visible可以让子孙节点显示;
  • 修改常规流中元素的 display 通常会造成文档重排,修改 visibility 属性只会造成本元素的重绘;
  • 读屏器不会读取 display: none得元素内容;会读取 visibility: hidden的元素内容。

2、css hack 原理及常用 hack。

原理:利用不同浏览器对 CSS 的支持和解析结果不一样编写针对特定浏览器样式。常见的 hack 有 :1)属性 hack,2)选择器 hack,3)IE 条件注释。
IE 条件注释,适用于[IE5, IE9]常见格式如下:

<!--[if IE 6]>
Special instructions for IE 6 here
<![endif]-->

选择器 hack,不同浏览器对选择器的支持不一样:

/***** Selector Hacks ******/
/* IE6 and below */
* html #uno  { color: red }

/* IE7 */
*:first-child+html #dos { color: red }

/* IE7, FF, Saf, Opera  */
html>body #tres { color: red }

/* IE8, FF, Saf, Opera (Everything but IE 6,7) */
html>/**/body #cuatro { color: red }

/* Opera 9.27 and below, safari 2 */
html:first-child #cinco { color: red }

/* Safari 2-3 */
html[xmlns*=""] body:last-child #seis { color: red }

/* safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:nth-of-type(1) #siete { color: red }

/* safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:first-of-type #ocho {  color: red }

/* saf3+, chrome1+ */
@media screen and (-webkit-min-device-pixel-ratio:0) {
 #diez  { color: red  }
}

/* iPhone / mobile webkit */
@media screen and (max-device-width: 480px) {
 #veintiseis { color: red  }
}

/* Safari 2 - 3.1 */
html[xmlns*=""]:root #trece  { color: red  }

/* Safari 2 - 3.1, Opera 9.25 */
*|html[xmlns*=""] #catorce { color: red  }

/* Everything but IE6-8 */
:root *> #quince { color: red  }

/* IE7 */
*+html #dieciocho {  color: red }

/* Firefox only. 1+ */
#veinticuatro,  x:-moz-any-link  { color: red }

/* Firefox 3.0+ */
#veinticinco,  x:-moz-any-link, x:default  { color: red  }

属性 hack:不同浏览器解析 bug 或方法:

/* IE6 */
#once { _color: blue }

/* IE6, IE7 */
#doce { *color: blue; /* or #color: blue */ }

/* Everything but IE6 */
#diecisiete { color/**/: blue }

/* IE6, IE7, IE8 */
#diecinueve { color: blue\9; }

/* IE7, IE8 */
#veinte { color/*\**/: blue\9; }

/* IE6, IE7 -- acts as an !important */
#veintesiete { color: blue !ie; } /* string after ! can be anything */

3、link 与 @import 的区别。

  • link 是 HTML 方式, @import 是 CSS 方式;
  • link 最大限度支持并行下载,@import 过多嵌套导致串行下载,出现 FOUC;
  • link 可以通过 rel=“alternate stylesheet” 指定候选样式;
  • 浏览器对 link 支持早于@import ,可以使用 @import 对老浏览器隐藏样式;
  • @import 必须在样式规则之前,可以在 css 文件中引用其他文件;
  • 总体来说:link 优于@import。

4、CSS 有哪些继承属性。

  • 关于文字排版的属性如:
    • font
    • word-break
    • letter-spacing
    • text-align
    • text-rendering
    • word-spacing
    • white-space
    • text-indent
    • text-transform
    • text-shadow
  • line-height
  • color
  • visibility
  • cursor

5、display,float,position 的关系。

  • 如果 display 为 none,那么 position 和 float 都不起作用,这种情况下元素不产生框;
  • 否则,如果 position 值为 absolute 或者 fixed,框就是绝对定位的,float 的计算值为 none,display 根据下面的表格进行调整;
  • 否则,如果 float 不是 none,框是浮动的,display 根据下表进行调整;
  • 否则,如果元素是根元素,display 根据下表进行调整;
  • 其他情况下 display 的值为指定值 总结起来:绝对定位、浮动、根元素都需要调整 display。

6、外边距折叠(collapsing margins)

外边距重叠就是 margin-collapse,相邻的两个盒子(可能是兄弟关系也可能是祖先关系)的外边距可以结合成一个单独的外边距。 这种合并外边距的方式被称为折叠,结合而成的外边距称为折叠外边距。
折叠结果遵循下列计算规则:

  • 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值;
  • 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值;
  • 两个外边距一正一负时,折叠结果是两者的相加的和。

7、介绍一下盒模型?有哪几种盒模型?

  • 有两种, IE 盒子模型、W3C 盒子模型;
  • 盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border);
  • 标准(W3C)盒模型:元素宽度 = content + padding + border + margin
  • 怪异(IE)盒模型:元素宽度 = content(content+border+padding)+margin
  • 区 别: IE 的 content 部分把 border 和 padding 计算了进去;
  • 标准浏览器通过设置 css3 的 box-sizing: border-box 属性,触发“怪异模式”解析计算宽高
  • 通过设置 css3 的 box-sizing: content-box属性,触发标准盒模型

8、box-sizing 常用的属性有哪些?分别有什么作用?

box-sizing: content-box; // 默认的标准(W3C)盒模型元素效果
box-sizing: border-box; // 触发怪异(IE)盒模型元素的效果
box-sizing: inherit; // 继承父元素 box-sizing 属性的值

9、CSS 选择器有哪些?

  • id 选择器( # myid)
  • 类选择器(.myclassname)
  • 标签选择器(div, h1, p)
  • 相邻选择器(h1 + p)
  • 子选择器(ul > li)
  • 后代选择器(li a)
  • 通配符选择器( * )
  • 属性选择器(a[rel = “external”])
  • 伪类选择器(a:hover, li:nth-child)

10、CSS3 新增伪类有那些?

  • p:first-of-type 选择属于其父元素的首个 p元素的每个p元素。
  • p:last-of-type 选择属于其父元素的最后 p元素的每个p元素。
  • p:only-of-type 选择属于其父元素唯一的 p元素的每个p元素。
  • p:only-child 选择属于其父元素的唯一子元素的每个 p元素。
  • p:nth-child(2) 选择属于其父元素的第二个子元素的每个p元素。
  • :after 在元素之前添加内容,也可以用来做清除浮动。
  • :before 在元素之后添加内容
  • :enabled 选择器匹配每个已启用的元素(大多用在表单元素上)。
  • :disabled 控制表单控件的禁用状态。
  • :checked 单选框或复选框被选中

11、如何居中 div?如何居中一个浮动元素?如何让绝对定位的 div 居中?

如果需要居中的元素为常规流中 inline 元素,为父元素设置 text-align: center,即可实现。
如果需要居中的元素为常规流中 block 元素,1)为元素设置宽度,2)设置左右 margin 为 auto,3)IE6 下需在父元素上设置 text-align: center,再给子元素恢复需要的值。

<body>
    <div class="content">aaaaaa</div>
</body>
<style>
    body {
        background: #DDD;
        text-align: center; /* 3 */
    }
    .content {
        width: 500px;      /* 1 */
        text-align: left;  /* 3 */
        margin: 0 auto;    /* 2 */
        background: purple;
    }
</style>

如果需要居中的元素为浮动元素,1)为元素设置宽度,2)position: relative,3)浮动方向偏移量(left 或者 right)设置为 50%,4)浮动方向上的 margin 设置为元素宽度一半乘以-1。

<body>
    <div class="content">aaaaaa</div>
</body>
<style>
    body {
        background: #DDD;
    }
    .content {
        width: 500px;         /* 1 */
        float: left;
        position: relative;   /* 2 */
        left: 50%;            /* 3 */
        margin-left: -250px;  /* 4 */
        background-color: purple;
    }
</style>

如果需要居中的元素为绝对定位元素,1)为元素设置宽度,2)偏移量设置为 50%,3)偏移方向外边距设置为元素宽度一半乘以-1。

<body>
    <div class="content">aaaaaa</div>
</body>
<style>
    body {
        background: #DDD;
        position: relative;
    }
    .content {
        width: 800px;
        position: absolute;
        left: 50%;
        margin-left: -400px;
        background-color: purple;
    }
</style>

如果需要居中的元素为绝对定位元素,1)为元素设置宽度,2)设置左右偏移量都为 0,3)设置左右外边距都为 auto。

<body>
    <div class="content">aaaaaa</div>
</body>
<style>
    body {
        background: #DDD;
        position: relative;
    }
    .content {
        width: 800px;
        position: absolute;
        margin: 0 auto;
        left: 0;
        right: 0;
        background-color: purple;
    }
</style>

12、如何竖直居中一个元素?

  • 绝对定位居中;
  • 如果居中的是行内元素,可以设置父级 height 与 line-height 相等;
  • 设置 margin/padding 居中;
  • 相对位置偏移居中;
  • flex 居中,设置 align-items:center 即可。

13、display 有哪些值?说明他们的作用。

  • block 像块级元素一样显示;
  • none 缺省值,像行内元素类型一样显示;
  • inline-block 像行内元素一样显示,但其内容像块级元素一样显示;
  • list-item 像块级元素一样显示,并添加样式列表标记;
  • table 此元素会作为块级表格来显示;
  • inherit 规定应该从父元素继承 display 属性的值。

14、position 有哪些值 ?relative 和 absolute 定位依据是?

  • static 静态定位,默认值,没有定位,元素出现在正常的流中(忽略 top, bottom, left, right - z-index 的应用);
  • relative 生成相对定位的元素,相对于元素的正常位置进行定位;
  • absolute绝对定位,相对于值不为 static 的第一个父元素进行定位,如果没有满足条件的父级元素,则会相对于浏览器窗口来进行定位;
  • fixed 固定定位,相对于浏览器窗口进行定位,(老 IE 不支持),使用固定定位的元素无论如何滚动浏览器窗口,元素位置固定不变 ;
  • sticky粘性定位,滚动页面时它的效果与relative相同,当要滚动到屏幕之外时则自动变成fixed的效果;
  • inherit 规定从父元素继承 position 属性的值。

15、CSS3 有哪些新特性?

  • 新增选择器 p:nth-child(n){color: rgba(255, 0, 0, 0.75)}
  • 弹性盒模型 display: flex;
  • 多列布局 column-count: 5;
  • 媒体查询 @media (max-width: 480px) {.box: {column-count: 1;}}
  • 个性化字体 @font-face{font-family: BorderWeb; src:url(BORDERW0.eot);}
  • 颜色透明度 color: rgba(255, 0, 0, 0.75);
  • 圆角 border-radius: 5px;
  • 渐变 background:linear-gradient(red, green, blue);
  • 阴影 box-shadow:3px 3px 3px rgba(0, 64, 128, 0.3);
  • 倒影 box-reflect: below 2px;
  • 文字装饰 text-stroke-color: red;
  • 文字溢出 text-overflow:ellipsis;
  • 背景效果 background-size: 100px 100px;
  • 边框效果 border-image:url(bt_blue.png) 0 10;
  • 平滑过渡 transition: all .3s ease-in .1s;
  • 动画 @keyframes anim-1 {50% {border-radius: 50%;}} animation: anim-1 1s;
  • 转换
    • 旋转 transform: rotate(20deg);
    • 倾斜 transform: skew(150deg, -10deg);
    • 位移 transform: translate(20px, 20px);
    • 缩放 transform: scale(.5);

16、用纯 CSS 创建一个三角形的原理是什么?

/* 把上、左、右三条边隐藏掉(颜色设为 transparent)*/
#demo {
  width: 0;
  height: 0;
  border-width: 20px;
  border-style: solid;
  border-color: transparent transparent red transparent;
}

17、一个满屏品字布局如何设计?

简单的方式:

  • 上面的 div 宽 100%,
  • 下面的两个 div 分别宽 50%,
  • 然后用 float 或者 inline 使其不换行即可

18、经常遇到的浏览器的兼容性有哪些?原因,解决方法是什么,常用 hack 的技巧 ?

  • png24 位的图片在 iE6 浏览器上出现背景,解决方案是做成 PNG8;
  • 浏览器默认的 margin 和 padding 不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一;
  • IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用 getAttribute()获取自定义属性;
  • Firefox下,只能使用 getAttribute()获取自定义属性。解决方法:统一通过 getAttribute()获取自定义属性;
  • IE下,even 对象有 x,y 属性,但是没有 pageX,pageY属性;
  • Firefox下,event 对象有 pageX,pageY属性,但是没有 x,y 属性。

19、li 与 li 之间有看不见的空白间隔是什么原因引起的(也称幽灵字符)?有什么解决办法?

行框的排列会受到中间空白(回车\空格)等的影响,因为空格也属于字符,这些空白也会被应用样式,占据空间,所以会有间隔,把字符大小设为 0,就没有空格了。

20、display:inline-block 间隙问题怎么解决?

移除空格、使用 margin 负值、使用 font-size:0、letter-spacing、word-spacing。

21、display:inline-block 什么时候会显示间隙?

  • 相邻的 inline-block 元素之间有换行或空格分隔的情况下会产生间距;
  • 非 inline-block 水平元素设置为 inline-block 也会有水平间距;
  • 可以借助 vertical-align:top; 消除垂直间隙;
  • 可以在父级加 font-size:0; 在子元素里设置需要的字体大小,消除垂直间隙;
  • 把 li 标签写到同一行可以消除垂直间隙,但代码可读性差。

22、css 定义的权重。

权重:
1.从0开始,一个行内style属性+1000;
2.一个id选择器+100;
3.一个属性选择器、class或者伪类+10;
4.一个元素选择器,或者伪元素+1,通配符+0。

23、CSS 优先级算法如何计算?

  • 优先级就近原则,同权重情况下样式定义最近者为准;
  • 载入样式以最后载入的为准;
  • 优先级为: !important > id > class > tag important比内联优先级高。

24、谈谈浮动和清除浮动。

浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。由于浮动框不在文档的普通流中,所以文档的普通流的块框表现得就像浮动框不存在一样,浮动的块框会漂浮在文档普通流的块框上。
解决方法:

  1. 父级 div 定义伪类:after 和 zoom (推荐使用,建议定义公共类,以减少 CSS 代码)
   .clearfloat:after{
       display:block;
       clear:both;
       content:"";
       visibility:hidden;
       height:0
   }
   .clearfloat{zoom:1}
  1. 在结尾处添加空 div 标签 clear:both
<div class="parent">
    <div class="left">Left</div>
    <div class="right">Right</div>
    <div class="clearfloat"></div>
</div>
<style>
    .left {float:left}
    .clearfloat{clear:both}
</style>
  1. 父级 div 定义 height;
  2. 父级 div 定义 overflow:auto;
  3. 父级 div 定义 overflow:hidden;
  4. 父级 div 也一起浮动;
  5. 父级 div 定义 display:table;
  6. 结尾处加 br 标签 clear:both。

参考链接几种常用的清除浮动方法

25、请列举几种隐藏元素的方法。

  • visibility: hidden;这个属性只是简单的隐藏某个元素,但是元素占用的空间任然存在;
  • opacity: 0 设置 0 可以使一个元素完全透明;
  • position: absolute设置一个很大的 left 负值定位,使元素定位在可见区域之外;
  • display: none元素会变得不可见,并且不会再占用文档的空间;
  • transform: scale(0)将一个元素设置为缩放无限小,元素将不可见,元素原来所在的位置将被保留;
  • <div hidden=“hidden”> HTML5 属性,效果和 display:none相同,但这个属性用于记录一个元素的状态;
  • height: 0将元素高度设为 0 ,并消除边框;
  • filter: blur(0),将一个元素的模糊度设置为 0,从而使这个元素消失。

26、rgba() 和 opacity 的透明效果有什么不同?

  • opacity 作用于元素以及元素内的所有内容(包括文字)的透明度;
  • rgba() 只作用于元素自身的颜色或其背景色,子元素不会继承透明效果。

27、css 属性 content 有什么作用?

content 属性专门应用在 before/after 伪元素上,用于插入额外内容或样式。

28、请解释一下 CSS3 的 Flexbox(弹性盒布局模型)以及适用场景?

Flexbox 用于不同尺寸屏幕中创建可自动扩展和收缩布局。

29、请写出多种等高布局。

  • 在列的父元素上使用这个背景图进行 Y 轴的铺放,从而实现一种等高列的假像;
  • 模仿表格布局等高列效果:兼容性不好,在 ie6-7 无法正常运行;
  • css3 flexbox 布局: .container{display: flex; align-items: stretch;}。

30、圣杯布局的实现原理?

要求:三列布局;中间主体内容前置,且宽度自适应;两边内容定宽。
好处:重要的内容放在文档流前面可以优先渲染。
原理:利用相对定位、浮动、负边距布局,而不添加额外标签。

  .container {
      padding-left: 150px;
      padding-right: 190px;
  }
  .main {
      float: left;
      width: 100%;
  }
  .left {
      float: left;
      width: 190px;
      margin-left: -100%;
      position: relative;
      left: -150px;
  }
  .right {
      float: left;
      width: 190px;
      margin-left: -190px;
      position: relative;
      right: -190px;
  }

31、什么是双飞翼布局?实现原理?

双飞翼布局:对圣杯布局(使用相对定位,对以后布局有局限性)的改进,消除相对定位布局。
原理:主体元素上设置左右边距,预留两翼位置。左右两栏使用浮动和负边距归位,消除相对定位。

.container {
    /*padding-left:150px;*/
    /*padding-right:190px;*/
}
.main-wrap {
    width: 100%;
    float: left;
}
.main {
    margin-left: 150px;
    margin-right: 190px;
}
.left {
    float: left;
    width: 150px;
    margin-left: -100%;
    /*position: relative;*/
    /*left:-150px;*/
}
.right {
    float: left;
    width: 190px;
    margin-left: -190px;
    /*position:relative;*/
    /*right:-190px;*/
}

32、在 CSS 样式中常使用 px、em 在表现上有什么区别?

  • px 相对于显示器屏幕分辨率,无法用浏览器字体放大功能;
  • em 值并不是固定的,会继承父级的字体大小: em = 像素值 / 父级 font-size。

33、为什么要初始化 CSS 样式?

  • 不同浏览器对有些标签样式的默认值解析不同;
  • 不初始化 CSS 会造成各现浏览器之间的页面显示差异;
  • 可以使用 reset.css 或 Normalize.css 做 CSS 初始化。

34、reset.css 和 Normalize.css 理解。

reset.css 意为重置默认样式。HTML 中绝大部分标签元素在网页显示中都有一个默认属性值,通常为了避免重复定义元素样式,需要进行重置默认样式
Eric Meyer(CSS Reset)推荐

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
    margin: 0;
    padding: 0;
    border: 0;
    outline: 0;
    font-size: 100%;
    vertical-align: baseline;
    background: transparent;
}
body {
    line-height: 1;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}
/* remember to define focus styles! */
:focus {
    outline: 0;
}
/* remember to highlight inserts somehow! */
ins {
    text-decoration: none;
}
del {
    text-decoration: line-through;
}
/* tables still need ‘cellspacing=”0″‘ in the markup */
table {
    border-collapse: collapse;
    border-spacing: 0;
}

Normalize.css 只是一个很小的 css 文件,但它在默认的 HTML 元素样式上提供了跨浏览器的高度一致性。相比于传统的 css reset,Normalize.css 是一种现代的,为 HTML5 准备的优质替代方案。
Normalize.css 是一种 CSS reset 的替代方案。经过@necolas 和@jon neal 花了几百个小时来努力研究不同浏览器的默认样式的差异,这个项目终于变成了现在这样。

我们创造 normalize.css 有下几个目的:

  • 保护有用的浏览器默认样式而不是完全去掉它们;
  • 一般化的样式:为大部分 HTML 元素提供;
  • 修复浏览器自身的 bug 并保证各浏览器的一致性;
  • 优化 CSS 可用性:用一些小技巧;
  • 解释代码:用注释和详细的文档来。

35、什么是 FOUC(Flash of Unstyled Content)? 如何来避免 FOUC?

  • 当使用 @import 导入 CSS 时,会导致某些页面在 IE 出现奇怪的现象: 没有样式的页面内容显示瞬间闪烁,这种现象称为“文档样式短暂失效”,简称为 FOUC;
  • 产生原因:当样式表晚于结构性 html 加载时,加载到此样式表时,页面将停止之前的渲染;
  • 等待此样式表被下载和解析后,再重新渲染页面,期间导致短暂的花屏现象;
  • 解决方法:使用 link 标签将样式表放在文档 head。

36、介绍使用过的 CSS 预处理器?

  • CSS 预处理器基本思想:为 CSS 增加了一些编程的特性(变量、逻辑判断、函数等);
  • 开发者使用这种语言进行进行 Web 页面样式设计,再编译成正常的 CSS 文件使用;
  • 使用 CSS 预处理器,可以使 CSS 更加简洁、适应性更强、可读性更佳,无需考虑兼容性;
  • 最常用的 CSS 预处理器语言包括:Sass(SCSS)和 LESS。

37、CSS 优化、提高性能的方法有哪些?

  • 多个 css 合并,尽量减少 HTTP 请求;
  • 将 css 文件放在页面最上面;
  • 移除空的 css 规则;
  • 避免使用 CSS 表达式;
  • 选择器优化嵌套,尽量避免层级过深;
  • 充分利用 css 继承属性,减少代码量;
  • 抽象提取公共样式,减少代码量;
  • 属性值为 0 时,不加单位(可以减少字节数);
  • 属性值为小于 1 的小数时,省略小数点前面的 0;
  • css 雪碧图。

38、浏览器是怎样解析 CSS 选择器的?

浏览器解析 CSS 选择器的方式是从右到左。

39、在网页中的应该使用奇数还是偶数的字体?

在网页中的应该使用“偶数”字体:

  • 偶数字号相对更容易和 web 设计的其他部分构成比例关系;
  • 使用奇数号字体时文本段落无法对齐;
  • 宋体的中文网页排布中使用最多的就是 12 和 14。

40、margin 和 padding 分别适合什么场景使用?

  • 需要在 border 外侧添加空白,且空白处不需要背景(色)时,使用 margin;
  • 需要在 border 内测添加空白,且空白处需要背景(色)时,使用 padding。

41、抽离样式模块怎么写,说出思路?

CSS 可以拆分成 2 部分:公共 CSS 和 业务 CSS:

  • 网站的配色,字体,交互提取出为公共 CSS。这部分 CSS 命名不应涉及具体的业务;
  • 对于业务 CSS,需要有统一的命名,使用公用的前缀。可以参考面向对象的 CSS。

42、元素竖向的百分比设定是相对于容器的高度吗?

元素竖向的百分比设定是相对于容器的宽度,而不是高度(这句话说的有问题),
正确说法:如果是height的话,是相对于容器高度,如果是padding-height,margin-height则是相对于容器的宽度。

43、全屏滚动的原理是什么? 用到了 CSS 的那些属性?

  • 原理类似图片轮播原理,超出隐藏部分,滚动时显示;
  • 可能用到的 CSS 属性:overflow:hidden; transform:translate(100%, 100%); display:none;。

44、什么是响应式设计?响应式设计的基本原理是什么?如何兼容低版本的 IE?

响应式设计就是网站能够兼容多个终端,而不是为每个终端做一个特定的版本。基本原理是利用 CSS3 媒体查询,为不同尺寸的设备适配不同样式。
对于低版本的 IE,可采用 JS 获取屏幕宽度,然后通过 resize 方法来实现兼容:

$(window).resize(function () {
    screenRespond();
});
screenRespond();
function screenRespond(){
    var screenWidth = $(window).width();
    if(screenWidth <= 1800){
        $("body").attr("class", "w1800");
    }
    if(screenWidth <= 1400){
        $("body").attr("class", "w1400");
    }
    if(screenWidth > 1800){
        $("body").attr("class", "");
    }
}

45、什么是视差滚动效果,如何给每页做不同的动画?

  • 视差滚动是指多层背景以不同的速度移动,形成立体的运动效果,具有非常出色的视觉体验
  • 一般把网页解剖为:背景层、内容层和悬浮层。当滚动鼠标滚轮时,各图层以不同速度移动,形成视差
    实现原理
  • 以 “页面滚动条” 作为 “视差动画进度条”
  • 以 “滚轮刻度” 当作 “动画帧度” 去播放动画的
  • 监听 mousewheel 事件,事件被触发即播放动画,实现“翻页”效果

46、a 标签上四个伪类的执行顺序是怎么样的?

link > visited > hover > active

47、伪元素和伪类的区别和作用?

伪元素:在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。例如:

p::before {content:"第一章:";}
p::after {content:"Hot!";}
p::first-line {background:red;}
p::first-letter {font-size:30px;}

伪类: 将特殊的效果添加到特定选择器上。它是已有元素上添加类别的,不会产生新的元素。例如:

a:hover {color: #FF00FF}
p:first-child {color: red}

48、::before 和 :after 中双冒号和单冒号有什么区别?

  • 在 CSS 中伪类一直用 : 表示,如 :hover, :active 等;
  • 伪元素在 CSS1 中已存在,当时语法是用 : 表示,如 :before 和 :after;
  • 后来在 CSS3 中修订,伪元素用 :: 表示,如 ::before 和 ::after,以此区分伪元素和伪类;
  • 由于低版本 IE 对双冒号不兼容,开发者为了兼容性各浏览器,继续使使用 :after 这种老语法表示伪元素;
  • 综上所述:::before 是 CSS3 中写伪元素的新语法, :after 是 CSS1 中存在的、兼容 IE 的老语法。

49、如何修改 Chrome 记住密码后自动填充表单的黄色背景?

产生原因:由于 Chrome 默认会给自动填充的 input 表单加上 input:-webkit-autofill 私有属性造成的。
解决方案 1:在 form 标签上直接关闭了表单的自动填充:autocomplete=“off”。
解决方案 2:input:-webkit-autofill { background-color: transparent; }。
input [type=search] 搜索框右侧小图标如何美化:

input[type="search"]::-webkit-search-cancel-button{
  -webkit-appearance: none;
  height: 15px;
  width: 15px;
  border-radius: 8px;
  background:url("images/searchicon.png") no-repeat 0 0;
  background-size: 15px 15px;
}

50、网站图片文件,如何点击下载?而非点击预览?

<a href="logo.jpg" download>下载</a> <a href="logo.jpg" download="网站LOGO" >下载</a>

51、iOS safari 如何阻止“橡皮筋效果”?

  $(document).ready(function(){
      var stopScrolling = function(event) {
          event.preventDefault();
      }
      document.addEventListener('touchstart', stopScrolling, false);
      document.addEventListener('touchmove', stopScrolling, false);
  });

52、你对 line-height 是如何理解的?

  • line-height 指一行字的高度,包含了字间距,实际上是下一行基线到上一行基线距离;
  • 如果一个标签没有定义 height 属性,那么其最终表现的高度是由 line-height 决定的;
  • 一个容器没有设置高度,那么撑开容器高度的是 line-height 而不是容器内的文字内容;
  • 把 line-height 值设置为 height 一样大小的值,可以实现单行文字的垂直居中;
  • line-height 和 height 都能撑开一个高度,height 会触发 haslayout,而 line-height 不会。

53、line-height 三种赋值方式有何区别(带单位、纯数字、百分比)?

  • 带单位:px 是固定值,而 em 会参考父元素 font-size 值计算自身的行高;
  • 纯数字:会把比例传递给后代。例如,父级行高为 1.5,子元素字体为 18px,则子元素行高为 1.5 * 18 = 27px;
  • 百分比:将计算后的值传递给后代。

54、设置元素浮动后,该元素的 display 值会如何变化?

设置元素浮动后,该元素的 display 值自动变成 block。

55、怎么让 Chrome 支持小于 12px 的文字?

  .shrink{
    -webkit-transform:scale(0.8);
    -o-transform:scale(1);
    display:inline-block;
  }

56、让页面里的字体变清晰,变细用 CSS 怎么做(IOS 手机浏览器字体齿轮设置)?

  -webkit-font-smoothing: antialiased;

57、font-style 属性 oblique 是什么意思?

font-style: oblique; 使没有 italic 属性的文字实现倾斜。

58、如果需要手动写动画,你认为最小时间间隔是多久?

16.7ms 多数显示器默认频率是 60Hz,即 1 秒刷新 60 次,所以理论上最小间隔: 1s / 60 * 1000 = 16.7ms。

59、overflow: scroll 时不能平滑滚动的问题怎么处理?

监听滚轮事件,然后滚动到一定距离时用 jquery 的 animate 实现平滑效果。

60、一个高度自适应的 div,里面有两个 div,一个高度 100px,希望另一个填满剩下的高度。

方案 1: .sub { height: calc(100%-100px); }
方案 2: .container { position:relative; } .sub { position: absolute; top: 100px; bottom: 0; }
方案 3: .container { display:flex; flex-direction:column; } .sub { flex:1; }

61、CSS 中类 class 和 id 的区别。

对于 CSS 而言,id 和 class 都是选择器,唯一不同的地方在于权重不同。如果只说 CSS,上面那一句话就讲完了。拓展出来,对于 html 而言,id 和 class 都是 dom 元素的属性值。不同的地方在于 id 属性的值是唯一的,而 class 属性值可以重复。id 还一个老特性是锚点功能,当浏览器地址栏有一个#xxx,页面会自动滚动到 id=xxx 的元素上面。
更直接的:id 给 js 用,class 给 css 用(趋势)。

62、如何优化网页的打印样式?

<link rel="stylesheet" type="text/css" media="screen" href="xxx.css" />

其中 media 指定的属性就是设备,显示器上就是 screen,打印机则是 print,电视是 tv,投影仪是 projection。

 <link rel="stylesheet" type="text/css" media="print" href="yyy.css" />

但打印样式表也应有些注意事项:

  • 打印样式表中最好不要用背景图片,因为打印机不能打印 CSS 中的背景。如要显示图片,请使用 html 插入到页面中;
  • 最好不要使用像素作为单位,因为打印样式表要打印出来的会是实物,所以建议使用 pt 和 cm;
  • 隐藏掉不必要的内容@print div{display:none;}
  • 打印样式表中最好少用浮动属性,因为它们会消失。

63、请问为何要使用 transform,而非absolute positioning,或反之的理由?为什么?

  • 使用 transform 或 position 实现动画效果时是有很大差别。
  • 使用 transform 时,可以让 GPU 参与运算,动画的 FPS 更高。
  • 使用 position 时,最小的动画变化的单位是 1px,而使用 transform 参与时,可以做到更小(动画效果更加平滑)
  • 功能都一样。但是 translate 不会引起浏览器的重绘和重排,这就相当 nice 了。

反之:

64、请解释 CSS sprites,以及你要如何在页面或网站中实现它。

  • CSS Sprites 其实就是把网页中一些背景图片整合到一张图片文件中,再利用 CSS 的“background-image”,“background- repeat”,“background-position”的组合进行背景定位,background-position 可以用数字能精确的定位出背景图片的位置。
  • CSS Sprites 为一些大型的网站节约了带宽,让提高了用户的加载速度和用户体验,不需要加载更多的图片。

65、你熟悉 SVG 样式的书写吗?

SVG等效的 CSS
fillbackground-color 或 color
fill-opacitybackground-color 或 color 设置 rgba/hsla
opacityopacity
strokeborder-color
stroke-widthborder-thickness
stroke-opacityborder-color 设置 rgba
rx, ryborder-radius

下面的属性在 SVG 和 CSS 中是一样的,只是在 SVG 的 transformations 和 dimensions 中稍有区别:

  • font-family, font-size, font-style, font-variant 和 font-weight;
  • width 和 height;
  • scale, rotate, skew。
    参考链接: 基本的 SVG 样式属性

65、如果设计中使用了非标准的字体,你该如何去实现?

二、html面试题

1、Doctype 作用?标准模式与兼容模式各有什么区别?

  • 声明位于HTML文档中的第一行,处于 html 标签之前。告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现;
  • 标准模式的排版 和 JS 运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。

2、HTML5 为什么只需要写 <!DOCTYPE HTML>

  • HTML5 不基于 SGML,因此不需要对 DTD 进行引用,但是需要 doctype 来规范浏览器的行为(让浏览器按照它们应该的方式来运行);
  • 而 HTML4.01 基于 SGML,所以需要对 DTD 进行引用,才能告知浏览器文档所使用的文档类型。

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

定义:CSS 规范规定,每个元素都有 display 属性,确定该元素的类型,每个元素都有默认的 display 值,如 div 的 display 默认值为“block”,则为“块级”元素;span 默认 display 属性值为“inline”,是“行内”元素。

  • 行内元素有:a b span img input select strong(强调的语气)
  • 块级元素有:div ul ol li dl dt dd h1 h2 h3 h4…p
  • 空元素:
    • 常见: br hr img input link meta
    • 不常见: area base col command embed keygen param source track wbr

不同浏览器(版本)、HTML4(5)、CSS2 等实际略有差异
参考: http://stackoverflow.com/questions/6867254/browsers-default-css-for-html-elements

4、页面导入样式时,使用 link 和@import 有什么区别?

  • link 属于 XHTML 标签,除了加载 CSS 外,还能用于定义 RSS, 定义 rel 连接属性等作用;而@import 是 CSS 提供的,只能用于加载 CSS;
  • 页面被加载的时,link 会同时被加载,而@import 引用的 CSS 会等到页面被加载完再加载;
  • import 是 CSS2.1 提出的,只在 IE5 以上才能被识别,而 link 是 XHTML 标签,无兼容问题;
  • link 支持使用 js 控制 DOM 去改变样式,而@import 不支持。

5、介绍一下你对浏览器内核的理解?

主要分成两部分:渲染引擎(layout engineer 或 Rendering Engine)和 JS 引擎。
渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。
JS 引擎则:解析和执行 javascript 来实现网页的动态效果。
最开始渲染引擎和 JS 引擎并没有区分的很明确,后来 JS 引擎越来越独立,内核就倾向于只指渲染引擎。

6、常见的浏览器内核有哪些?

  • Trident 内核:IE,MaxThon,TT,The World,360,搜狗浏览器等。[又称 MSHTML]
  • Gecko 内核:Netscape6 及以上版本,FF,MozillaSuite/SeaMonkey 等
  • Presto 内核:Opera7 及以上。 [Opera 内核原为:Presto,现为:Blink;]
  • Webkit 内核:Safari,Chrome 等。 [ Chrome 的:Blink(WebKit 的分支)]
    详细文章:浏览器内核的解析和对比

7、html5 有哪些新特性、移除了那些元素?如何处理 HTML5 新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?

  • HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加:
    • 绘画 canvas
    • 用于媒介回放的 video 和 audio 元素
    • 本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失
    • sessionStorage 的数据在浏览器关闭后自动删除
    • 语意化更好的内容元素,比如 article、footer、header、nav、section
    • 表单控件,calendar、date、time、email、url、search
    • 新的技术 webworker, websocket, Geolocation
  • 移除的元素:
    • 纯表现的元素:basefont,big,center,font, s,strike,tt,u;
    • 对可用性产生负面影响的元素:frame,frameset,noframes;
  • 支持 HTML5 新标签:
    • IE8/IE7/IE6 支持通过 document.createElement 方法产生的标签,
    • 可以利用这一特性让这些浏览器支持 HTML5 新标签,
    • 浏览器支持新标签后,还需要添加标签默认的样式。
    • 当然也可以直接使用成熟的框架、比如 html5shim;
      <!--[if lt IE 9]>
          <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
      <![endif]-->
      
  • 如何区分 HTML5: DOCTYPE 声明、新增的结构元素、功能元素:
    - 新增的结构元素:
    (1)section
    表示页面中的一个内容区块,比如章节,页眉,页脚或页面中的其他部分。它可以与h1,h2,h3,h4,h5,h6等元素结合起来使用,标示文档结构。
    (2)article
    表示页面中的一块与上下文不相关的独立内容,譬如博客中的一篇文章或报纸中的一篇文章。
    (3)aside
    表示article元素的内容之外的,与article元素的内容相关的辅助信息。
    (4)header
    表示页面中一个内容区块或整个页面的标题。
    (5)hgroup
    用于对整个页面或页面中一个内容区块的标题进行组合。
    (6)footer
    表示整个页面或页面中一个内容区块的脚注。一般来说,它会包含创作者的姓名,创作日期以及创作者联系信息。
    (7)nav
    表示页面中导航链接的部分。
    (8)figure
    表示一段独立的流内容,一般表示文档主体流内容的一个独立单元。使用figcaption元素为figure元素组添加标题。
    
    - 新增的功能元素:
    hgroup元素:用于对整个页面或页面中一个内容区块的标题进行组合。
    figure元素:表示一段独立的流内容,一般表示文档主题流内容中的一个独立单元。
    video元素:定义视频,比如电影片段或其他视频流。
    audio元素:定义音频,比如音乐或其他音频流。
    embed元素:用来插入各种多媒体,格式可以是MIDI、WAV、AIFF、AU、MP3等。
    mark元素:主要用来在视觉上向用户呈现需要突出显示或高亮显示的文字。
    time元素:表示日期或时间,也可以同时表示两者。
    canvas元素:表示图形,如图表和其他图像。
    output元素:表示不同类型的输出,比如脚本的输出。
    source元素:为媒介元素定义媒介资源。
    menu元素:表示菜单列表。当希望列出表单控制时使用该标签。
    ruby元素:表示ruby注释。
    rt元素:表示字符的解释或发音。
    rp元素:在ruby解释中使用,以定义不支持ruby元素的浏览器所显示的内容。
    wbr元素:表示软换行。
    command元素:表示命令按钮,如单选按钮、复选框或按钮。
    details元素:表示用户要求得到并且可以得到的细节信息,可与summary 元素配合使用。
    datalist元素:可选数据的列表,与input元素配合使用,可以制作出输入值的下拉列表。
    datagrid元素:表示可选数据的列表,它以树形列表的形式来显示。
    keygen元素:表示生成密钥。
    progress元素:表示运行中的进程,可以使用progress来显示JavaScript中耗费时间的函数的进程。
    email:表示必须输入E-mail地址的文本输入框。
    url:表示必须输入URL地址的文本输入框。
    number:表示必须输入数值的文本输入框。
    range:表示必须输入一定范围内数字值的文本输入框。
    Date Pickers:HTML5拥有多个可供选取日期和时间的新型输入文本框。
    

8、简述一下你对 HTML 语义化的理解?

  • 用正确的标签做正确的事情。
  • html 语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;
  • 即使在没有样式 CSS 情况下也以一种文档格式显示,并且是容易阅读的;
  • 搜索引擎的爬虫也依赖于 HTML 标记来确定上下文和各个关键字的权重,利于 SEO;
  • 使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。

9、HTML5 的离线储存怎么使用,工作原理能不能解释一下?

在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件。
原理:HTML5 的离线存储是基于一个新建的.appcache 文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像 cookie 一样被存储了下来。之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示。
如何使用:

  1. 页面头部像下面一样加入一个 manifest 的属性;
  2. 在 cache.manifest 文件的编写离线存储的资源:
CACHE MANIFEST
#v1.0

CACHE:
js/app.js
css/style.css

NETWORK:
assets/logo.png

FALLBACK:
/html5/ /404.html
  1. 在离线状态时,操作 window.applicationCache 进行需求实现。
    参考链接:HTML5 离线缓存-manifest 简介

10、浏览器是怎么对 HTML5 的离线储存资源进行管理和加载的呢?

  • 在线的情况下,浏览器发现 html 头部有 manifest 属性,它会请求 manifest 文件,如果是第一次访问 app,那么浏览器就会根据 manifest 文件的内容下载相应的资源并且进行离线存储。如果已经访问过 app 并且资源已经离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的 manifest 文件与旧的 manifest 文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,那么就会重新下载文件中的资源并进行离线存储。
  • 离线的情况下,浏览器就直接使用离线存储的资源。

11、请描述一下 cookies,sessionStorage 和 localStorage 的区别?

  • cookie 是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
  • cookie 数据始终在同源的 http 请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
  • sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存。
  • 存储大小:
    • cookie 数据大小不能超过 4k。
    • sessionStorage 和 localStorage 虽然也有存储大小的限制,但比 cookie 大得多,可以达到 5M 或更大。
  • 有效期(生命周期):
    • localStorage: 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
    • sessionStorage: 数据在当前浏览器窗口关闭后自动删除。
    • cookie: 设置的 cookie 过期时间之前一直有效,即使窗口或浏览器关闭。

12、iframe 有那些缺点?

  • iframe 会阻塞主页面的 Onload 事件;
  • 搜索引擎的检索程序无法解读这种页面,不利于 SEO;
  • iframe 和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。

使用 iframe 之前需要考虑这两个缺点。如果需要使用 iframe,最好是通过 javascript
动态给 iframe 添加 src 属性值,这样可以绕开以上两个问题。

13、Label 的作用是什么?是怎么用的?

label 标签来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。

  <label for="Name">Number:</label>
  <input type=“text“name="Name" id="Name"/>
  <label>Date:<input type="text" name="B"/></label>

14、HTML5 的 form 如何关闭自动完成功能?

给不想要提示的 form 或某个 input 设置为 autocomplete=off。

15、如何实现浏览器内多个标签页之间的通信 (阿里)?

  • WebSocket、SharedWorker;
  • 也可以调用 localstorge、cookies 等本地存储方式;

localstorge 另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件,
我们通过监听事件,控制它的值来进行页面信息通信,
注意 quirks:Safari 在无痕模式下设置 localstorge 值时会抛出 QuotaExceededError 的异常。

16、webSocket 如何兼容低浏览器(阿里)?

Adobe Flash Socket 、ActiveX HTMLFile (IE) 、 基于 multipart 编码发送 XHR 、基于长轮询的 XHR。

17、页面可见性(Page Visibility API) 可以有哪些用途?

  • 通过 visibilityState 的值检测页面当前是否可见,以及打开网页的时间等;
  • 在页面被切换到其他后台进程的时候,自动暂停音乐或视频的播放。

18、如何在页面上实现一个圆形的可点击区域?

  • map+area 或者 svg
  • border-radius
  • 纯 js 实现 需要求一个点在不在圆上简单算法、获取鼠标坐标等等

19、实现不使用 border 画出 1px 高的线,在不同浏览器的标准模式与怪异模式下都能保持一致的效果。

 <div style="height:1px;overflow:hidden;background:red"></div>

20、网页验证码是干嘛的,是为了解决什么安全问题?

  • 区分用户是计算机还是人的公共全自动程序。可以防止恶意破解密码、刷票、论坛灌水;
  • 有效防止黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。

21、title 与 h1 的区别、b 与 strong 的区别、i 与 em 的区别?

  • title 属性没有明确意义只表示是个标题,H1 则表示层次明确的标题,对页面信息的抓取也有很大的影响;
  • strong 是标明重点内容,有语气加强的含义,使用阅读设备阅读网络时:strong 会重读,而 b 是展示强调内容。
  • i 内容展示为斜体,em 表示强调的文本;

Physical Style Elements – 自然样式标签
b, i, u, s, pre
Semantic Style Elements – 语义样式标签
strong, em, ins, del, code
应该准确使用语义样式标签, 但不能滥用, 如果不能确定时首选使用自然样式标签。

22、html 中 title 属性和 alt 属性的区别?

<img src="#" alt="alt信息" />

当图片不输出信息的时候,会显示 alt 信息 鼠标放上去没有信息,当图片正常读取,不会出现 alt 信息。

<img src="#" alt="alt信息" title="title信息" />

当图片不输出信息的时候,会显示 alt 信息 鼠标放上去会出现 title 信息;
当图片正常输出的时候,不会出现 alt 信息,鼠标放上去会出现 title 信息。

23、另外有关 title 属性的知识。

  • title 属性可以用在除了 base,basefont,head,html,meta,param,script 和 title 之外的所有标签。
  • title 属性的功能是提示。额外的说明信息和非本质的信息请使用 title 属性。title 属性值可以比 alt 属性值设置的更长。
  • title 属性有一个很好的用途,即为链接添加描述性文字,特别是当连接本身并不是十分清楚的表达了链接的目的。

三、Javascript面试题

1、JavaScript 的组成。

JavaScript 由以下三部分组成:

  • ECMAScript(核心):JavaScript 语言基础;
  • DOM(文档对象模型):规定了访问 HTML 和 XML 的接口;
  • BOM(浏览器对象模型):提供了浏览器窗口之间进行交互的对象和方法。

2、JS 的基本数据类型和引用数据类型。

  • 基本数据类型:undefined、null、boolean、number、string、symbol;
  • 引用数据类型:object、array、function。

3、检测浏览器版本版本有哪些方式?

  • 根据 navigator.userAgent // UA.toLowerCase().indexOf(‘chrome’);
  • 根据 window 对象的成员 // ‘ActiveXObject’ in window。

4、介绍 JS 有哪些内置对象?

  • 数据封装类对象:Object、Array、Boolean、Number、String;
  • 其他对象:Function、Arguments、Math、Date、RegExp、Error;
  • ES6 新增对象:Symbol、Map、Set、Promises、Proxy、Reflect。

5、说几条写 JavaScript 的基本规范?

  • 代码缩进,建议使用“四个空格”缩进;
  • 代码段使用花括号{}包裹;
  • 语句结束使用分号;
  • 变量和函数在使用前进行声明;
  • 以大写字母开头命名构造函数,全大写命名常量;
  • 规范定义 JSON 对象,补全双引号;
  • 用{}和[]声明对象和数组。

6、如何编写高性能的 JavaScript?

  • 遵循严格模式:“use strict”;
  • 将 js 脚本放在页面底部,加快渲染页面;
  • 将 js 脚本将脚本成组打包,减少请求;
  • 使用非阻塞方式下载 js 脚本;
  • 尽量使用局部变量来保存全局变量;
  • 尽量减少使用闭包;
  • 使用 window 对象属性方法时,省略 window;
  • 尽量减少对象成员嵌套;
  • 缓存 DOM 节点的访问;
  • 通过避免使用 eval() 和 Function() 构造器;
  • 给 setTimeout() 和 setInterval() 传递函数而不是字符串作为参数;
  • 尽量使用直接量创建对象和数组;
  • 最小化重绘(repaint)和回流(reflow)。

7、DOM 元素 e 的 e.getAttribute(propName)和 e.propName 有什么区别和联系。

  • e.getAttribute(),是标准 DOM 操作文档元素属性的方法,具有通用性可在任意文档上使用,返回元素在源文件中设置的属性;
  • e.propName 通常是在 HTML 文档中访问特定元素的特性,浏览器解析元素后生成对应对象(如 a 标签生成 HTMLAnchorElement),这些对象的特性会根据特定规则结合属性设置得到,对于没有对应特性的属性,只能使用 getAttribute 进行访问;
  • e.getAttribute()返回值是源文件中设置的值,类型是字符串或者 null(有的实现返回"");
  • e.propName 返回值可能是字符串、布尔值、对象、undefined 等;
  • 大部分 attribute 与 property 是一一对应关系,修改其中一个会影响另一个,如 id,title 等属性;
  • 一些布尔属性<input hidden/>的检测设置需要 hasAttribute 和 removeAttribute 来完成,或者设置对应 property;
  • <a href="../index.html">link</a>中 href 属性,转换成 property 的时候需要通过转换得到完整 URL;
  • 一些 attribute 和 property 不是一一对应如:form 控件中<input value="hello"/>对应的是 defaultValue,修改或设置 value property 修改的是控件当前值,setAttribute 修改 value 属性不会改变 value property。

8、offsetWidth/offsetHeight,clientWidth/clientHeight 与 scrollWidth/scrollHeight 的区别。

  • offsetWidth/offsetHeight 返回值包含 content + padding + border,效果与 e.getBoundingClientRect()相同;
  • clientWidth/clientHeight 返回值只包含 content + padding,如果有滚动条,也不包含滚动条;
  • scrollWidth/scrollHeight 返回值包含 content + padding + 溢出内容的尺寸。

9、描述浏览器的渲染过程,DOM 树和渲染树的区别?

浏览器的渲染过程:

  • 解析 HTML 构建 DOM(DOM 树),并行请求 css/image/js;
  • CSS 文件下载完成,开始构建 CSSOM(CSS 树);
  • CSSOM 构建结束后,和 DOM 一起生成 Render Tree(渲染树);
  • 布局(Layout):计算出每个节点在屏幕中的位置;
  • 显示(Painting):通过显卡把页面画到屏幕上。

DOM 树 和 渲染树 的区别:

  • DOM 树与 HTML 标签一一对应,包括 head 和隐藏元素;
  • 渲染树不包括 head 和隐藏元素,大段文本的每一个行都是独立节点,每一个节点都有对应的 css 属性。

10、重绘和回流(重排)的区别和关系?

  • 重绘:当渲染树中的元素外观(如:颜色)发生改变,不影响布局时,产生重绘;
  • 回流:当渲染树中的元素的布局(如:尺寸、位置、隐藏/状态状态)发生改变时,产生重绘回流;
  • 注意:JS 获取 Layout 属性值(如:offsetLeft、scrollTop、getComputedStyle 等)也会引起回流。因为浏览器需要通过回流计算最新值;
  • 回流必将引起重绘,而重绘不一定会引起回流。

11、如何最小化重绘(repaint)和回流(reflow)?

  • 需要要对元素进行复杂的操作时,可以先隐藏(display:“none”),操作完成后再显示;
  • 需要创建多个 DOM 节点时,使用 DocumentFragment 创建完后一次性的加入 document;
  • 缓存 Layout 属性值,如:var left = elem.offsetLeft; 这样,多次使用 left 只产生一次回流;
  • 尽量避免用 table 布局(table 元素一旦触发回流就会导致 table 里所有的其它元素回流);
  • 避免使用 css 表达式(expression),因为每次调用都会重新计算值(包括加载页面);
  • 尽量使用 css 属性简写,如:用 border 代替 border-width, border-style, border-color;
    批量修改元素样式:elem.className 和 elem.style.cssText 代替 elem.style.xxx。

12、script 的位置是否会影响首屏显示时间?

  • 在解析 HTML 生成 DOM 过程中,js 文件的下载是并行的,不需要 DOM 处理到 script 节点。因此,script 的位置不影响首屏显示的开始时间;
  • 浏览器解析 HTML 是自上而下的线性过程,script 作为 HTML 的一部分同样遵循这个原则;
  • 因此,script 会延迟 DomContentLoad,只显示其上部分首屏内容,从而影响首屏显示的完成时间。

13、解释 JavaScript 中的作用域与变量声明提升?

JavaScript 作用域:

  • 在 Java、C 等语言中,作用域为 for 语句、if 语句或{}内的一块区域,称为作用域;
  • 而在 JavaScript 中,作用域为 function(){}内的区域,称为函数作用域。

JavaScript 变量声明提升:

  • 在 JavaScript 中,函数声明与变量声明经常被 JavaScript 引擎隐式地提升到当前作用域的顶部;
  • 声明语句中的赋值部分并不会被提升,只有名称被提升;
  • 函数声明的优先级高于变量,如果变量名跟函数名相同且未赋值,则函数声明会覆盖变量声明;
  • 如果函数有多个同名参数,那么最后一个参数(即使没有定义)会覆盖前面的同名参数。

14、介绍 JavaScript 的原型,原型链?有什么特点?

原型:

  • JavaScript 的所有对象中都包含了一个 [proto] 内部属性,这个属性所对应的就是该对象的原型;
  • JavaScript 的函数对象,除了原型 [proto] 之外,还预置了 prototype 属性;
  • 当函数对象作为构造函数创建实例时,该 prototype 属性值将被作为实例对象的原型 [proto]。

原型链:

  • 当一个对象调用的属性/方法自身不存在时,就会去自己 [proto] 关联的前辈 prototype 对象上去找;
  • 如果没找到,就会去该 prototype 原型 [proto] 关联的前辈 prototype 去找。依次类推,直到找到属性/方法或 undefined 为止。从而形成了所谓的“原型链”。

原型特点:

  • JavaScript 对象是通过引用来传递的,当修改原型时,与之相关的对象也会继承这一改变。

15、JavaScript 有几种类型的值?你能画一下他们的内存图吗?

  • 原始数据类型(Undefined,Null,Boolean,Number、String)-- 栈;
  • 引用数据类型(对象、数组和函数)-- 堆;
  • 两种类型的区别是:存储位置不同;
  • 原始数据类型是直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据;
  • 引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;
  • 引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。
  • 当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

16、JavaScript 如何实现一个类,怎么实例化这个类?

  1. 构造函数法(this + prototype) – 用 new 关键字 生成实例对象
    • 缺点:用到了 this 和 prototype,编写复杂,可读性差
  function Mobile(name, price){
     this.name = name;
     this.price = price;
   }
   Mobile.prototype.sell = function(){
      alert(this.name + ",售价 $" + this.price);
   }
   var iPhone7 = new Mobile("iPhone7", 1000);
   iPhone7.sell();
  1. Object.create 法 – 用 Object.create() 生成实例对象
    • 缺点:不能实现私有属性和私有方法,实例对象之间也不能共享数据
 var Person = {
     firstname: "Mark",
     lastname: "Yun",
     age: 25,
     introduce: function(){
         alert('I am ' + Person.firstname + ' ' + Person.lastname);
     }
 };

 var person = Object.create(Person);
 person.introduce();
 // Object.create 要求 IE9+,低版本浏览器可以自行部署:
 if (!Object.create) {
    Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
  };
 }
  1. 极简主义法(消除 this 和 prototype) – 调用 createNew() 得到实例对象
    • 优点:容易理解,结构清晰优雅,符合传统的"面向对象编程"的构造
 var Cat = {
   age: 3, // 共享数据 -- 定义在类对象内,createNew() 外
   createNew: function () {
     var cat = {};
     // var cat = Animal.createNew(); // 继承 Animal 类
     cat.name = "小咪";
     var sound = "喵喵喵"; // 私有属性--定义在 createNew() 内,输出对象外
     cat.makeSound = function () {
       alert(sound);  // 暴露私有属性
     };
     cat.changeAge = function(num){
       Cat.age = num; // 修改共享数据
     };
     return cat; // 输出对象
   }
 };

 var cat = Cat.createNew();
 cat.makeSound();
  1. ES6 语法糖 class – 用 new 关键字 生成实例对象
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
var point = new Point(2, 3);

17、Javascript 如何实现继承?

  1. 构造函数绑定:使用 call 或 apply 方法,将父对象的构造函数绑定在子对象上
function Cat(name,color){
  Animal.apply(this, arguments);
  this.name = name;
  this.color = color;
}
  1. 实例继承:将子对象的 prototype 指向父对象的一个实例
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
  1. 拷贝继承:如果把父对象的所有属性和方法,拷贝进子对象
function extend(Child, Parent) {
   var p = Parent.prototype;
   var c = Child.prototype;
   for (var i in p) {
      c[i] = p[i];
   }
   c.uber = p;
}
  1. 原型继承:将子对象的 prototype 指向父对象的 prototype
function extend(Child, Parent) {
    var F = function(){};
     F.prototype = Parent.prototype;
     Child.prototype = new F();
     Child.prototype.constructor = Child;
     Child.uber = Parent.prototype;
}
  1. ES6 语法糖 extends:class ColorPoint extends Point {}
class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x, y); // 调用父类的constructor(x, y)
        this.color = color;
    }
    toString() {
        return this.color + ' ' + super.toString(); // 调用父类的toString()
    }
}

18、js 继承方式及其优缺点。

原型链继承的缺点

  • 一是字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。

借用构造函数(类式继承)

  • 借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起。所以我们需要原型链+借用构造函数的模式,这种模式称为组合继承。

组合式继承

  • 组合式继承是比较常用的一种继承方法,其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又保证每个实例都有它自己的属性。

19、javascript 创建对象的几种方式?

javascript 创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用 JSON;但写法有很多种,也能混合使用

  1. 对象字面量的方式
person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};
  1. 用 function 来模拟无参的构造函数
 function Person(){}
    var person=new Person();//定义一个function,如果使用new"实例化",该function可以看作是一个Class
        person.name="Mark";
        person.age="25";
        person.work=function(){
        alert(person.name+" hello...");
    }
person.work();
  1. 用 function 来模拟参构造函数来实现(用 this 关键字定义构造的上下文属性)
function Pet(name,age,hobby){
    this.name=name;//this作用域:当前对象
    this.age=age;
    this.hobby=hobby;
    this.eat=function(){
        alert("我叫"+this.name+",我喜欢"+this.hobby+",是个程序员");
    }
}
var maidou =new Pet("麦兜",25,"coding");//实例化、创建对象
maidou.eat();//调用eat方法
  1. 用工厂方式来创建(内置对象)
var wcDog =new Object();
     wcDog.name="旺财";
     wcDog.age=3;
wcDog.work=function(){
    alert("我是"+wcDog.name+",汪汪汪......");
}
wcDog.work();
  1. 用原型方式来创建
function Dog(){

}
Dog.prototype.name="旺财";
Dog.prototype.eat=function(){
    alert(this.name+"是个吃货");
}
var wangcai =new Dog();
wangcai.eat();
  1. 用混合方式来创建
function Car(name,price){
    this.name=name;
    this.price=price;
}
Car.prototype.sell=function(){
	alert("我是"+this.name+",我现在卖"+this.price+"万元");
}
var camry =new Car("凯美瑞",27);
camry.sell();

20、Javascript 作用链域?

  • 全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节;
  • 如果当前作用域没有找到属性或方法,会向上层作用域查找,直至全局函数,这种形式就是作用域链。

21、谈谈 this 对象的理解。

  • this 总是指向函数的直接调用者;
  • 如果有 new 关键字,this 指向 new 出来的实例对象;
  • 在事件中,this 指向触发这个事件的对象;
  • IE 下 attachEvent 中的 this 总是指向全局对象 Window。

22、eval 是做什么的?

eval 的功能是把对应的字符串解析成 JS 代码并运行:

  • 应该避免使用 eval,不安全,非常耗性能(先解析成 js 语句,再执行);
  • 由 JSON 字符串转换为 JSON 对象的时候可以用 eval(‘(’+ str +‘)’)。

23、什么是 Window 对象? 什么是 Document 对象?

  • Window 对象表示当前浏览器的窗口,是 JavaScript 的顶级对象。
  • 我们创建的所有对象、函数、变量都是 Window 对象的成员。
  • Window 对象的方法和属性是在全局范围内有效的。
  • Document 对象是 HTML 文档的根节点与所有其他节点(元素节点,文本节点,属性节点, 注释节点)。
  • Document 对象使我们可以通过脚本对 HTML 页面中的所有元素进行访问。
  • Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问。

24、介绍 DOM 的发展。

  • DOM:文档对象模型(Document Object Model),定义了访问 HTML 和 XML 文档的标准,与编程语言及平台无关
  • DOM0:提供了查询和操作 Web 文档的内容 API。未形成标准,实现混乱。如:document.forms[‘login’]
  • DOM1:W3C 提出标准化的 DOM,简化了对文档中任意部分的访问和操作。如:JavaScript 中的 Document 对象
  • DOM2:原来 DOM 基础上扩充了鼠标事件等细分模块,增加了对 CSS 的支持。如:getComputedStyle(elem, pseudo)
  • DOM3:增加了 XPath 模块和加载与保存(Load and Save)模块。如:XPathEvaluator

25、介绍 DOM0,DOM2,DOM3 事件处理方式区别。

DOM0 级事件处理方式:

  • btn.onclick = func;
  • btn.onclick = null;

DOM2 级事件处理方式:

  • btn.addEventListener(‘click’, func, false);
  • btn.removeEventListener(‘click’, func, false);
  • btn.attachEvent(“onclick”, func);
  • btn.detachEvent(“onclick”, func);

DOM3 级事件处理方式:

  • eventUtil.addListener(input, “textInput”, func);
  • eventUtil 是自定义对象,textInput 是 DOM3 级事件

26、事件的三个阶段。

捕获、目标、冒泡

27、介绍事件“捕获”和“冒泡”执行顺序和事件的执行次数?

按照 W3C 标准的事件:首是进入捕获阶段,直到达到目标元素,再进入冒泡阶段。
事件执行次数(DOM2-addEventListener):元素上绑定事件的个数。

  • 注意 1:前提是事件被确实触发;
  • 注意 2:事件绑定几次就算几个事件,即使类型和功能完全一样也不会“覆盖”。

事件执行顺序:判断的关键是否目标元素

  • 非目标元素:根据 W3C 的标准执行:捕获->目标元素->冒泡(不依据事件绑定顺序);
  • 目标元素:依据事件绑定顺序:先绑定的事件先执行(不依据捕获冒泡标准);
  • 最终顺序:父元素捕获->目标元素事件 1->目标元素事件 2->子元素捕获->子元素冒泡->父元素冒泡;
  • 注意:子元素事件执行前提 事件确实“落”到子元素布局区域上,而不是简单的具有嵌套关系。

28、在一个 DOM 上同时绑定两个点击事件:一个用捕获,一个用冒泡。事件会执行几次,先执行冒泡还是捕获?

  • 该 DOM 上的事件如果被触发,会执行两次(执行次数等于绑定次数);
  • 如果该 DOM 是目标元素,则按事件绑定顺序执行,不区分冒泡/捕获;
  • 如果该 DOM 是处于事件流中的非目标元素,则先执行捕获,后执行冒泡。

29、事件的代理/委托。

事件委托是指将事件绑定目标元素的到父元素上,利用冒泡机制触发该事件
优点:

  • 可以减少事件注册,节省大量内存占用
  • 可以将事件应用于动态添加的子元素上

缺点: 使用不当会造成事件在不应该触发时触发
示例:

ulEl.addEventListener('click', function(e){
    var target = event.target || event.srcElement;
    if(!!target && target.nodeName.toUpperCase() === "LI"){
        console.log(target.innerHTML);
    }
}, false);

30、IE 与火狐的事件机制有什么区别? 如何阻止冒泡?

IE 只事件冒泡,不支持事件捕获;火狐同时支持件冒泡和事件捕获。
阻止冒泡:

  • 取消默认操作: w3c 的方法是 e.preventDefault(),IE 则是使用 e.returnValue = false;
  • return false javascript 的 return false 只会阻止默认行为,而是用 jQuery 的话则既阻止默认行为又防止对象冒泡。
  • 阻止冒泡 w3c 的方法是 e.stopPropagation(),IE 则是使用 e.cancelBubble = true
[js] view plaincopy
function stopHandler(event)
    window.event?window.event.cancelBubble=true:event.stopPropagation();
}

参考链接:浅谈 javascript 事件取消和阻止冒泡-开源中国 2015

31、IE 的事件处理和 W3C 的事件处理有哪些区别(必考)?

绑定事件

  • W3C: targetEl.addEventListener(‘click’, handler, false);
  • IE: targetEl.attachEvent(‘onclick’, handler);

删除事件

  • W3C: targetEl.removeEventListener(‘click’, handler, false);
  • IE: targetEl.detachEvent(event, handler);

事件对象

  • W3C: var e = arguments.callee.caller.arguments[0]
  • IE: window.event

事件目标

  • W3C: e.target
  • IE: window.event.srcElement

阻止事件默认行为

  • W3C: e.preventDefault()
  • IE: window.event.returnValue = false’

阻止事件传播

  • W3C: e.stopPropagation()
  • IE: window.event.cancelBubble = true

32、W3C 事件的 target 与 currentTarget 的区别?

  • target 只会出现在事件流的目标阶段;
  • currentTarget 可能出现在事件流的任何阶段;
  • 当事件流处在目标阶段时,二者的指向相同;
  • 当事件流处于捕获或冒泡阶段时:currentTarget 指向当前事件活动的对象(一般为父级)。

33、如何派发事件(dispatchEvent)?(如何进行事件广播?)

  • W3C: 使用 dispatchEvent 方法
  • IE: 使用 fireEvent 方法
var fireEvent = function(element, event){
    if (document.createEventObject){
        var mockEvent = document.createEventObject();
        return element.fireEvent('on' + event, mockEvent)
    }else{
        var mockEvent = document.createEvent('HTMLEvents');
        mockEvent.initEvent(event, true, true);
        return !element.dispatchEvent(mockEvent);
    }
}

34、什么是函数节流?介绍一下应用场景和原理?

  • 函数节流(throttle)是指阻止一个函数在很短时间间隔内连续调用。 只有当上一次函数执行后达到规定的时间间隔,才能进行下一次调用。 但要保证一个累计最小调用间隔(否则拖拽类的节流都将无连续效果)
  • 函数节流用于 onresize, onscroll 等短时间内会多次触发的事件
  • 函数节流的原理:使用定时器做时间节流。 当触发一个事件时,先用 setTimout 让这个事件延迟一小段时间再执行。 如果在这个时间间隔内又触发了事件,就 clearTimeout 原来的定时器, 再 setTimeout 一个新的定时器重复以上流程。
    函数节流简单实现:
function throttle(method, context) {
     clearTimeout(methor.tId);
     method.tId = setTimeout(function(){
         method.call(context);
     }100); // 两次调用至少间隔 100ms
}
// 调用
window.onresize = function(){
    throttle(myFunc, window);
}

35、区分什么是“客户区坐标”、“页面坐标”、“屏幕坐标”?

  • 客户区坐标:鼠标指针在可视区中的水平坐标(clientX)和垂直坐标(clientY),相对于浏览器的左上定点为原点。
  • 页面坐标:鼠标指针在页面布局中的水平坐标(pageX)和垂直坐标(pageY),相对于Document对象即文档窗口的左上顶点为坐标原点。
  • 屏幕坐标:设备物理屏幕的水平坐标(screenX)和垂直坐标(screenY)。

36、如何获得一个 DOM 元素的绝对位置?

  • elem.offsetLeft:返回元素相对于其定位父级左侧的距离;
  • elem.offsetTop:返回元素相对于其定位父级顶部的距离;
  • elem.getBoundingClientRect():返回一个 DOMRect 对象,包含一组描述边框的只读属性,单位像素。

37、分析 [‘1’, ‘2’, ‘3’].map(parseInt) 答案是多少?(常考)

答案:[1, NaN, NaN]
parseInt(string, radix) 第 2 个参数 radix 表示进制。省略 radix 或 radix = 0,则数字将以十进制解析。
map 每次为 parseInt 传 3 个参数(elem, index, array),其中 index 为数组索引。
因此,map 遍历 [“1”, “2”, “3”],相应 parseInt 接收参数如下:

parseInt('1', 0);  // 1
parseInt('2', 1);  // NaN
parseInt('3', 2);  // NaN

所以,parseInt 参数 radix 不合法,导致返回值为 NaN。

38、new 操作符具体干了什么?

  • 创建实例对象,this 变量引用该对象,同时还继承了构造函数的原型;
  • 属性和方法被加入到 this 引用的对象中;
  • 新创建的对象由 this 所引用,并且最后隐式的返回 this。

39、用原生 JavaScript 的实现过什么功能吗?

封装选择器、调用第三方 API、设置和获取样式(自由回答)。

40、解释一下这段代码的意思吗?

  [].forEach.call($$("*"), function(el){
      el.style.outline = "1px solid #" + (~~(Math.random()*(1<<24))).toString(16);
  })

解释:获取页面所有的元素,遍历这些元素,为它们添加 1 像素随机颜色的轮廓(outline)

`$$(sel) // $$`函数被许多现代浏览器命令行支持,等价于 document.querySelectorAll(sel)
[].forEach.call(NodeLists) // 使用 call 函数将数组遍历函数 forEach 应到节点元素列表
el.style.outline = "1px solid #333" // 样式 outline 位于盒模型之外,不影响元素布局位置
(1<<24) // parseInt("ffffff", 16) == 16777215 == 2^24 - 1 // 1<<24 == 2^24 == 16777216
Math.random()\*(1<<24) // 表示一个位于 0 到 16777216 之间的随机浮点数
~~Math.random()\*(1<<24) // ~~ 作用相当于 parseInt 取整
(~~(Math.random()\*(1<<24))).toString(16) // 转换为一个十六进制-

41、同步和异步的区别?

  • 同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作
  • 异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容

42、JavaScript 实现异步编程的方法?

  • 回调函数
  • 事件监听
  • 发布/订阅
  • Promises 对象
  • Async 函数[ES7]

43、js 延迟加载的方式有哪些?

defer 和 async、动态创建 DOM 方式(用得最多)、按需异步载入 js

44、defer 和 async

defer 并行加载 js 文件,会按照页面上 script 标签的顺序执行 async 并行加载 js 文件,下载完成立即执行,不会按照页面上 script 标签的顺序执行

45、web 开发中会话跟踪的方法有哪些?

  • cookie
  • session
  • url 重写
  • 隐藏 input
  • ip 地址

46、异步加载 JS 的方式有哪些?

  • 设置<script>属性 async=“async” (一旦脚本可用,则会异步执行)
  • 动态创建 script DOM:document.createElement(‘script’);
  • XmlHttpRequest 脚本注入
  • 异步加载库 LABjs
  • 模块加载器 Sea.js

47、什么是闭包(closure),为什么要用它?

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域。
闭包的特性:

  • 函数内再嵌套函数
  • 内部函数可以引用外层的参数和变量
  • 参数和变量不会被垃圾回收机制回收

48、javascript 代码中的"use strict;"是什么意思 ? 使用它区别是什么?

use strict 是一种 ECMAscript 5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行,使 JS 编码更加规范化的模式,消除 Javascript 语法的一些不合理、不严谨之处,减少一些怪异行为。

49、如何判断一个对象是否属于某个类?

// 使用instanceof (待完善)
   if(a instanceof Person){
       alert('yes');
   }

50、Ajax 是什么? 如何创建一个 Ajax?

ajax 的全称:Asynchronous Javascript And XML
异步传输+js+xml
所谓异步,在这里简单地解释就是:向服务器发送请求的时候,我们不必等待结果,而是可以同时做其他的事情,等到有了结果它自己会根据设定进行后续操作,与此同时,页面是不会发生整页刷新的,提高了用户体验

  • 创建 XMLHttpRequest 对象,也就是创建一个异步调用对象
  • 建一个新的 HTTP 请求,并指定该 HTTP 请求的方法、URL 及验证信息
  • 设置响应 HTTP 请求状态变化的函数
  • 发送 HTTP 请求
  • 获取异步调用返回的数据
  • 用 JavaScript 和 DOM 实现局部刷新

51、documen.write 和 innerHTML 的区别。

  • document.write 只能重绘整个页面
  • innerHTML 可以重绘页面的一部分

52、DOM 操作——怎样添加、移除、移动、复制、创建和查找节点?

创建新节点:

createDocumentFragment() //创建一个 DOM 片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点

添加、移除、替换、插入:

appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点

查找:

getElementsByTagName() //通过标签名称
getElementsByName() // 通过元素的 Name 属性的值(IE 容错能力较强,会得到一个数组,其中包括 id 等于 name 值的)
getElementById() //通过元素 Id,唯一性

53、那些操作会造成内存泄漏?

  • 内存泄漏指任何对象在您不再拥有或需要它之后仍然存在;
  • 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收;
  • setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏;
  • 闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)。

54、渐进增强和优雅降级。

  • 渐进增强 :针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
  • 优雅降级 :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

55、Javascript 垃圾回收方法。

标记清除(mark and sweep)

  • 这是 JavaScript 最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。
  • 垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了。
    引用计数(reference counting)
  • 在低版本 IE 中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加 1,如果该变量的值变成了另外一个,则这个值得引用次数减 1,当这个值的引用次数变为 0 的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为 0 的值占用的空间。
    参考链接 内存管理-MDN

56、用过哪些设计模式?

  1. 工厂模式:
  • 主要好处就是可以消除对象间的耦合,通过使用工程方法而不是 new 关键字。将所有实例化的代码集中在一个位置防止代码重复
  • 工厂模式解决了重复实例化的问题 ,但还有一个问题,那就是识别问题,因为根本无法 搞清楚他们到底是哪个对象的实例
function createObject(name,age,profession){
    //集中实例化的函数
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.profession = profession;
    obj.move = function () {
        return this.name + ' at ' + this.age + ' engaged in ' + this.profession;
    };
    return obj;
}
var test1 = createObject('trigkit4',22,'programmer');//第一个实例var test2 = createObject('mike',25,'engineer');//第二个实例
  1. 构造函数模式
  • 使用构造函数的方法 ,即解决了重复实例化的问题 ,又解决了对象识别的问题,该模式与工厂模式的不同之处在于
  • 构造函数方法没有显示的创建对象 (new Object());
  • 直接将属性和方法赋值给 this 对象;
  • 没有 renturn 语句。

57、说说你对闭包的理解。

使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在 js 中,函数即闭包,只有函数才会产生作用域的概念。
闭包有三个特性:

  • 函数嵌套函数
  • 函数内部可以引用外部的参数和变量
  • 参数和变量不会被垃圾回收机制回收

58、请解释一下 JavaScript 的同源策略。

  • 概念:同源策略是客户端脚本(尤其是 Javascript)的重要的安全度量标准。它最早出自 Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议
  • 指一段脚本只能读取来自同一来源的窗口和文档的属性

59、为什么要有同源限制?

我们举例说明:比如一个黑客程序,他利用 Iframe 把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过 Javascript 读取到你的表单中 input 中的内容,这样用户名,密码就轻松到手了。]
缺点: 现在网站的 JS 都会进行压缩,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge 后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节。

60、实现一个函数 clone,可以对 JavaScript 中的 5 种主要的数据类型(包括 Number、String、Object、Array、Boolean)进行值复制(常考)。

function deepClone(obj) {
    if (!isObject(obj)) {
        throw new Error('obj 不是一个对象!')
    }
    let isArray = Array.isArray(obj)
    let cloneObj = isArray ? [] : {}
    for (let key in obj) {
        cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    }
    return cloneObj
}

注意:for…in 法不支持拷贝 func、date、reg 和 err。

// 代理法
function deepClone(obj) {
    if (!isObject(obj)) {
        throw new Error('obj 不是一个对象!')
    }
    let isArray = Array.isArray(obj)
    let cloneObj = isArray ? [...obj] : { ...obj }
    Reflect.ownKeys(cloneObj).forEach(key => {
        cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    })
    return cloneObj
}

61、说说严格模式的限制。

  • 严格模式主要有以下限制:
  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用 with 语句
  • 不能对只读属性赋值,否则报错
  • 不能使用前缀 0 表示八进制数,否则报错
  • 不能删除不可删除的属性,否则报错
  • 不能删除变量 delete prop,会报错,只能删除属性 delete global[prop]
  • eval 不会在它的外层作用域引入变量
  • eval 和 arguments 不能被重新赋值
  • arguments 不会自动反映函数参数的变化
  • 不能使用 arguments.callee
  • 不能使用 arguments.caller
  • 禁止 this 指向全局对象
  • 不能使用 fn.caller 和 fn.arguments 获取函数调用的堆栈
  • 增加了保留字(比如 protected、static 和 interface)

62、如何删除一个 cookie。

将时间设为当前时间往前一点

var date = new Date();
date.setDate(date.getDate() - 1);//真正的删除

setDate()方法用于设置一个月的某一天
expires 的设置

  document.cookie = 'user='+ encodeURIComponent('name')  + ';expires = ' + new Date(0)

63、编写一个方法,求一个字符串的字节长度。

假设:一个英文字符占用一个字节,一个中文字符占用两个字节

function GetBytes(str){
        var len = str.length;
        var bytes = len;

        for(var i=0; i<len; i++){
            if (str.charCodeAt(i) > 255) bytes++;
        }

        return bytes;
    }
alert(GetBytes("你好,as"));

64、请解释什么是事件代理。

事件代理(Event Delegation),又称之为事件委托。是 JavaScript 中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是 DOM 元素的事件冒泡。使用事件代理的好处是可以提高性能。

65、attribute 和 property 的区别是什么?

  • attribute 是 dom 元素在文档中作为 html 标签拥有的属性;
  • property 就是 dom 元素在 js 中作为对象拥有的属性。
  • 对于 html 的标准属性来说,attribute 和 property 是同步的,是会自动更新的
  • 但是对于自定义的属性来说,他们是不同步的

66、页面编码和被请求的资源编码如果不一致如何处理?

  • 后端响应头设置 charset
  • 前端页面<meta>设置 charset

67、把 <script> 放在 </body> 之前和之后有什么区别?浏览器会如何解析它们?

按照 HTML 标准,在结束后出现<script>或任何元素的开始标签,都是解析错误;
虽然不符合 HTML 标准,但浏览器会自动容错,使实际效果与写在</body>之前没有区别;
浏览器的容错机制会忽略<script>之前的,视作<script>仍在 body 体内。省略</body></html>闭合标签符合 HTML 标准,服务器可以利用这一标准。

68、把 <script> 放在 </head> 中会有什么问题?

在浏览器渲染页面之前,它需要通过解析HTML标记然后构建DOM树。在这个过程中,如果解析器遇到了一个脚本(script),它就会停下来,并且执行这个脚本,然后才会继续解析HTML。如果遇到了一个引用外部资源的脚本(script),它就必须停下来等待这个脚本资源的下载,而这个行为会导致一个或者多个的网络往返,并且会延迟页面的首次渲染时间。
还有一点是需要我们注意的,那就是外部引入的脚本(script)会阻塞浏览器的并行下载,HTTP/1.1规范表明,浏览器在每个主机下并行下载的组件不超过两个(也就是说,浏览器一次只能够同时从同一个服务器加载两个脚本);如果你网站的图片是通过多个服务器提供的,那么按道理来说,你的网站可以一次并行下载多张图片。但是,当我们网站在加载脚本的时候;浏览器不会再启动任何其它的下载,即使这些组件来自不同的服务器。

69、JavaScript 中,调用函数有哪几种方式?

  • 方法调用模式 Foo.foo(arg1, arg2);
  • 函数调用模式 foo(arg1, arg2);
  • 构造器调用模式 (new Foo())(arg1, arg2);
  • call/applay 调用模式 Foo.foo.call(that, arg1, arg2);
  • bind 调用模式 Foo.foo.bind(that)(arg1, arg2)();

70、简单实现 Function.bind 函数?

  if (!Function.prototype.bind) {
    Function.prototype.bind = function(that) {
      var func = this, args = arguments;
      return function() {
        return func.apply(that, Array.prototype.slice.call(args, 1));
      }
    }
  }
  // 只支持 bind 阶段的默认参数:
  func.bind(that, arg1, arg2)();

  // 不支持以下调用阶段传入的参数:
  func.bind(that)(arg1, arg2);

71、列举一下 JavaScript 数组和对象有哪些原生方法。

  • 数组:
    • arr.concat(arr1, arr2, arrn);
    • arr.join(“,”);
    • arr.sort(func);
    • arr.pop();
    • arr.push(e1, e2, en);
    • arr.shift();
    • unshift(e1, e2, en);
    • arr.reverse();
    • arr.slice(start, end);
    • arr.splice(index, count, e1, e2, en);
    • arr.indexOf(el);
    • arr.includes(el); // ES6
  • 对象:
    • object.hasOwnProperty(prop);
    • object.propertyIsEnumerable(prop);
    • object.valueOf();
    • object.toString();
    • object.toLocaleString();
    • Class.prototype.isPropertyOf(object);

72、Array.slice() 与 Array.splice() 的区别?

  • slice – “读取”数组指定的元素,不会对原数组进行修改
    • 语法:arr.slice(start, end)
    • start 指定选取开始位置(含)
    • end 指定选取结束位置(不含)
  • splice
    • “操作”数组指定的元素,会修改原数组,返回被删除的元素
    • 语法:arr.splice(index, count, [insert Elements])
    • index 是操作的起始位置
    • count = 0 插入元素,count > 0 删除元素
    • [insert Elements] 向数组新插入的元素

73、JavaScript 对象生命周期的理解?

  • 当创建一个对象时,JavaScript 会自动为该对象分配适当的内存
  • 垃圾回收器定期扫描对象,并计算引用了该对象的其他对象的数量
  • 如果被引用数量为 0,或惟一引用是循环的,那么该对象的内存即可回收

74、哪些操作会造成内存泄漏?

  • JavaScript 内存泄露指对象在不需要使用它时仍然存在,导致占用的内存不能使用或回收
  • 未使用 var 声明的全局变量
  • 闭包函数(Closures)
  • 循环引用(两个对象相互引用)
  • 控制台日志(console.log)
  • 移除存在绑定事件的 DOM 元素(IE)

75、在 javascript 中,1 与 Number(1)有什么区别 [易混淆]。

var a = Number(1) // 1
var b = new Number(1)  // Number {[[PrimitiveValue]]: 1}
typeof (a) // number
typeof (b) // object
a == b // true
  • var a = 1 是一个常量,而 Number(1)是一个函数
  • new Number(1)返回的是一个对象
  • a==b 为 true 是因为所以在求值过程中,总是会强制转为原始数据类型而非对象,例如下面的代码:
typeof 123 // "number"
typeof new Number(123) // "object"
123 instanceof Number // false
(new Number(123)) instanceof Number // true
123 === new Number(123) // false

参考地址:面试题:在 javascript 中,1 与 Number(1)有什么区别

76、console.log(!!(new Boolean(false))输出什么 [易混淆]。

true,布尔的包装对象 Boolean 的对象实例,对象只有在 null 与 undefined 时,才会认定为布尔的 false 值,布尔包装对象本身是个对象,对象->布尔 都是 true,所以 new Boolean(false)其实是布尔的 true,看下面这段代码:

if(new Boolean(false)){
    alert('true!!');
}

只有使用了 valueOf 后才是真正的转换布尔值,与上面包装对象与原始资料转换说明的相同:

!!(new Boolean(false))  //true
(new Boolean(false)).valueOf() //false

77、为什么 JS 是单线程,而不是多线程 [常考]。

  • 单线程是指 JavaScript 在执行的时候,有且只有一个主线程来处理所有的任务。
  • 目的是为了实现与浏览器交互。
  • 我们设想一下,如果 JavaScript 是多线程的,现在我们在浏览器中同时操作一个 DOM,一个线程要求浏览器在这个 DOM 中添加节点,而另一个线程却要求浏览器删掉这个 DOM 节点,那这个时候浏览器就会很郁闷,他不知道应该以哪个线程为准。所以为了避免此类现象的发生,降低复杂度,JavaScript 选择只用一个主线程来执行代码,以此来保证程序执行的一致性。

78、浏览器中的 Event Loop。

  • 主线程运行的时候会生成堆(heap)和栈(stack);
  • js 从上到下解析方法,将其中的同步任务按照执行顺序排列到执行栈中;
  • 当程序调用外部的 API 时,比如 ajax、setTimeout 等,会将此类异步任务挂起,继续执行执行栈中的任务,等异步任务返回结果后,再按照执行顺序排列到事件队列中;
  • 主线程先将执行栈中的同步任务清空,然后检查事件队列中是否有任务,如果有,就将第一个事件对应的回调推到执行栈中执行,若在执行过程中遇到异步任务,则继续将这个异步任务排列到事件队列中。
  • 主线程每次将执行栈清空后,就去事件队列中检查是否有任务,如果有,就每次取出一个推到执行栈中执行,这个过程是循环往复的… …,这个过程被称为“Event Loop 事件循环”
    参考地址:Event Loop 这个循环你晓得么?(附 GIF 详解)-饿了么前端

四、网络问题

1、http 响应常见状态码

  • 100-199 : 表示成功接收请求, 要求客户端继续提交下一次请求才能完成整个处理过程
  • 200-299: 表示成果接收请求并已完成整个处理过程. 常用 200
  • 300-399: 为完成请求, 客户需进一步细化需求: 例如: 请求的资源已经移动一个新地址, 常用 302(重定向), 307 和 304(拿缓存)
  • 400-499: 客户端的请求有错误, 包含语法错误或者不能正确执行. 常用 404(请求的资源在 web 服务器中没有) 403(服务器拒绝访问, 权限不够)
  • 500-599: 服务器端出现错误
    常用:
  • 200 正常,表示一切正常, 返回的是正常请求结果
  • 302/307 临时重定向,指出请求的文档已被临时移动到别处, 此文档的新的 url 在 location 响应头中给出
  • 304 未修改,表示客户机缓存的版本是最新的, 客户机应该继续使用它
  • 403 禁止,服务器理解客户端请求, 但拒绝处理它, 通常用于服务器上文件或目录的权限设置所致
  • 404 找不到,服务器上不存在客户机所请求的资源
  • 500 服务器内部错误,服务器端的 cgi, asp, jsp 等程序发生错误

2、简述 http 1.1 与 http 1.0 的区别。

  • http 1.0 对于每个连接都得建立一次连接, 一次只能传送一个请求和响应, 请求就会关闭, http1.0 没有 Host 字段
  • 而 http1.1 在同一个连接中可以传送多个请求和响应, 多个请求可以重叠和同时进行, http1.1 必须有 host 字段
  • http1.1 中引入了 ETag 头, 它的值 entity tag 可以用来唯一的描述一个资源. 请求消息中可以使用 If-None-Match 头域来匹配资源的 entitytag 是否有变化
  • http1.1 新增了 Cache-Control 头域(消息请求和响应请求都可以使用), 它支持一个可扩展的指令子集
  • http1.0 中只定义了 16 个状态响应码, 对错误或警告的提示不够具体. http1.1 引入了一个 Warning 头域, 增加对错误或警告信息的描述. 且新增了 24 个状态响应码

3、说一下 TCP 三次握手和四次挥手。

  • 建立 TCP 连接需要三次握手:三次握手: 首先 Client 端发送连接请求报文,Server 段接受连接后回复 ACK 报文,并为这次连接分配资源。Client 端接收到 ACK 报文后也向 Server 段发生 ACK 报文,并分配资源,这样 TCP 连接就建立了。
    • 第一步: 客户机的 TCP 先向服务器的 TCP 发送一个连接请求报文. 这个特殊的报文中不含应用层数据, 其首部中的 SYN 标志位被置 1. 另外, 客户机会随机选择一个起始序号 seq=x(连接请求报文不携带数据,但要消耗掉一个序号)
    • 第二步: 服务器端的 TCP 收到连接请求报文后, 若同意建立连接, 就向客户机发送请求, 并为该 TCP 连接分配 TCP 缓存和变量. 在确认报文中,SYN 和 ACK 位都被置为 1, 确认号字段的值为 x+1, 并且服务器随机产生起始序号 seq=y(确认报文不携带数据, 但也要消耗掉一个序号). 确认报文同样不包含应用层数据.
    • 第三步: 当客户机收到确认报文后, 还要向服务器给出确认, 并且也要给该连接分配缓存和变量. 这个报文的 ACK 标志位被置为 1, 序号字段为 x+1, 确认号字段为 y+1
  • 四次挥手
    • 第一步: 客户机打算关闭连接,就向其 TCP 发送一个连接释放报文,并停止再发送数据,主动关闭 TCP 连接, 该报文的 FIN 标志位被置 1, seq=u, 它等于前面已经传送过的数据的最后一个字节的序号加 1(FIN 报文即使不携带数据,也要消耗掉一个序号)
    • 第二步: 服务器接收连接释放报文后即发出确认, 确认号是 ack=u+1, 这个报文自己的序号是 v, 等于它前面已传送过的数据的最后一个自己的序号加 1. 此时, 从客户机到服务器这个方向的连接就释放了, TCP 连接处于半关闭状态. 但服务器若发送数据, 客户机仍要接收, 即从服务器到客户机的连接仍未关闭.
    • 第三步: 若服务器已经没有了要向客户机发送的数据, 就通知 TCP 释放连接, 此时其发出 FIN=1 的连接释放报文
    • 第四步: 客户机收到连接释放报文后, 必须发出确认. 在确认报文中, ACK 字段被置为 1, 确认号 ack=w+1, 序号 seq=u+1. 此时, TCP 连接还没有释放掉, 必须经过等待计时器设置的时间 2MSL 后, A 才进入到连接关闭状态.

4、计算机网络体系结构有哪些

学习计算机网络时我们一般采用折中的办法,也就是中和 OSI 和 TCP/IP 的优点,采用一种只有五层协议的体系结构,这样既简洁又能将概念阐述清楚。

应用层

应用层(application-layer)的任务是通过应用进程间的交互来完成特定网络应用。应用层协议定义的是应用进程(进程:主机中正在运行的程序)间的通信和交互的规则。对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如域名系统 DNS,支持万维网应用的 HTTP 协议,支持电子邮件的 SMTP 协议等等。我们把应用层交互的数据单元称为报文。
域名系统

  • 域名系统(Domain Name System 缩写 DNS,Domain Name 被译为域名)是因特网的一项核心服务,它作为可以将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的 IP 数串。(百度百科)例如:一个公司的 Web 网站可看作是它在网上的门户,而域名就相当于其门牌地址,通常域名都使用该公司的名称或简称。例如上面提到的微软公司的域名,类似的还有:IBM 公司的域名是 www.ibm.com、Oracle 公司的域名是 www.oracle.com、Cisco 公司的域名是 www.cisco.com 等。
    HTTP 协议
  • 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的 WWW(万维网) 文件都必须遵守这个标准。设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法。(百度百科)
运输层

运输层(transport layer)的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务。应用进程利用该服务传送应用层报文。“通用的”是指并不针对某一个特定的网络应用,而是多种应用可以使用同一个运输层服务。由于一台主机可同时运行多个线程,因此运输层有复用和分用的功能。所谓复用就是指多个应用层进程可同时使用下面运输层的服务,分用和复用相反,是运输层把收到的信息分别交付上面应用层中的相应进程。
运输层主要使用以下两种协议

  • 传输控制协议 TCP(Transmisson Control Protocol)–提供面向连接的,可靠的数据传输服务。
  • 用户数据协议 UDP(User Datagram Protocol)–提供无连接的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。
    UDP 的主要特点
  • UDP 是无连接的;
  • UDP 使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态(这里面有许多参数);
  • UDP 是面向报文的;
  • UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如 直播,实时视频会议等);
  • UDP 支持一对一、一对多、多对一和多对多的交互通信;
  • UDP 的首部开销小,只有 8 个字节,比 TCP 的 20 个字节的首部要短。
    TCP 的主要特点
  • TCP 是面向连接的。(就好像打电话一样,通话前需要先拨号建立连接,通话结束后要挂机释放连接);
  • 每一条 TCP 连接只能有两个端点,每一条 TCP 连接只能是点对点的(一对一);
  • TCP 提供可靠交付的服务。通过 TCP 连接传送的数据,无差错、不丢失、不重复、并且按序到达;
  • TCP 提供全双工通信。TCP 允许通信双方的应用进程在任何时候都能发送数据。TCP 连接的两端都设有发送缓存和接收缓存,用来临时存放双方通信的数据;
  • 面向字节流。TCP 中的“流”(Stream)指的是流入进程或从进程流出的字节序列。“面向字节流”的含义是:虽然应用程序和 TCP 的交互是一次一个数据块(大小不等),但 TCP 把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。
网络层

在 计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路,也可能还要经过很多通信子网。网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。 在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报 ,简称 数据报。
这里要注意:不要把运输层的“用户数据报 UDP ”和网络层的“ IP 数据报”弄混。另外,无论是哪一层的数据单元,都可笼统地用“分组”来表示。
这里强调指出,网络层中的“网络”二字已经不是我们通常谈到的具体网络,而是指计算机网络体系结构模型中第三层的名称.
互联网是由大量的异构(heterogeneous)网络通过路由器(router)相互连接起来的。互联网使用的网络层协议是无连接的网际协议(Intert Prococol)和许多路由选择协议,因此互联网的网络层也叫做网际层或 IP 层。

数据链路层

数据链路层(data link layer)通常简称为链路层。两台主机之间的数据传输,总是在一段一段的链路上传送的,这就需要使用专门的链路层的协议。 在两个相邻节点之间传送数据时,数据链路层将网络层交下来的 IP 数据报组装程帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。
在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束。这样,数据链路层在收到一个帧后,就可从中提出数据部分,上交给网络层。 控制信息还使接收端能够检测到所收到的帧中有误差错。如果发现差错,数据链路层就简单地丢弃这个出了差错的帧,以避免继续在网络中传送下去白白浪费网络资源。如果需要改正数据在链路层传输时出现差错(这就是说,数据链路层不仅要检错,而且还要纠错),那么就要采用可靠性传输协议来纠正出现的差错。这种方法会使链路层的协议复杂些。

物理层

在物理层上所传送的数据单位是比特。 物理层(physical layer)的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异。 使其上面的数据链路层不必考虑网络的具体传输介质是什么。“透明传送比特流”表示经实际电路传送后的比特流没有发生变化,对传送的比特流来说,这个电路好像是看不见的。
在互联网使用的各种协中最重要和最著名的就是 TCP/IP 两个协议。现在人们经常提到的 TCP/IP 并不一定单指 TCP 和 IP 这两个具体的协议,而往往表示互联网所使用的整个 TCP/IP 协议族。
上面我们对计算机网络的五层体系结构有了初步的了解,下面附送一张七层体系结构图总结一下。图片来源:

https://blog.csdn.net/yaopeng_2005/article/details/7064869

5、Http 和 Https 的区别(常考)。

  • Http 协议运行在 TCP 之上,明文传输,客户端与服务器端都无法验证对方的身份;Https 是身披 SSL(Secure Socket Layer)外壳的 Http,运行于 SSL 上,SSL 运行于 TCP 之上,是添加了加密和认证机制的 HTTP。二者之间存在如下不同:
  • 端口不同:Http 与 Http 使用不同的连接方式,用的端口也不一样,前者是 80,后者是 443;
  • 资源消耗:和 HTTP 通信相比,Https 通信会由于加减密处理消耗更多的 CPU 和内存资源;
  • 开销:Https 通信需要证书,而证书一般需要向认证机构购买;
  • Https 的加密机制是一种共享密钥加密和公开密钥加密并用的混合加密机制。

6、对称加密与非对称加密。

  • 对称密钥加密是指加密和解密使用同一个密钥的方式,这种方式存在的最大问题就是密钥发送问题,即如何安全地将密钥发给对方;而非对称加密是指使用一对非对称密钥,即公钥和私钥,公钥可以随意发布,但私钥只有自己知道。发送密文的一方使用对方的公钥进行加密处理,对方接收到加密信息后,使用自己的私钥进行解密。
  • 由于非对称加密的方式不需要发送用来解密的私钥,所以可以保证安全性;但是和对称加密比起来,它非常的慢,所以我们还是要用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。

7、TCP 协议如何来保证传输的可靠性。

TCP 提供一种面向连接的、可靠的字节流服务。其中,面向连接意味着两个使用 TCP 的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个 TCP 连接。在一个 TCP 连接中,仅有两方进行彼此通信;而字节流服务意味着两个应用程序通过 TCP 链接交换 8bit 字节构成的字节流,TCP 不在字节流中插入记录标识符。
对于可靠性,TCP 通过以下方式进行保证:

  • 数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时 TCP 发送数据端超时后会重发数据;
  • 对失序数据包重排序:既然 TCP 报文段作为 IP 数据报来传输,而 IP 数据报的到达可能会失序,因此 TCP 报文段的到达也可能会失序。TCP 将对失序数据进行重新排序,然后才交给应用层;
  • 丢弃重复数据:对于重复数据,能够丢弃重复数据;
  • 应答机制:当 TCP 收到发自 TCP 连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
  • 超时重发:当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
  • 流量控制:TCP 连接的每一方都有固定大小的缓冲空间。TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。TCP 使用的流量控制协议是可变大小的滑动窗口协议。
    参考链接 计算机网络面试问题集锦

8、查找域名对应 IP 地址。

这一步包括 DNS 具体的查找过程,包括:浏览器缓存->系统缓存->路由器缓存…

  • 浏览器搜索自己的 DNS 缓存(维护一张域名与 IP 地址的对应表);
  • 搜索操作系统中的 DNS 缓存(维护一张域名与 IP 地址的对应表);
  • 搜索操作系统的 hosts 文件( Windows 环境下,维护一张域名与 IP 地址的对应表);
  • 操作系统将域名发送至 LDNS(本地区域名服务器),LDNS 查询 自己的 DNS 缓存(一般查找成功率在 80% 左右),查找成功则返回结果,失败则发起一个迭代 DNS 解析请求:
    • LDNS 向 Root Name Server (根域名服务器,如 com、net、org 等的解析的顶级域名服务器的地址)发起请求,此处,Root Name Server 返回 com 域的顶级域名服务器的地址;
    • LDNS 向 com 域的顶级域名服务器发起请求,返回 baidu.com 域名服务器地址;
    • LDNS 向 baidu.com 域名服务器发起请求,得到 www.baidu.com 的 IP 地址;
  • LDNS 将得到的 IP 地址返回给操作系统,同时自己也将 IP 地址缓存起来;
  • 操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来;

9、从输入 URL 到页面加载发生了什么【必考】?

总体来说分为以下几个过程:

  • DNS 解析
  • TCP 连接
  • 发送 HTTP 请求
  • 服务器处理请求并返回 HTTP 报文
  • 浏览器解析渲染页面
  • 连接结束
    这道题的区分度很高建议大家仔细查看下面这篇文章从输入 URL 到页面加载发生了什么

10、HTTP 的几种请求方法用途。

  • GET 方法:发送一个请求来取得服务器上的某一资源
  • POST 方法:向 URL 指定的资源提交数据或附加新的数据
  • PUT 方法:跟 POST 方法很像,也是想服务器提交数据。但是,它们之间有不同。PUT 指定了资源在服务器上的位置,而 POST 没有
  • HEAD 方法:只请求页面的首部
  • DELETE 方法:删除服务器上的某资源
  • OPTIONS 方法:它用于获取当前 URL 所支持的方法。如果请求成功,会有一个 Allow 的头包含类似“GET,POST”这样的信息
  • TRACE 方法:TRACE 方法被用于激发一个远程的,应用层的请求消息回路
  • CONNECT 方法:把请求连接转换到透明的 TCP/IP 通道

11、127.0.0.1 与 192.168.0.1 有什么区别【可能考】?

首先明确二者没有区别!两个 IP 地址的角度不一样,127.0.0.1 是从 IETF(因特尔工程任务组)规定看,是保留给本机使用的 IP 地址,所有的计算机默认都是相同的。而 192.168.0.1 其实只是 IETF 在 c 类网址中,专门留出给专用网络用的一个网段中的一个 IP 而已,该网段包含了 192.168.0.1 到 192.168.255.255 中所有的 IP 地址。

12、五类 ip 地址的范围。

IP 地址分为 A,B,C,D,E 五类。
网络号:用于识别主机所在的网络;
主机号:用于识别该网络中的主机。
其中 A 类分配给政府机关使用,B 类地址给大中型企业使用,C 类地址给个人使用。这三种是主要的。
IP 地址分为五类,A 类保留给政府机构,B 类分配给中等规模的公司,C 类分配给任何需要的人,D 类用于组播,E 类用于实验,各类可容纳的地址数目不同。
其中 A 类、B 类、和 C 类这三类地址用于 TCP/IP 节点,其它两类 D 类和 E 类被用于特殊用途。
A、B、C 三类 IP 地址的特征:当将 IP 地址写成二进制形式时,A 类地址的第一位总是 O,B 类地址的前两位总是 10,C 类地址的前三位总是 110。
A 类地址

  • ⑴ A 类地址第 1 字节为网络地址,其它 3 个字节为主机地址。
  • ⑵ A 类地址范围:1.0.0.1—126.155.255.254
  • ⑶ A 类地址中的私有地址和保留地址:
    • ① 10.X.X.X 是私有地址(所谓的私有地址就是在互联网上不使用,而被用在局域网络中的地址)。
    • ② 127.X.X.X 是保留地址,用做循环测试用的。
      B 类地址
  • ⑴ B 类地址第 1 字节和第 2 字节为网络地址,其它 2 个字节为主机地址。
  • ⑵ B 类地址范围:128.0.0.1—191.255.255.254。
  • ⑶ B 类地址的私有地址和保留地址
    • ① 172.16.0.0—172.31.255.255 是私有地址
    • ② 169.254.X.X 是保留地址。如果你的 IP 地址是自动获取 IP 地址,而你在网络上又没有找到可用的 DHCP 服务器。就会得到其中一个 IP。
      C 类地址
  • ⑴ C 类地址第 1 字节、第 2 字节和第 3 个字节为网络地址,第 4 个个字节为主机地址。另外第 1 个字节的前三位固定为 110。
  • ⑵ C 类地址范围:192.0.0.1—223.255.255.254。
  • ⑶ C 类地址中的私有地址:
    • 192.168.X.X 是私有地址。
      D 类地址
  • ⑴ D 类地址不分网络地址和主机地址,它的第 1 个字节的前四位固定为 1110。
  • ⑵ D 类地址范围:224.0.0.1—239.255.255.254
    E 类地址
  • ⑴ E 类地址也不分网络地址和主机地址,它的第 1 个字节的前五位固定为 11110。
  • ⑵ E 类地址范围:240.0.0.1—255.255.255.254

13、HTTP 长连接、短连接。

在 HTTP/1.0 中默认使用短连接。也就是说,客户端和服务器每进行一次 HTTP 操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS 文件等),每遇到这样一个 Web 资源,浏览器就会重新建立一个 HTTP 会话。
而从 HTTP/1.1 起,默认使用长连接,用以保持连接特性。使用长连接的 HTTP 协议,会在响应头加入这行代码:

Connection:keep-alive

在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive 不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如 Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。
HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。
HTTP 长连接、短连接究竟是什么?

14、如何理解 HTTP 协议是无状态的【常考】?

HTTP 协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。也就是说,打开一个服务器上的网页和上一次打开这个服务器上的网页之间没有任何联系。HTTP 是一个无状态的面向连接的协议,无状态不代表 HTTP 不能保持 TCP 连接,更不能代表 HTTP 使用的是 UDP 协议(无连接)。

15、各种协议与 HTTP 协议之间的关系。

一般面试官会通过这样的问题来考察你对计算机网络知识体系的理解。

16、Socket 连接与 HTTP 连接的联系与区别(需了解)。

由于通常情况下 Socket 连接就是 TCP 连接,因此 Socket 连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
而 HTTP 连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。
很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是 Socket 连接,服务器就可以直接将数据传送给客户端;若双方建立的是 HTTP 连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。

17、http 报文大小限制。

如前所述,一个 HTTP 报文包含起始行,头域和消息体,HTTP 协议本身并没有对报文中任一部分的长度做限制,也就是说,理论上一个请求 URI 可以无限长,头域可以无限多,请求体可以无限大。但在实际场景下,请求 URI 的长度会受到浏览器的限制,如果在浏览器中输入过长的 URL,那么浏览器会自动进行截断。而服务器出于安全性和效率的考虑,也会对头域和消息体的大小作出一定的限制。

18、http(tcp) 报文结构(必考)。

例如一个 100kb 的 HTML 文档需要传送到另外一台计算机,并不会整个文档直接传送过去,可能会切割成几个部分,比如四个分别为 25kb 的数据段。而每个数据段再加上一个 TCP 首部,就组成了 TCP 报文。
TCP 报文 (Segment),包括首部和数据部分。
首部:

  • 源端口 source port
  • 目的端口 destination port
  • 序号 sequence number
  • 确认号 acknowledgment number
  • 数据偏移 offset
  • 保留 reserved
  • 标志位 tcp flags
  • 窗口大小 window size
  • 检验和 checksum
  • 紧急指针 urgent pointer
  • 选项 tcp options

19、HTTP 的缓存机制(常考)。

Http 的缓存主要利用 header 里的两个字段来控制:

  • Cache-control主要包含以及几个字段:
    • private:则只有客户端可以缓存
    • public:客户端和代理服务器都可以缓存
    • max-age:缓存的过期时间
    • no-cache:需要使用对比缓存来验证缓存数据
    • no-store:所有内存都不会进行缓存
  • ETag:即用来进行对比缓存,Etag 是服务端资源的一个标识码
    • 当客户端发送第一次请求时服务端会下发当前请求资源的标识码 Etag,下次再请求时,客户端则会通过 header 里的 If-None-Match 将这个标识码 Etag 带上,服务端将客户端传来的 Etag 与最新的资源 Etag 做对比,如果一样,则表示资源没有更新,返回 304。
      通过 Cache-control 和 Etag 的配合来实现 Http 的缓存机制。

20、Cookie

Cookie 就是用来在本地缓存记住一些状态的,一个 Cookie 一般都包含 domin(所属域)、path、Expires(过期时间)等几个属性。服务端可以通过在响应头里的 set-cookies 来将状态写入客户端的 Cookie 里。下次客户端发起请求时可以将 Co

21、Http 2.0 与 http1.x 相比有什么优点(常考)?

  • 二进制格式:http1.x 是文本协议,而 http2.0 是二进制以帧为基本单位,是一个二进制协议,一帧中除了包含数据外同时还包含该帧的标识:Stream Identifier,即标识了该帧属于哪个 request,使得网络传输变得十分灵活。
  • 多路复用: 一个很大的改进,原先 http1.x 一个连接一个请求的情况有比较大的局限性,也引发了很多问题,如建立多个连接的消耗以及效率问题。
    • http1.x 为了解决效率问题,可能会尽量多的发起并发的请求去加载资源,然而浏览器对于同一域名下的并发请求有限制,而优化的手段一般是将请求的资源放到不同的域名下来突破这种限制。
    • 而 http2.0 支持的多路复用可以很好的解决这个问题,多个请求共用一个 TCP 连接,多个请求可以同时在这个 TCP 连接上并发,一个是解决了建立多个 TCP 连接的消耗问题,一个也解决了效率的问题。那么是什么原理支撑多个请求可以在一个 TCP 连接上并发呢?基本原理就是上面的二进制分帧,因为每一帧都有一个身份标识,所以多个请求的不同帧可以并发的无序发送出去,在服务端会根据每一帧的身份标识,将其整理到对应的 request 中。
  • header 头部压缩:主要是通过压缩 header 来减少请求的大小,减少流量消耗,提高效率。因为之前存在一个问题是,每次请求都要带上 header,而这个 header 中的数据通常是一层不变的。
  • 支持服务端推送

22、流量控制

流量控制是对一条通信路径上的流量进行控制,就是发送方通过获取接收方的回馈来动态调整发送的速率,来达到控制流量的效果,其目的是保证发送者的发送速度不超过接收者的接收速度。

23、拥塞控制

拥塞控制是对整个通信子网的流量进行控制,属于全局控制。

  1. 慢开始+拥塞避免 先来看一张经典的图:
    一开始使用慢启动,即拥塞窗口设为 1,然后拥塞窗口指数增长到慢开始的门限值(ssthresh=16),则切换为拥塞避免,即加法增长,这样增长到一定程度,导致网络拥塞,则此时会把拥塞窗口重新降为 1,即重新慢开始,同时调整新的慢开始门限值为 12,之后以此类推。
  2. 快重传+快恢复
  • 快重传:上面我们说的重传机制都是等到超时还未收到接收方的回复,才开始进行重传。而快重传的设计思路是:如果发送方收到 3 个重复的接收方的 ACK,就可以判断有报文段丢失,此时就可以立即重传丢失的报文段,而不用等到设置的超时时间到了才开始重传,提高了重传的效率。
  • 快恢复:上面的拥塞控制会在网络拥塞时将拥塞窗口降为 1,重新慢开始,这样存在的一个问题就是网络无法很快恢复到正常状态。快恢复就是来优化这个问题的,使用快恢复,则出现拥塞时,拥塞窗口只会降低到新的慢开始门阀值(即 12),而不会降为 1,然后直接开始进入拥塞避免加法增长
    感谢:Android 网络系列(一):关于计算机网络的一些基础 -舒大飞
  • 9
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值