• WEB前端面试题整理


     

    HTML:

     

    1. 说下行内元素和块级元素的区别?行内块元素的兼容性使用?(IE8 以下)
       (1)行内元素:会在水平方向排列,不能包含块级元素,设置width无效,height无效(可以设置line-height),margin上下无效,padding上下无效。
           块级元素:各占据一行,垂直方向排列。从新行开始结束接着一个断行。
       (2)兼容性:display:inline-block;*display:inline;*zoom:1; 

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

    3.你知道多少种Doctype文档类型? 

       该标签可声明三种 DTD 类型,分别表示严格版本、过渡版本以及基于框架的 HTML 文档。 
     HTML 4.01 规定了三种文档类型:Strict、Transitional 以及 Frameset。 
       XHTML 1.0 规定了三种 XML 文档类型:Strict、Transitional 以及 Frameset。 
    Standards (标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而 Quirks 

     (包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。 

    4.Doctype作用?标准模式与兼容模式各有什么区别?
       (1)<!DOCTYPE>告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。
        (2)标准模式的排版和JS运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。 

    5.严格模式和混杂模式的区分,以及如何触发这2种模式? 

    严格模式就是浏览器根据web标准去解析页面,是一种要求严格的DTD,不允许使用任何表现层的语法,如 

    混杂模式是一种向后兼容的解析方法。 

    触发标准模式或者说严格模式很简单,就是Html前申明正确的DTD,出发混杂模式可以在html文档开始不声明DTD,或者在DOCTYPE前加入XML声明(DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现。) 

    6.说说严格模式的限制 

    严格模式主要有以下限制: 

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

    7.设立”严格模式”的目的,主要有以下几个: 

    消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为; 

    消除代码运行的一些不安全之处,保证代码运行的安全; 

    提高编译器效率,增加运行速度; 

    为未来新版本的Javascript做好铺垫。 

    注:经过测试IE6,7,8,9均不支持严格模式。 

    8.页面导入样式时,使用link和@import有什么区别?
      (1)link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;而@import是CSS提供的,只能用于加载CSS;
      (2)页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
      (3)import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题; 

    9.html5有哪些新特性?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?
    (Q1) 
         HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。
         (1)绘画 canvas;
         (2)用于媒介回放的 video 和 audio 元素;
         (3)本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
         (4)sessionStorage 的数据在浏览器关闭后自动删除;
         (5)语意化更好的内容元素,比如 article、footer、header、nav、section;
         (6)表单控件,calendar、date、time、email、url、search;
         (7)新的技术webworker, websocket, Geolocation;
     (Q2)
         IE8/IE7/IE6支持通过document.createElement方法产生的标签,
         可以利用这一特性让这些浏览器支持HTML5新标签,
         浏览器支持新标签后,还需要添加标签默认的样式。
         当然也可以直接使用成熟的框架、比如html5shim;
    <!--[if lt IE 9]>
       <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
    <![endif]--> 

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

    11.Html和xhtml有什么区别? 

    html是一种基本的web网页设计语言,xhtml是一个基于XML的置标语言。 

    最主要的不同: 

    XHTML元素必须正确的被嵌套,元素必须关闭,标签必须小写,必须有根元素。 

    12.行内元素有哪些?块级元素有哪些?CSS盒模型 

    行内元素: br span input a 

    块级元素IV P H1 H2 FORM ul 

    CSS盒模型内容:padding border margin 

    13.iframe有那些缺点?
    iframe会阻塞主页面的Onload事件;
    搜索引擎的检索程序无法解读这种页面,不利于SEO;
    iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。
    使用iframe之前需要考虑这两个缺点。如果需要使用iframe,最好是通过javascript动态给iframe添加src属性值,这样可以绕开以上两个问题。 

    14.<strong><em><b><i>标签 

    <strong> 标签和 <em> 标签一样,用于强调文本,但它强调的程度更强一些。 

    em 是 斜体强调标签,更强烈强调,表示内容的强调点。相当于html元素中的 <i>...</i>; 

    < b > < i >是视觉要素,分别表示无意义的加粗,无意义的斜体。

    em 和 strong 是表达要素(phrase elements)。   

    CSS:

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

    行内元素:a、b、span、img、input、strong、select、label、em、button、textarea
    块级元素:div、ul、li、dl、dt、dd、p、h1-h6、blockquote
    空元素:即系没有内容的HTML元素,例如:br、meta、hr、link、input、img

     

    1.清除浮动有哪些方式?比较好的方式是哪一种?
      (Q1)
         (1)父级div定义height。
         (2)结尾处加空div标签clear:both。
         (3)父级div定义伪类:after和zoom。
         (4)父级div定义overflow:hidden。
         (5)父级div定义overflow:auto。
         (6)父级div也浮动,需要定义宽度。
         (7)父级div定义display:table。
         (8)结尾处加br标签clear:both。

    (9)使用空标签清除浮动。
           这种方法是在所有浮动标签后面添加一个空标签 定义css clear:both. 弊端就是增加了无意义标签。
    (10)使用overflow。

               给包含浮动元素的父标签添加css属性 overflow:auto; zoom:1; zoom:1用于兼容IE6。
       (Q2)比较好的是第3种方式,好多网站都这么用。

    2.box-sizing常用的属性有哪些?分别有什么作用?
        (Q1)box-sizing: content-box|border-box|inherit;
        (Q2)content-box:宽度和高度分别应用到元素的内容框。在宽度和高度之外绘制元素的内边距和边框(元素  默认效果)。
            border-box:元素指定的任何内边距和边框都将在已设定的宽度和高度内进行绘制。通过从已设定的宽  度和高度分别减去边框和内边距才能得到内容的宽度和高度。

    3.介绍一下box-sizing属性?

    box-sizing属性主要用来控制元素的盒模型的解析模式。默认值是content-box

    content-box:让元素维持W3C的标准盒模型。元素的宽度/高度由border + padding + content的宽度/高度决定,设置width/height属性指的是content部分的宽/高

    border-box:让元素维持IE传统盒模型(IE6以下版本和IE6~7的怪异模式)。设置width/height属性指的是border + padding + content

    标准浏览器下,按照W3C规范对盒模型解析,一旦修改了元素的边框或内距,就会影响元素的盒子尺寸,就不得不重新计算元素的盒子尺寸,从而影响整个页面的布局。

    4.CSS3中新增了一种盒模型计算方式:box-sizing。盒模型默认的值是content-box, 新增的值是padding-boxborder-box,几种盒模型计算元素宽高的区别如下:

    content-box(默认)

    布局所占宽度Width:

    Width = width + padding-left + padding-right + border-left + border-right

    布局所占高度Height:

    Height = height + padding-top + padding-bottom + border-top + border-bottom

    padding-box

    布局所占宽度Width:

    Width = width(包含padding-left + padding-right) + border-top + border-bottom

    布局所占高度Height:

    Height = height(包含padding-top + padding-bottom) + border-top + border-bottom

    border-box

    布局所占宽度Width:

    Width = width(包含padding-left + padding-right + border-left + border-right)

    布局所占高度Height:

    Height = height(包含padding-top + padding-bottom + border-top + border-bottom)

    5.介绍一下标准的CSS的盒子模型?低版本IE的盒子模型有什么不同的?
    (1)有两种, IE 盒子模型、W3C 盒子模型。
    (2)盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border)。
    (3)区  别: IE的content部分把 border 和 padding计算了进去。

    什么是盒子模型?

    在网页中,一个元素占有空间的大小由几个部分构成,其中包括元素的内容(content),元素的内边距(padding),元素的边框(border),元素的外边距(margin)四个部分。这四个部分占有的空间中,有的部分可以显示相应的内容,而有的部分只用来分隔相邻的区域或区域。4个部分一起构成了css中元素的盒模型。

    6.IE 8以下版本的浏览器中的盒模型有什么不同?
    IE8以下浏览器的盒模型中定义的元素的宽高不包括内边距和边框

    7.css引入的方式有哪些?link和@import的区别?

    引入方式3种:行内添加定义style属性值,页面头部内内嵌调用和外链调用,

    区别:

    1.link是xhtml标签,除了加载css外,还可以定义RSS等其他事务,@import只能加载CSS

    2.link引用CSS时候,页面载入的时候同时加载,@import需要页面网页完全载入后加载

    3.link是XHTML标签,没有兼容问题,@import是在CSS2.1提出的,低版本的浏览器不支持。

    4.link支持使用javascript控制DOM去改变样式,但是@import不支持。

    8.CSS选择符有哪些? 哪些属性可以继承?优先级算法如何计算?内联和Important哪个优先级高?

    1.id选择器( # myid)

        2.类选择器(.myclassname)

        3.标签选择器(div, h1, p)

        4.相邻选择器(h1 + p)

        5.子选择器(ul > li)

        6.后代选择器(li a)

        7.通配符选择器( * )

        8.属性选择器(a[rel = "external"])

    9.伪类选择器(a: hover, li:nth-child)

    important 比 内联优先级高,但内联比 id 要高

    9.img标签上的title和alt属性区别是什么?

    alt是当图片不能正常显示的时候,用文字代替

    title该属性提供信息

    10.display:nonevisibility:hidden的区别?

         diplay:none  隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢,就当他从来不存在。

         visibility:hidden  隐藏对应的元素,但是在文档布局中仍保留原来的空间。

    11.position的值? relative和absolute分别是相对于谁进行定位的?

    (1)absolute :生成绝对定位的元素, 相对于最近一级的 定位不是 static 的父元素来进行定位。

        (2)fixed (老IE不支持)生成绝对定位的元素,通常相对于浏览器窗口或 frame 进行定位。

    (3)relative 生成相对定位的元素,相对于其在普通流中的位置进行定位。

    (4)static 默认值。没有定位,元素出现在正常的流中

    (5)sticky 生成粘性定位的元素,容器的位置根据正常文档流计算得出

    12.position:absolutefloat属性的异同

    共同点:对内联元素设置floatabsolute属性,可以让元素脱离文档流,并且可以设置其宽高。

    不同点:float仍会占据位置,absolute会覆盖文档流中的其他元素。

    13.如何在页面上实现一个圆形的可点击区域?
    (1)map+area或者svg
    (2)border-radius
    (3)纯js实现 需要求一个点在不在圆上简单算法、获取鼠标坐标等等

    14.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> 元素。

        :enabled  :disabled 控制表单控件的禁用状态。

    :checked        单选框或复选框被选中。

    15.css3有哪些新特性?

    CSS3实现圆角(border-radius),阴影(box-shadow),
    对文字加特效(text-shadow、),线性渐变(gradient),旋转(transform)
    transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);//旋转,缩放,定位,倾斜
    增加了更多的CSS选择器  多背景 rgba
    在CSS3中唯一引入的伪元素是::selection.
    媒体查询,多栏布局
    border-image

    16.常见兼容性问题?

    (1)png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8.也可以引用一段脚本处理.
    (2)浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。
    (3)IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。
    (4)浮动ie产生的双倍距离(IE6双边距问题:在IE6下,如果对元素设置了浮动,同时又设置了margin-left或margin-right,margin值会加倍。)
    (5)#box{ float:left; 10px; margin:0 0 0 100px;}
    这种情况之下IE会产生20px的距离,解决方案是在float的标签样式控制中加入_display:inline;将其转化为行内属性。(_这个符号只有ie6会识别)
         渐进识别的方式,从总体中逐渐排除局部。
             首先,巧妙的使用“9”这一标记,将IE游览器从所有情况中分离出来。
             接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。
      css
          .bb{
           /*所有识别*/
          .background-color:#00deff9; /*IE6、7、8识别*/
          +/*IE6、7识别*/
          _background-color:#1e0bd1;/*IE6识别*/
          }
         怪异模式问题:漏写DTD声明,Firefox仍然会按照标准模式来解析网页,但在IE中会触发
         怪异模式。为避免怪异模式给我们带来不必要的麻烦,最好养成书写DTD声明的好习惯。现在
         可以使用[html5](http://www.w3.org/TR/html5/single-page.html)推荐的写法:`<doctype html>`
    17.上下margin重合问题
         ie和ff都存在,相邻的两个div的margin-left和margin-right不会重合,但是margin-top和margin-bottom却会发生重合。

        解决方法,养成良好的代码编写习惯,同时采用margin-top或者同时采用margin-bottom。
    18.display有哪些值?说明他们的作用。
           block         块类型。默认宽度为父元素宽度,可设置宽高,换行显示。
         none          缺省值。象行内元素类型一样显示。
         inline        行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。
         inline-block  默认宽度为内容宽度,可以设置宽高,同行显示。
         list-item     象块类型元素一样显示,并添加样式列表标记。
         table         此元素会作为块级表格来显示。
         inherit       规定应该从父元素继承 display 属性的值。

    19.CSS居中(包括水平居中和垂直居中)
    内联元素居中方案
    水平居中设置:
      1.行内元素
        设置 text-align:center;
      2.Flex布局
        设置display:flex;justify-content:center;(灵活运用,支持Chroime,Firefox,IE9+)
    垂直居中设置:
      1.父元素高度确定的单行文本(内联元素)
        设置 height = line-height;
      2.父元素高度确定的多行文本(内联元素)
        a:插入 table (插入方法和水平居中一样),然后设置 vertical-align:middle;
        b:先设置 display:table-cell 再设置 vertical-align:middle;
    块级元素居中方案
    水平居中设置:
      1.定宽块状元素
        设置 左右 margin 值为 auto;
      2.不定宽块状元素
        a:在元素外加入 table 标签(完整的,包括 table、tbody、tr、td),该元素写在 td 内,然后设置 margin 的值为 auto;
        b:给该元素设置 displa:inine 方法;
        c:父元素设置 position:relative 和 left:50%,子元素设置 position:relative 和 left:50%;
    垂直居中设置:
        使用position:absolute(fixed),设置left、top、margin-left、margin-top的属性;
        利用position:fixed(absolute)属性,margin:auto这个必须不要忘记了;
        利用display:table-cell属性使内容垂直居中;
        使用css3的新属性transform:translate(x,y)属性;
        使用:before元素;

    CSS实现垂直水平居中案例:

    一道经典的问题,实现方法有很多种,以下是其中一种实现:
    HTML结构:

    <div class="wrapper"> <div class="content"></div> </div>

    CSS:

    .wrapper { position: relative; 500px; height: 500px; background-color: #ddd; } .content{ background-color:#6699FF; 200px; height:200px; position: absolute; //父元素需要相对定位 top: 50%; left: 50%; margin-top:-100px ; //二分之一的height,width margin-left: -100px; }

    20.在书写高效 CSS 时会有哪些问题需要考虑?
    reset。参照上题“描述下 “reset” CSS 文件的作用和使用它的好处”的答案。
    规范命名。尤其对于没有语义化的html标签,例如div,所赋予的class值要特别注意。
    抽取可重用的部件,注意层叠样式表的“优先级”。

    21.为什么要使用CSS sprites
    CSS Sprites其实就是把网页中一些背景图片整合到一张图片文件中,再利用CSS的“background-image”,“background-position”的组合进行背景定位,这样可以减少很多图片请求的开销,因为请求耗时比较长;请求虽然可以并发,但是如果请求太多会给服务器增加很大的压力。

    22.简述一下src与href的区别

    href 是指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,用于超链接。

    src是指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,例如js脚本,img图片和frame等元素。当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此,类似于将所指向资源嵌入当前标签内。这也是为什么将js脚本放在底部而不是头部。

    23.什么是CSS Hack?

    一般来说是针对不同的浏览器写不同的CSS,就是 CSS Hack。
    IE浏览器Hack一般又分为三种,条件Hack、属性级Hack、选择符Hack(详细参考CSS文档:css文档)。例如:

    // 1、条件Hack <!--[if IE]> <style> .test{color:red;} </style> <![endif]-->

    // 2、属性Hack .test{ color:#0909; /* For IE8+ */ *color:#f00; /* For IE7 and earlier */ _color:#ff0; /* For IE6 and earlier */ }

    // 3、选择符Hack * html .test{color:#090;} /* For IE6 and earlier */ * + html .test{color:#ff0;} /* For IE7 */

    24.px和em的区别

    px和em都是长度单位,区别是,px的值是固定的,指定是多少就是多少,计算比较容易。em得值不是固定的,并且em会继承父级元素的字体大小。
        浏览器的默认字体高都是16px。所以未经调整的浏览器都符合: 1em=16px。那么12px=0.75em, 10px=0.625em

    JS:

    1. 介绍js的基本数据类型
    Undefined、Null、Boolean、Number、String

    数据类型:2大类:*原始类型*的值和*引用类型*的对象  

        原始类型:值直接保存在变量本地的类型(值为一个,而且不能特别复杂)

         原始类型5类:Number  String   Boolean  undefined  null

           引用类型:值没有直接保存在变量本地的类型

                     变量中只保存指向实际数据所在位置的地址值

    2.js有哪些内置对象?
    数据封装类对象:Object、Array、Boolean、Number 和 String
    其他对象:Function、Arguments、Math、Date、RegExp、Error

    3.this对象的理解
    this总是指向函数的直接调用者(而非间接调用者);
    如果有new关键字,this指向new出来的那个对象;
    在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window;

    4.谈谈This对象的理解。
    this是js的一个关键字,随着函数使用场合不同,this的值会发生变化。
    但是有一个总原则,那就是this指的是调用函数的那个对象。
    this一般情况下:是全局对象Global。 作为方法调用,那么this就是指这个对象

    5.eval是做什么的?
    它的功能是把对应的字符串解析成JS代码并运行;
    应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)。
    由JSON字符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')');

    6.JavaScript的typeof返回哪些数据类型
    Object number function boolean underfind;

    7.例举3种强制类型转换和2种隐式类型转换?
    强制(parseInt,parseFloat,number)隐式(== – ===);

    8.split() join() 的区别
    前者是切割成数组的形式,后者是将数组转换成字符串

    9.数组方法pop() push() unshift() shift()
    Push()尾部添加 pop()尾部删除
    Unshift()头部添加 shift()头部删除

    10.IE和DOM事件流的区别
    执行顺序不一样、
    参数不一样
    事件加不加on
    this指向问题

    11.IE和标准下有哪些兼容性的写法
       Var ev = ev || window.event
       document.documentElement.clientWidth || document.body.clientWidth
       Var target = ev.srcElement||ev.target

    12.”==”和“===”的不同
       前者会自动转换类型,后者不会

     

    13.DOM怎样添加、移除、移动、复制、创建和查找节点

    // 创建新节点

    createDocumentFragment()    //创建一个DOM片段

    createElement()   //创建一个具体的元素

    createTextNode()   //创建一个文本节点

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

    appendChild()

    removeChild()

    replaceChild()

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

    // 查找

    getElementsByTagName()    //通过标签名称

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

    getElementById()    //通过元素Id,唯一性

    14.null和undefined的区别?
    null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。
    undefined:
    (1)变量被声明了,但没有赋值时,就等于undefined。
    (2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
    (3)对象没有赋值的属性,该属性的值为undefined。
    (4)函数没有返回值时,默认返回undefined。
    null:
    (1) 作为函数的参数,表示该函数的参数不是对象。
    (2) 作为对象原型链的终点。

    15.new操作符具体干了什么呢?
    (1)创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
    (2)属性和方法被加入到 this 引用的对象中。
    (3)新创建的对象由 this 所引用,并且最后隐式的返回 this 。

    16.js延迟加载的方式有哪些?

    defer和async、动态创建DOM方式(创建script,插入到DOM中,加载完毕后callBack)、按需异步载入js
    17.call() 和 apply() 的区别和作用?

    call vs apply: 都是:在调用方法时,修改当前调用方法的对象

           差别:传入参数的形式:

             xxx.call(obj,值1,值2,值3....)         

         xxx.apply(obj,[值1,值2,值3....])

       apply()函数有两个参数:第一个参数是上下文,第二个参数是参数组成的数组。如果上下文是null,则使用全局对象代替。
       如:function.apply(this,[1,2,3]);
       call()的第一个参数是上下文,后续是实例传入的参数序列。
       如:function.call(this,1,2,3);

    详解:

    call方法:

    语法:call(thisObj,Object)

    定义:调用一个对象的一个方法,以另一个对象替换当前对象。

    说明:

    call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

    如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

    apply方法:

    语法:apply(thisObj,[argArray])

    定义:应用某一对象的一个方法,用另一个对象替换当前对象。

    说明:

    如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。

    如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

    18.什么是闭包?

    闭包:反复使用局部变量,且保证局部变量不被污染的结构

          何时使用:希望反复使用局部变量,且保证不被污染时

           缺点:比普通函数占用更多的内存空间(外层函数的AO)

       如何创建:3步:

            1. 外层函数封装受保护的局部变量

            2. 外层函数,返回一个操作受保护的局部变量的内层函数对象

            3. 全局由变量调用并保存了外层函数返回的内层函数对象

            结果:只有内层函数有权操作受保护的局部变量

    19.说说你对闭包的理解

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

    20.闭包有三个特性:

    1.函数嵌套函数

    2.内层函数必须使用了外层函数的局部变量

    3.外层函数将内层函数返回到外部,可在外部调用

    判断闭包输出结果:

        1. 找首保护的局部变量

        2. 外层函数被调用几次,就创建了几个受保护的变量副本。

        3. 同一次外层函数调用返回的内层函数,总使用统一个局部变量

    21.栈和队列的区别?

    栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的。
    队列先进先出,栈先进后出。
    栈只允许在表尾一端进行插入和删除,而队列只允许在表尾一端进行插入,在表头一端进行删除

    22.栈和堆的区别?

    栈区(stack)—   由编译器自动分配释放   ,存放函数的参数值,局部变量的值等。
    堆区(heap)   —   一般由程序员分配释放,   若程序员不释放,程序结束时可能由OS回收。
    堆(数据结构):堆可以被看成是一棵树,如:堆排序;
    栈(数据结构):一种先进后出的数据结构。

    23.defer和async

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

    24.document.write()的用法

    document.write()方法可以用在两个方面:页面载入过程中用实时脚本创建页面内容,以及用延时脚本创建本窗口或新窗口的内容。

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

    25.git fetch和git pull的区别

    git pull:相当于是从远程获取最新版本并merge到本地

    git fetch:相当于是从远程获取最新版本到本地,不会自动merge

    26.attribute和property的区别是什么?

    attributedom元素在文档中作为html标签拥有的属性;

    property就是dom元素在js中作为对象拥有的属性。

    所以:

    对于html的标准属性来说,attributeproperty是同步的,是会自动更新的,

    但是对于自定义的属性来说,他们是不同步的,

    27.请解释一下 JavaScript 的同源策略。

    概念:同源策略是客户端脚本(尤其是Javascript)的重要的安全度量标准。它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。

    这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。

    指一段脚本只能读取来自同一来源的窗口和文档的属性。

    说一下什么是JavaScript的同源策略?
    一段脚本只能读取来自于同一来源的窗口和文档的属性,这里的同一来源指的是主机名、协议和端口号的组合代码相关的问题。

    28.为什么要有同源限制?

    我们举例说明:比如一个黑客程序,他利用Iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript读取到你的表单中input中的内容,这样用户名,密码就轻松到手了。

    缺点:

    现在网站的JS 都会进行压缩,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge 后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节。

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

        1. 我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事件。是可以被 JavaScript 侦测到的行为。
    2. 事件处理机制:IE是事件冒泡、firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件。
        3. `ev.stopPropagation()`;注意旧ie的方法 `ev.cancelBubble = true`;

    30.事件委托是什么
    让利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行!

    31.请解释什么是事件代理

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

    32.谈一谈JavaScript作用域链

    作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的。
        当执行一段JavaScript代码(全局代码或函数)时,JavaScript引擎会创建为其创建一个作用域又称为执行上下文(Execution Context),在页面加载后会首先创建一个全局的作用域,然后每执行一个函数,会建立一个对应的作用域,从而形成了一条作用域链。每个作用域都有一条对应的作用域链,链头是全局作用域,链尾是当前函数作用域。
        作用域链的作用是用于解析标识符,当函数被创建时(不是执行),会将this、arguments、命名参数和该函数中的所有局部变量添加到该当前作用域中,当JavaScript需要查找变量X的时候(这个过程称为变量解析),它首先会从作用域链中的链尾也就是当前作用域进行查找是否有X属性,如果没有找到就顺着作用域链继续查找,直到查找到链头,也就是全局作用域链,仍未找到该变量的话,就认为这段代码的作用域链上不存在x变量,并抛出一个引用错误(ReferenceError)的异常。

    33.如何理解JavaScript原型链
    JavaScript中的每个对象都有一个prototype属性,我们称之为原型,而原型的值也是一个对象,因此它也有自己的原型,这样就串联起来了一条原型链,原型链的链头是object,它的prototype比较特殊,值为null。
    原型链的作用是用于对象继承,函数A的原型属性(prototype property)是一个对象,当这个函数被用作构造函数来创建实例时,该函数的原型属性将被作为原型赋值给所有对象实例,比如我们新建一个数组,数组的方法便从数组的原型上继承而来。
    当访问对象的一个属性时, 首先查找对象本身, 找到则返回; 若未找到, 则继续查找其原型对象的属性(如果还找不到实际上还会沿着原型链向上查找, 直至到根). 只要没有被覆盖的话, 对象原型的属性就能在所有的实例中找到,若整个原型链未找到则返回undefined

    34.JavaScript原型,原型链 ? 有什么特点?
    (1)原型对象也是普通的对象,是对象一个自带隐式的 __proto__ 属性,原型也有可能有自己的原型,如果一个原型对象的原型不为null的话,我们就称之为原型链。
    (2)原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链。

    35. 对面向对象的理解

        什么是面向对象?面向对象就是在程序中,用一个对象描述现实中一个事物

        为什么使用面向对象?因为面向对象更接近于人的思维方式,更便于代码维护。

        面向对象三大特点:封装,继承,多态

            封装:讲现实中一个事物的属性和方法,集中定义在程序中的一个对象中。

              为什么要封装:更接近于人的想法,便于代码维护。

            继承:父对象中的成员,子对象可以直接使用。

              为什么要继承:代码重用!节约内存空间

            多态:同一样东西,在不同情况下表现出不同的状态。

            多态方式:重写,重载:

              重载:多个同名方法,但参数列表不同,调用时,可根据传入参数的不同,动态决定调用何种匹配的方法。

                 为什么使用重载:便于调用,减少调用者负担。

                 js语法不支持重载,但可用arguments对象模拟重载效果。

              重写:子对象觉得父对象的成员不好用,可在本地定义与父对象同名的成员,覆盖父对象的成员

                 为什么使用重写:专门定义子对象与父对象之间的差异。

    35.JavaScript如何实现继承?
    构造继承
    原型继承
    实例继承
    拷贝继承
    原型prototype机制或apply和call方法去实现较简单,建议使用构造函数与原型混合方式。
            function Parent(){
                this.name = 'wang';
            }

            function Child(){
                this.age = 28;
            }
            Child.prototype = new Parent();//继承了Parent,通过原型
            var demo = new Child();
            alert(demo.age);
            alert(demo.name);//得到被继承的属性

    36.javascript里面的继承怎么实现,如何避免原型链上面的对象共享
    用构造函数和原型链的混合模式去实现继承,避免对象共享可以参考经典的extend()函数,很多前端框架都有封装的,就是用一个空函数当做中间变量

    37.js继承方式及其优缺点

    ①   原型链继承的缺点

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

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

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

    ③   组合式继承

    组合式继承是比较常用的一种继承方法,其背后的思路是 使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。

    38.Javascript垃圾回收方法

    ①  标记清除(mark and sweep)

    这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。

    垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了

    ②   引用计数(reference counting)
        在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。

    在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 
        也就是说只要涉及BOM及DOM就会出现循环引用问题。

    39.用过哪些设计模式?

    ①   工厂模式:

    主要好处就是可以消除对象间的耦合,通过使用工程方法而不是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());
    2.直接将属性和方法赋值给 this 对象;
    3.没有 renturn 语句。

    40.javascript对象的几种创建方式

    1,工厂模式
    2,构造函数模式
    3,原型模式
    4,混合构造函数和原型模式
    5,动态原型模式
    6,寄生构造函数模式
    7,稳妥构造函数模式
    41.Javascript中callee和caller的作用?

    caller是返回一个对函数的引用,该函数调用了当前函数;

    callee是返回正在被执行的function函数,也就是所指定的function对象的正文。

    42.请描述一下cookies,sessionStorage和localStorage的区别

    sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

    web storage和cookie的区别

    Web Storage的概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。
        除此之外,Web Storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生。

    43.跨域请求资源的方法有哪些?

    由于浏览器同源策略,凡是发送请求 URL 的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。

    (1)JSONP(jsonp 跨域 get 请求) 

    这种方式主要是通过动态创建一个 script 标签,浏览器对 script 的资源引用没有同源限制,同时资源加载到页面后会立即执行;(创建 script 标签向不同域提交 http 请求的不会被拒绝的方法,jsonp 标签的 src 属性是没有跨域限制的)

    实际项目中 JSONP 通常用来获取 json 格式数据,这时前后端通常约定一个参数 callback,该参数的值,就是处理返回数据的函数名称;

    缺点:这种方式无法发送 post 请求,另外要确定 jsonp 的请求是否失败并不容易,大多数框架的实现都是结合超时时间来判断。

    (2)proxy 代理

    这种方式首先将请求发送给后台服务器,通过服务器来发送请求,然后将请求的结果传递给前端;

    需要注意的是如果你代理的是 https 协议的请求,那么你的 proxy 首先需要信任该证书或者忽略证书检查,否则你的请求无法成功。

    (3)cors

    当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求头 origin,后台进行一系列处理,如果确定接受请求则在返回结果加入一个响应头 Access-Control-Allow-Origin;浏览器判断该响应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据; 

    post 请求的 content-type 不是常规的三个:application/x-www-form-urlencoded(使用 HTTP 的 post 方式提交表单)、multipart/form-data(同上,但主要用于表单提交时伴随文件上传的场合)、text/plain(纯文本)

    post 请求的 payload 为 text/html 

    payload 指在 http 中,应该是 post 请求时所携带的有效数据;

    有一种跨域需要特别注意就是 https 协议下发送 https 请求,除了使用 proxy 代理外其他方法都无解,会被浏览器直接 block 掉。

    44.浅谈MVC,MVP和 MVVM

     1.MVC

        ①.MVC模式的意思是,软件可以分成三个部分。

    视图(View):用户界面。

    控制器(Controller):业务逻辑

    模型(Model):数据保存

             各部分之间通信方式如下:

     View 传送指令到 Controller

                Controller 完成业务逻辑后,要求 Model 改变状态

    Model 将新的数据发送到 View,用户得到反馈

    ②.互动模式

    接受用户指令时,MVC 可以分成两种方式。一种是通过 View 接受指令,传递给 Controller。

    另一种是直接通过controller接受指令。

    ③   实例:Backbone

    实际项目往往采用更灵活的方式,以 Backbone.js 为例。

    1. 用户可以向 View 发送指令(DOM 事件),再由 View 直接要求 Model 改变状态。

    2. 用户也可以直接向 Controller 发送指令(改变 URL 触发 hashChange 事件),再由 Controller 发送给 View。

    3. Controller 非常薄,只起到路由的作用,而 View 非常厚,业务逻辑都部署在 View。所以,Backbone 索性取消了 Controller,只保留一个 Router(路由器) 。

    2、MVP

    MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。

    1. 各部分之间的通信,都是双向的。

    2. View 与 Model 不发生联系,都通过 Presenter 传递。

    3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

    3、MVVM

    MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。

    唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。Angular 和 Ember 都采用这种模式。

    1.ajax的原理

    在旧的交互方式中,由用户触发一个HTTP请求到服务器,服务器对其进行处理后再返回一个新的HTHL页到客户端, 每当服务器处理客户端提交的请求时,客户都只能空闲等待,并且哪怕只是一次很小的交互、只需从服务器端得到很简单的一个数据,都要返回一个完整的HTML页,而用户每次都要浪费时间和带宽去重新读取整个页面。而使用Ajax后用户从感觉上几乎所有的操作都会很快响应没有页面重载(白屏)的等待。

    Ajax的原理简单来说是在用户和服务器之间加了—个中间层(AJAX引擎),通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。使用户操作与服务器响应异步化。这其中最关键的一步就是从服务器获得请求数据。

    Ajax的过程只涉及JavaScript、XMLHttpRequest和DOM。XMLHttpRequest是ajax的核心机制,它是在IE5中首先引入的,是一种支持异步请求的技术。简单的说,也就是javascript可以及时向服务器提出请求和处理响应,而不阻塞用户。达到无刷新的效果。

    2.简述同步和异步的区别

    同步是阻塞模式,异步是非阻塞模式。
    同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;
    异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。

     

    1.创建ajax过程

    (1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.

    (2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.

    (3)设置响应HTTP请求状态变化的函数.

    (4)发送HTTP请求.

    (5)获取异步调用返回的数据.

    (6)使用JavaScript和DOM实现局部刷新.

            var xmlHttp = new XMLHttpRequest();

            xmlHttp.open('GET','demo.php','true');

            xmlHttp.send()

            xmlHttp.onreadystatechange = function(){

               if(xmlHttp.readyState === 4 & xmlHttp.status === 200){   }

        }

    2.ajax的缺点和在IE下的问题?

    ①ajax的缺点

      1、ajax不支持浏览器back按钮。
      2、安全问题 AJAX暴露了与服务器交互的细节。
      3、对搜索引擎的支持比较弱。
      4、破坏了程序的异常机制。
      5、不容易调试。

    ②IE缓存问题

    在IE浏览器下,如果请求的方法是GET,并且请求的URL不变,那么这个请求的结果就会被缓存。解决这个问题的办法可以通过实时改变请求的URL,只要URL改变,就不会被缓存,可以通过在URL末尾添加上随机的时间戳参数('t'= + new Date().getTime())

    或者:open('GET','demo.php?rand=+Math.random()',true);//

    • 3.ajax 有那些优缺点?如何解决跨域问题?
      (Q1)
      优点:
      (1)通过异步模式,提升了用户体验.
      (2)优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用.
      (3)Ajax在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。
      (4)Ajax可以实现动态不刷新(局部刷新)
      缺点:
      (1)安全问题 AJAX暴露了与服务器交互的细节。
      (2)对搜索引擎的支持比较弱。
      (3)不容易调试。
      (Q2)jsonp、 iframe、window.name、window.postMessage、服务器上设置代理页面。

    4..GET和POST的区别,何时使用POST?
         GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在2000个字符
         POST:一般用于修改服务器上的资源,对所发送的信息没有限制。
         GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值,
        也就是说Get是通过地址栏来传值,而Post是通过提交表单来传值。
        然而,在以下情况中,请使用 POST 请求:
        无法使用缓存文件(更新服务器上的文件或数据库)
        向服务器发送大量数据(POST 没有数据量限制)
        发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

    5.ajax请求时,如何解释json数据
      使用eval parse,鉴于安全性考虑 使用parse更靠谱;

    6.异步加载和延迟加载

    1.异步加载的方案: 动态插入script标签
    2.通过ajax去获取js代码,然后通过eval执行
    3.script标签上添加defer或者async属性
    4.创建并插入iframe,让它异步执行js
    5.延迟加载:有些 js 代码并不是页面初始化的时候就立刻需要的,而稍后的某些情况才需要的。

    7.Ajax请求的页面历史记录状态问题

    可以通过锚点来记录状态,location.hash。让浏览器记录Ajax请求时页面状态的变化。

    还可以通过HTML5history.pushState,来实现浏览器地址栏的无刷新改变

    HTTP&JSON:

    一次完整的HTTP事务是怎样的一个过程?

    基本流程:

    a. 域名解析

    b. 发起TCP的3次握手

    c. 建立TCP连接后发起http请求

    d. 服务器端响应http请求,浏览器得到html代码

    e. 浏览器解析html代码,并请求html代码中的资源

    f. 浏览器对页面进行渲染呈现给用户

    1.HTTP状态码知道哪些?
    100  Continue  继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
    200  OK   正常返回信息
    201  Created  请求成功并且服务器创建了新的资源
    202  Accepted  服务器已接受请求,但尚未处理
    301  Moved Permanently  请求的网页已永久移动到新位置。
    302 Found  临时性重定向。
    303 See Other  临时性重定向,且总是使用 GET 请求新的 URI。
    304  Not Modified  自从上次请求后,请求的网页未修改过。
    400 Bad Request  服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
    401 Unauthorized  请求未授权。
    403 Forbidden  禁止访问。
    404 Not Found  找不到如何与 URI 相匹配的资源。
    500 Internal Server Error  最常见的服务器端错误。
    503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。

    2.HTTP和HTTPS

    HTTP协议通常承载于TCP协议之上,在HTTPTCP之间添加一个安全协议层(SSLTSL),这个时候,就成了我们常说的HTTPS。

    默认HTTP的端口号为80,HTTPS的端口号为443。

    3.为什么HTTPS安全

    因为网络请求需要中间有很多的服务器路由器的转发。中间的节点都可能篡改信息,而如果使用HTTPS,密钥在你和终点站才有。https之所以比http安全,是因为他利用ssl/tls协议传输。它包含证书,卸载,流量转发,负载均衡,页面适配,浏览器适配,refer传递等。保障了传输过程的安全性

    4.关于Http 2.0 你知道多少?

    HTTP/2引入了“服务端推(server push)”的概念,它允许服务端在客户端需要数据之前就主动地将数据发送到客户端缓存中,从而提高性能。

    HTTP/2提供更多的加密支持

    HTTP/2使用多路技术,允许多个消息在一个连接上同时交差。

    它增加了头压缩(header compression),因此即使非常小的请求,其请求和响应的header都只会占用很小比例的带宽。

    5.一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?
    (1)查找浏览器缓存
    (2)DNS解析、查找该域名对应的IP地址、重定向(301)、发出第二个GET请求
    (3)进行HTTP协议会话
    (4)客户端发送报头(请求报头)
    (5)服务器回馈报头(响应报头)
    (6)html文档开始下载
    (7)文档树建立,根据标记请求所需指定MIME类型的文件
    (8)文件显示

    6.JSON 的了解?
    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小。
    格式:采用键值对,例如:{'age':'12', 'name':'back'}

    7.XMLJSON的区别?

    (1).数据体积方面。

    JSON相对于XML来讲,数据的体积小,传递的速度更快些。

    (2).数据交互方面。

    JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互。

    (3).数据描述方面。

    JSON对数据的描述性比XML较差。

    (4).传输速度方面。

    JSON的速度要远远快于XML。

    8.如何解决跨域问题

    ①   JSONP:

    原理是:动态插入script标签,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。

    由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求。

    优点是兼容性好,简单易用,支持浏览器与服务器双向通信。缺点是只支持GET请求。

    JSONPjson+padding(内填充),顾名思义,就是把JSON填充到一个盒子里

    <script>

        function createJs(sUrl){

            var oScript = document.createElement('script');

            oScript.type = 'text/javascript';

            oScript.src = sUrl;

            document.getElementsByTagName('head')[0].appendChild(oScript);

        }

        createJs('jsonp.js');

        box({

           'name': 'test'

        });

        function box(json){

            alert(json.name);

        }

    </script>

       

    ②   CORS

    服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问

    ③   通过修改document.domain来跨子域

    将子域和主域的document.domain设为同一个主域.前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域

    主域相同的使用document.domain

    ④   使用window.name来进行跨域

    window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的

    ⑤   使用HTML5中新引进的window.postMessage方法来跨域传送数据

    还有flash、在服务器上设置代理页面等跨域方式。个人认为window.name的方法既不复杂,也能兼容到几乎所有浏览器,这真是极好的一种跨域方法。

    其他:

    1. 常用那几种浏览器测试?有哪些内核(Layout Engine)?
       (1)
    浏览器:IEChromeFireFoxSafariOpera
       (2)
    内核:TridentGeckoPrestoWebkit

    2.页面的哪些浏览器你测试过,分别内核是什么?

    IE(IE内核),火狐(Gecko),谷歌(webkit),opera(presto)

    3.常见的浏览器内核有哪些?
    Trident内核:IE,MaxThon,TT,The World,360,搜狗浏览器等。[又称MSHTML]
    Gecko
    内核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey
    Presto
    内核:Opera7及以上。 [Opera内核原为:Presto,现为:Blink;]
    Webkit
    内核:Safari,Chrome等。 [ Chrome的:BlinkWebKit的分支)]

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

    5.如何实现浏览器内多个标签页之间的通信?
    WebSocket
    SharedWorker
    也可以调用localstorgecookies等本地存储方式。
    localstorge
    另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件,我们通过监听事件,控制它的值来进行页面信息通信。
    注意quirksSafari 在无痕模式下设置localstorge值时会抛出 QuotaExceededError 的异常。

    6.web标准以及w3c的理解和认识

    :标签闭合,标签小写,不乱嵌套,提高搜索机器人搜索几率。使用外链cssjs脚本,结构行为表现分离,内容能被更多广泛的设备所访问,更少的代码和组件,容易维护,改版方便,不需要变动页面内容。

    7.前端页面有哪三层构成,分别是什么,作用是什么?

    结构层:html 表示层:css 行为层:js

    8.线程与进程的区别
    一个程序至少有一个进程,一个进程至少有一个线程. 
    线程的划分尺度小于进程,使得多线程程序的并发性高。 
    另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 
    线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 
    从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

    9.BFC规范的理解?

    BFC,块级格式化上下文,一个创建了新的BFC的盒子是独立布局的,盒子里面的子元素的样式不会影响到外面的元素。在同一个BFC中的两个毗邻的块级盒在垂直方向(和布局方向有关系)的margin会发生折叠。
       W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行布局,以及与其他元素的关系和相互作用。

    10.请描述一下 cookiessessionStorage localStorage 的区别?
    cookie
    在浏览器和服务器间来回传递。 sessionStoragelocalStorage不会
    sessionStorage
    localStorage的存储空间更大;
    sessionStorage
    localStorage有更多丰富易用的接口;
    sessionStorage
    localStorage各自独立的存储空间;

    详细解释:

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

    11.常见web安全及防护原理

      sql注入原理

    就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。

    总的来说有以下几点:

              1.永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双"-"进行转换等。

              2.永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。

              3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。

    4.不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。

      XSS原理及防范

    Xss(cross-site scripting)攻击指的是攻击者往Web页面里插入恶意 html标签或者JavaScript代码。比如:攻击者在论坛中放一个看似安全的链接,骗取用户点击后,窃取cookie中的用户私密信息;或者攻击者在论坛中加一个恶意表单,当用户提交表单的时候,却把信息传送到攻击者的服务器中,而不是用户原本以为的信任站点。

      XSS防范方法

    首先代码里对用户输入的地方和变量都需要仔细检查长度和对”<”,”>”,”;”,”’”等字符做过滤;其次任何内容写到页面之前都必须加以encode,避免不小心把html tag 弄出来。这一个层面做好,至少可以堵住超过一半的XSS 攻击。

    首先,避免直接在cookie 中泄露用户隐私,例如email、密码等等。

    其次,通过使cookie 和系统ip 绑定来降低cookie 泄露后的危险。这样攻击者得到的cookie 没有实际价值,不可能拿来重放。

    如果网站不需要再浏览器端对cookie 进行操作,可以在Set-Cookie 末尾加上HttpOnly 来防止javascript 代码直接获取cookie 

    尽量采用POST 而非GET 提交表单

      XSSCSRF有什么区别吗?

    XSS是获取信息,不需要提前知道其他用户页面的代码和数据包。CSRF是代替用户完成指定的动作,需要知道其他用户页面的代码和数据包。

    要完成一次CSRF攻击,受害者必须依次完成两个步骤:

    登录受信任网站A,并在本地生成Cookie

    在不登出A的情况下,访问危险网站B

      CSRF的防御

    服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。

    通过验证码的方法

    12.Web Worker webSocket

    worker主线程:

        1.通过 worker = new Worker( url ) 加载一个JS文件来创建一个worker,同时返回一个worker实例。

        2.通过worker.postMessage( data ) 方法来向worker发送数据。

        3.绑定worker.onmessage方法来接收worker发送过来的数据。

    4.可以使用 worker.terminate() 来终止一个worker的执行。

    WebSocketWeb应用程序的传输协议,它提供了双向的,按序到达的数据流。他是一个Html5协议,WebSocket的连接是持久的,他通过在客户端和服务器之间保持双工连接,服务器的更新可以被及时推送给客户端,而不需要客户端以一定时间间隔去轮询。

    13.谈谈你对webpack的看法

    WebPack 是一个模块打包工具,你可以使用WebPack管理你的模块依赖,并编绎输出模块们所需的静态文件。它能够很好地管理、打包Web开发中所用到的HTMLJavaScriptCSS以及各种静态文件(图片、字体等),让开发过程更加高效。对于不同类型的资源,webpack有对应的模块加载器。webpack模块打包器会分析模块间的依赖关系,最后 生成了优化且合并后的静态资源。

    webpack的两大特色:

             1.code splitting(可以自动完成)
             2.loader 可以处理各种类型的静态文件,并且支持串联操作

    webpack 是以commonJS的形式来书写脚本滴,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。

    webpack具有requireJsbrowserify的功能,但仍有很多自己的新特性:

    1. CommonJS AMD ES6的语法做了兼容

    2. jscss、图片等资源文件都支持打包

    3. 串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScriptES6的支持

    4. 有独立的配置文件webpack.config.js

    5. 可以将代码切割成不同的chunk,实现按需加载,降低了初始化时间

    6. 支持 SourceUrls SourceMaps,易于调试

    7. 具有强大的Plugin接口,大多是内部插件,使用起来比较灵活

    8.webpack 使用异步 IO 并具有多级缓存。这使得 webpack 很快且在增量编译上更加快

    14.WEB应用从服务器主动推送Data到客户端有那些方式?

    Javascript数据推送

    Commet:基于HTTP长连接的服务器推送技术

    基于WebSocket的推送方案

    SSEServer-Send Event):服务器推送数据新方式

    15.说说你对AMDCommonjs的理解

    CommonJS是服务器端模块的规范,Node.js采用了这个规范。CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD规范则是非同步加载模块,允许指定回调函数。

    AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exportsexports的属性赋值来达到暴露模块对象的目的。

    16.如何删除一个cookie

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

    var date = newDate();

    date.setDate(date.getDate() - 1);//真正的删除

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

      expires的设置

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

    17.请你谈谈Cookie的弊端

    cookie虽然在持久保存客户端数据提供了方便,分担了服务器存储的负担,但还是有很多局限性的。

    第一:每个特定的域名下最多生成20cookie

    1.IE6或更低版本最多20cookie
    2.IE7和之后的版本最后可以有50cookie
    3.Firefox最多50cookie
    4.chromeSafari没有做硬性限制

    IEOpera 会清理近期最少使用的cookieFirefox会随机清理cookie

    cookie的最大大约为4096字节,为了兼容性,一般不能超过4095字节。

    IE 提供了一种存储可以持久化用户数据,叫做userdata,从IE5.0就开始支持。每个数据最多128K,每个域名下最多1M。这个持久化数据放在缓存中,如果缓存没有清理,那么会一直存在。

      优点:极高的扩展性和可用性

    1.通过良好的编程,控制保存在cookie中的session对象的大小。
    2.通过加密和安全传输技术(SSL),减少cookie被破解的可能性。
    3.只在cookie中存放不敏感数据,即使被盗也不会有重大损失。
    4.控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie

    ②缺点:

    1.`Cookie`数量和长度的限制。每个domain最多只能有20cookie,每个cookie长度不能超过4KB,否则会被截掉.
    2.安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。
    3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。

    18.浏览器本地存储

    在较高版本的浏览器中,js提供了sessionStorageglobalStorage。在HTML5中提供了localStorage来取代globalStorage

    html5中的Web Storage包括了两种存储方式:sessionStoragelocalStorage

    sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。

    localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

    你所了解到的Web攻击技术:

    1XSSCross-Site Scripting,跨站脚本攻击):指通过存在安全漏洞的Web网站注册用户的浏览器内运行非法的HTML标签或者JavaScript进行的一种攻击。
       
    2SQL注入攻击
       
    3CSRFCross-Site Request Forgeries,跨站点请求伪造):指攻击者通过设置好的陷阱,强制对已完成的认证用户进行非预期的个人信息或设定信息等某些状态更新。

     

    19.web storagecookie的区别

    Web Storage的概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。

    除此之外,Web Storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookiegetCookie

    但是cookie也是不可以或缺的:cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生

    浏览器的支持除了IE及以下不支持外,其他标准浏览器都完全支持(ieFF需在web服务器里运行),值得一提的是IE总是办好事,例如IE7IE6中的userData其实就是javascript本地存储的解决方案。通过简单的代码封装可以统一到所有的浏览器都支持web storage

    localStoragesessionStorage都具有相同的操作方法,例如setItemgetItemremoveItem

    20.cookie session 的区别:

        1cookie数据存放在客户的浏览器上,session数据放在服务器上。
        2cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
           考虑到安全应当使用session
        3session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
            考虑到减轻服务器性能方面,应当使用COOKIE
        4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20cookie
    5、所以个人建议:
           将登陆信息等重要信息存放为SESSION
           其他信息如果需要保留,可以放在COOKIE

    21.哪些操作会造成内存泄漏?

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

    22.对前端模块化的认识

    AMD  RequireJS 在推广过程中对模块定义的规范化产出。

    CMD  SeaJS 在推广过程中对模块定义的规范化产出。

    AMD 是提前执行,CMD 是延迟执行。

    AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exportsexports的属性赋值来达到暴露模块对象的目的。

    CMD模块方式

    define(function(require, exports, module) {

                    // 模块代码

        });

    23.你有哪些性能优化的方法?
    1) 减少http请求次数:CSS Sprites, JSCSS源码压缩、图片大小控制合适;网页GzipCDN托管,data缓存 ,图片服务器。
    2) 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
    3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
    4) 当需要设置的样式很多时设置className而不是直接操作style
    5) 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
    6) 避免使用CSS Expressioncss表达式)又称Dynamic properties(动态属性)
    7) 图片预加载,将样式表放在顶部,将脚本放在底部  加上时间戳。

    24.谈谈性能优化问题

    代码层面:避免使用css表达式,避免使用高级选择器,通配选择器。

    缓存利用:缓存Ajax,使用CDN,使用外部jscss文件以便缓存,添加Expires头,服务端配置Etag,减少DNS查找等

    请求数量:合并样式和脚本,使用css图片精灵,初始首屏之外的图片资源按需加载,静态资源延迟加载。

    请求带宽:压缩文件,开启GZIP

       代码层面的优化

    1.hash-table来优化查找

    2.少用全局变量

    3.innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能

    4.setTimeout来避免页面失去响应

    5.缓存DOM节点查找的结果

    6.避免使用CSS Expression

    7.避免全局查询

    8.避免使用with(with会创建自己的作用域,会增加作用域链长度)

    9.多个变量声明合并

    10.避免图片和iFrame等的空Src。空Src会重新加载当前页面,影响速度和效率

    11.尽量避免写在HTML标签中写Style属性

    25.移动端性能优化

    1.尽量使用css3动画,开启硬件加速。

    2.适当使用touch事件代替click事件。

    3.避免使用css3渐变阴影效果。

    4.可以用transform: translateZ(0)来开启硬件加速。

    5.不滥用FloatFloat在渲染时计算量比较大,尽量减少使用

    6.不滥用Web字体。Web字体需要下载,解析,重绘当前页面,尽量减少使用。

    7.合理使用requestAnimationFrame动画代替setTimeout

    8.CSS中的属性(CSS3 transitionsCSS3 3D transformsOpacityCanvasWebGLVideo)会触发GPU渲染,请合理使用。过渡使用会引发手机过耗电增加

    9.PC端的在移动端同样适用

    26.什么是Etag

    当发送一个服务器请求时,浏览器首先会进行缓存过期判断。浏览器根据缓存过期时间判断缓存文件是否过期。

    情景一:若没有过期,则不向服务器发送请求,直接使用缓存中的结果,此时我们在浏览器控制台中可以看到 200 OK(from cache) ,此时的情况就是完全使用缓存,浏览器和服务器没有任何交互的。

    情景二:若已过期,则向服务器发送请求,此时请求中会带上①中设置的文件修改时间,和Etag

    然后,进行资源更新判断。服务器根据浏览器传过来的文件修改时间,判断自浏览器上一次请求之后,文件是不是没有被修改过;根据Etag,判断文件内容自上一次请求之后,有没有发生变化

    情形一:若两种判断的结论都是文件没有被修改过,则服务器就不给浏览器发index.html的内容了,直接告诉它,文件没有被修改过,你用你那边的缓存吧—— 304 Not Modified,此时浏览器就会从本地缓存中获取index.html的内容。此时的情况叫协议缓存,浏览器和服务器之间有一次请求交互。

    情形二:若修改时间和文件内容判断有任意一个没有通过,则服务器会受理此次请求,之后的操作同①

        只有get请求会被缓存,post请求不会

    27.ETag应用:

    Etag由服务器端生成,客户端通过If-Match或者说If-None-Match这个条件判断请求来验证资源是否修改。常见的是使用If-None-Match。请求一个文件的流程可能如下:

    ====第一次请求===

    1.客户端发起 HTTP GET 请求一个文件;
    2.服务器处理请求,返回文件内容和一堆Header,当然包括Etag(例如"2e681a-6-5d044840")(假设服务器支持Etag生成和已经开启了Etag).状态码200

    ====第二次请求===

    客户端发起 HTTP GET 请求一个文件,注意这个时候客户端同时发送一个If-None-Match头,这个头的内容就是第一次请求时服务器返回的Etag2e681a-6-5d0448402.服务器判断发送过来的Etag和计算出来的Etag匹配,因此If-None-MatchFalse,不返回200,返回304,客户端继续使用本地缓存;流程很简单,问题是,如果服务器又设置了Cache-Control:max-ageExpires呢,怎么办

    答案是同时使用,也就是说在完全匹配If-Modified-SinceIf-None-Match即检查完修改时间和Etag之后,

    服务器才能返回304.(不要陷入到底使用谁的问题怪圈)

    28.为什么使用Etag请求头?

    Etag 主要为了解决 Last-Modified 无法解决的一些问题。

    29.ExpiresCache-Control

    Expires要求客户端和服务端的时钟严格同步。HTTP1.1引入Cache-Control来克服Expires头的限制。如果max-ageExpires同时出现,则max-age有更高的优先级。

        Cache-Control: no-cache, private, max-age=0

        ETag: abcde

        Expires: Thu, 15 Apr 201420:00:00 GMT

        Pragma: private

    Last-Modified: $now // RFC1123 format

    30.ES6的了解

    新增模板字符串(为JavaScript提供了简单的字符串插值功能)、箭头函数(操作符左边为输入的参数,而右边则是进行的操作以及返回的值Inputs=>outputs。)、for-of(用来遍历数据—例如数组中的值。)   arguments对象可被不定参数和默认参数完美代替。ES6promise对象纳入规范,提供了原生的Promise对象。增加了letconst命令,用来声明变量。增加了块级作用域。let命令实际上就增加了块级作用域。ES6规定,var命令和function命令声明的全局变量,属于全局对象的属性;let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。。还有就是引入module模块的概念

    31.你觉得jQueryzepto源码有哪些写的好的地方

    (答案仅供参考)

    jQuery源码封装在一个匿名函数的自执行环境中,有助于防止变量的全局污染,然后通过传入window对象参数,可以使window对象作为局部变量使用,好处是当jQuery中访问window对象的时候,就不用将作用域链退回到顶层作用域了,从而可以更快的访问window对象。同样,传入undefined参数,可以缩短查找undefined时的作用域链。

    (function( window, undefined ) {

             //用一个函数域包起来,就是所谓的沙箱

             //在这里边var定义的变量,属于这个函数域内的局部变量,避免污染全局

             //把当前沙箱需要的外部变量通过函数参数引入进来

             //只要保证参数对内提供的接口的一致性,你还可以随意替换传进来的这个参数

            window.jQuery = window.$ = jQuery;

      })( window );

    jquery将一些原型属性和方法封装在了jquery.prototype中,为了缩短名称,又赋值给了jquery.fn,这是很形象的写法。

    有一些数组或对象的方法经常能使用到,jQuery将其保存为局部变量以提高访问速度。

    jquery实现的链式调用可以节约代码,所返回的都是同一个对象,可以提高代码效率。

    32.如何评价AngularJSBackboneJS

    backbone具有依赖性,依赖underscore.jsBackbone + Underscore + jQuery(or Zepto) 就比一个AngularJS 多出了2 HTTP请求.

    BackboneModel没有与UI视图数据绑定,而是需要在View中自行操作DOM来更新或读取UI数据。AngularJS与此相反,Model直接与UI视图绑定,ModelUI视图的关系,通过directive封装,angularjs内置的通用directive,就能实现大部分操作了,也就是说,基本不必关心ModelUI视图的关系,直接操作Model就行了,UI视图自动更新。

    AngularJSdirective,你输入特定数据,他就能输出相应UI视图。是一个比较完善的前端MVW框架,包含模板,数据双向绑定,路由,模块化,服务,依赖注入等所有功能,模板功能强大丰富,并且是声明式的,自带了丰富的 Angular 指令。

    33.谈谈你对重构的理解

    网站重构:在不改变外部行为的前提下,简化结构、添加可读性,而在网站前端保持一致的行为。也就是说是在不改变UI的情况下,对网站进行优化, 
       
    在扩展的同时保持一致的UI

    对于传统的网站来说重构通常是:
    表格(table)布局改为DIV+CSS
    使网站前端兼容于现代浏览器(针对于不合规范的CSS、如对IE6有效的)
    对于移动平台的优化
    针对于SEO进行优化
    深层次的网站重构应该考虑的方面
    减少代码间的耦合
    让代码保持弹性
    严格按规范编写代码
    设计可扩展的API
    代替旧有的框架、语言(VB)
    增强用户体验
    通常来说对于速度的优化也包含在重构中
    压缩JSCSSimage等前端资源(通常是由服务器来解决)
    程序的性能优化(如数据读写)
    采用CDN来加速资源加载
    对于JS DOM的优化
    HTTP服务器的文件缓存

    34.讲讲304缓存的原理

    服务器首先产生ETag,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其(客户端)缓存。

    304HTTP状态码,服务器用来标识这个文件没修改,不返回内容,浏览器在接收到个状态码后,会使用浏览器已缓存的文件

    客户端请求一个页面(A)。 服务器返回页面A,并在给A加上一个ETag。 客户端展现该页面,并将页面连同ETag一起缓存。 客户再次请求页面A,并将上次请求时服务器返回的ETag一起传递给服务器。 服务器检查该ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304(未修改——Not Modified)和一个空的响应体。

    : 动态主机配置协议,是一种让系统得以连接到网络上,并获取所需要的配置参数手段。

    35.什么是 FOUC(无样式内容闪烁)?你如何来避免 FOUC

    FOUC - Flash Of Unstyled Content 文档样式闪烁

         <style type="text/css" media="all">@import "../fouc.css";</style>

        而引用CSS文件的@import就是造成这个问题的罪魁祸首。IE会先加载整个HTML文档的DOM,然后再去导入外部的CSS文件,因此,在页面DOM加载完成到CSS导入完成中间会有一段时间页面上的内容是没有样式的,这段时间的长短跟网速,电脑速度都有关系。

     解决方法简单的出奇,只要在<head>之间加入一个<link>或者<script>元素就可以了。

    36.说说你对Promise的理解

    依照 Promise/A+ 的定义,Promise 有四种状态:

    pending: 初始状态, fulfilled  rejected.
    fulfilled: 成功的操作.
    rejected: 失败的操作.
    settled: Promise已被fulfilledrejected,且不是pending

    另外, fulfilled  rejected 一起合称 settled

    Promise 对象用来进行延迟(deferred) 和异步(asynchronous ) 计算。

    Promise对象有以下两个特点:

    1.  对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是承诺,表示其他手段无法改变。

    2.  一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

     

    37.Promise 的构造函数

    构造一个 Promise,最基本的用法如下:

    var promise = new Promise(function(resolve, reject) {

            if (...) {  // succeed

                resolve(result);

            } else {   // fails

                reject(Error(errMessage));

            }

     });

    Promise 实例拥有 then 方法(具有 then 方法的对象,通常被称为 thenable)。它的使用方法如: promise.then(onFulfilled, onRejected)

    接收两个函数作为参数,一个在 fulfilled 的时候被调用,一个在 rejected 的时候被调用,接收参数就是 futureonFulfilled对应 resolveonRejected 对应 reject

    38.说说mongoDBMySQL的区别

    MySQL是传统的关系型数据库MongoDB则是非关系型数据库

    MongoDBBSON结构(二进制)进行存储,对海量数据存储有着很明显的优势。

    对比传统关系型数据库,NoSQL有着非常显著的性能和扩展性优势,与关系型数据库相比,mongodb的优点有: 
      
    ①弱一致性(最终一致),更能保证用户的访问速度: 
      
    ②文档结构的存储方式,能够更便捷的获取数据。

    39.计算机网络体系结构

    应用层(HTTPSMTPFTPPOP3)

    运输层(TCPUDP)

    网络层(IP(路由器))

    数据链路层(网桥(CSMA/CDPPP))

    物理层(集线器)

    40.说说网络分层里七层模型是哪七层

    应用层:应用层、表示层、会话层(从上往下)(HTTPFTPSMTPDNS

    传输层(TCPUDP

    网络层(IP

    物理和数据链路层(以太网)

    ① 每一层的作用如下:

    物理层:通过媒介传输比特,确定机械及电气规范(比特Bit

    数据链路层:将比特组装成帧和点到点的传递(帧Frame

    网络层:负责数据包从源到宿的传递和网际互连(包PackeT

    传输层:提供端到端的可靠报文传递和错误恢复(段Segment

    会话层:建立、管理和终止会话(会话协议数据单元SPDU

    表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU

    应用层:允许访问OSI环境的手段(应用协议数据单元APDU

      各种协议

    ICMP协议: 因特网控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。 
        TFTP协议: 是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。 
        HTTP协议: 超文本传输协议,是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。 
        DHCP协议: 动态主机配置协议,是一种让系统得以连接到网络上,并获取所需要的配置参数手段。

    41.说说TCP传输的三次握手四次挥手策略

    为了准确无误地把数据送达目标处,TCP协议采用了三次握手策略。用TCP协议把数据包送出去后,TCP不会对传送 后的情况置之不理,它一定会向对方确认是否成功送达。握手过程中使用了TCP的标志:SYNACK

    发送端首先发送一个带SYN标志的数据包给对方。接收端收到后,回传一个带有SYN/ACK标志的数据包以示传达确认信息。 
       
    最后,发送端再回传一个带
    ACK标志的数据包,代表“握手”结束。 
       
    若在握手过程中某个阶段莫名中断,
    TCP协议会再次以相同的顺序发送相同的数据包。

    42.断开一个TCP连接则需要“四次握手”:

    第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack  确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可 以接受数据。

    第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。

    第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。

    第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。

    43.TCPUDP的区别

    TCPTransmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来

    UDPUser Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去! 
       UDP
    适用于一次只传送少量数据、对可靠性要求不高的应用环境。

    44.什么叫优雅降级和渐进增强?
    优雅降级:Web站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,则代码会检查以确认它们是否能正常工作。由于IE独特的盒模型布局问题,针对不同版本的IEhack实践过优雅降级了,为那些无法支持功能的浏览器增加候选方案,使之在旧式浏览器上以某种形式降级体验却不至于完全失效.
    渐进增强:从被所有浏览器支持的基本功能开始,逐步地添加那些只有新式浏览器才支持的功能,向页面增加无害于基础浏览器的额外样式和功能的。当浏览器支持时,它们会自动地呈现出来并发挥作用。

    渐进增强和优雅降级?

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

    优雅降级 :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

    45.你觉得前端工程的价值体现在哪

    为简化用户使用提供技术支持(交互部分)
    为多个浏览器兼容性提供支持
    为提高用户浏览速度(浏览器性能)提供支持
    为跨平台或者其他基于webkit或其他渲染引擎的应用提供支持
    为展示数据提供支持(数据接口)

    46.列举IE 与其他浏览器不一样的特性?

    IE支持currentStyleFIrefox使用getComputStyle

    IE 使用innerTextFirefox使用textContent

    滤镜方面:IE:filter:alpha(opacity= num)Firefox-moz-opacity:num

    事件方面:IEattachEvent:火狐是addEventListener

    鼠标位置:IEevent.clientX;火狐是event.pageX

    IE使用event.srcElementFirefox使用event.target

    IE中消除list的原点仅需margin:0即可达到最终效果;FIrefox需要设置margin:0;padding:0以及list-style:none

    CSS圆角:ie7以下不支持圆角

    47.ie各版本和chrome可以并行下载多少个资源

    IE6 两个并发,iE7升级之后的6个并发,之后版本也是6
    Firefoxchrome也是6

    48.FlashAjax各自的优缺点,在使用中如何取舍?
    Flash
    适合处理多媒体、矢量图形、访问机器;对CSS、处理文本上不足,不容易被搜索。
    Ajax
    CSS、文本支持很好,支持搜索;多媒体、矢量图形、机器访问不足。
    共同点:与服务器的无刷新传递消息、用户离线和在线状态、操作DOM

    49.说说你对前端架构师的理解

    负责前端团队的管理及与其他团队的协调工作,提升团队成员能力和整体效率; 
    带领团队完成研发工具及平台前端部分的设计、研发和维护; 
    带领团队进行前端领域前沿技术研究及新技术调研,保证团队的技术领先 
    负责前端开发规范制定、功能模块化设计、公共组件搭建等工作,并组织培训。

    50.了解Node么?Node的使用场景都有哪些?
        高并发、聊天、实时消息推送
    51.介绍下你最常用的一款框架
        jquery,rn,angular
    ;
    52.对于前端自动化构建工具有了解吗?简单介绍一下
        Gulp,Grunt
    等;
    53.说说最近最流行的一些东西吧?常去哪些网站?
       Node.js
    MVVMReact-native,Angular,Weex
       CSDN,Segmentfault,
    博客园,掘金,Stackoverflow,伯乐在线等
    54.如果今年你打算熟练掌握一项新技术,那会是什么?
       via
    开发单页webapp的技术。
       SAP
    能够是页面与页面之间无缝连接,避免出现白页,且带有动态效果,提高用户体验。同时SAP,有JavaScript渲染页面,然后在从服务器获取小量的数据显示,如此反复,请求的数据无需要服务器处理,减少服务器负荷。
    SAP
    对技术要求高。要考虑首屏加载事件过长;动画效果要考虑低端手机;垃圾收集,需要自己释放资源,避免页面变卡。
    55.什么样的前端代码是好的

    高复用低耦合,这样文件小,好维护,而且好扩展。

    补充:

    从输入 URL 到页面加载完成的过程中都发生了什么

    1.  查找域名对应IP地址

    这一步包括 DNS 具体的查找过程,包括:浏览器缓存->系统缓存->路由器缓存...
    (1)
    浏览器搜索自己的 DNS 缓存(维护一张域名与 IP 地址的对应表);
    (2)
    搜索操作系统中的 DNS 缓存(维护一张域名与 IP 地址的对应表);
    (3)
    搜索操作系统的 hosts 文件( Windows 环境下,维护一张域名与 IP 地址的对应表);
    (4)
    操作系统将域名发送至 LDNS(本地区域名服务器),LDNS 查询 自己的 DNS 缓存(一般查找成功率    80% 左右),查找成功则返回结果,失败则发起一个迭代 DNS 解析请求

    LDNS Root Name Server (根域名服务器,如 comnetorg等的解析的顶级域名服务器的地址)发起请求,此处,Root Name Server 返回 com 域的顶级域名服务器的地址;

    LDNS com 域的顶级域名服务器发起请求,返回 baidu.com 域名服务器地址; LDNS baidu.com 域名服务器发起请求,得到 www.baidu.com IP 地址;

    (5) LDNS 将得到的 IP 地址返回给操作系统,同时自己也将 IP 地址缓存起来;

    (6) 操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来;

    2. 建立连接(TCP的三次握手)

    (1) 主机向服务器发送一个建立连接的请求;

    (2) 服务器接到请求后发送同意连接的信号;

    (3) 主机接到同意连接的信号后,再次向服务器发送了确认信号 ;

    注意:这里的三次握手中主机两次向服务器发送确认,第二次是为了防止已失效的连接请求报文段传至服务器导致错误。

    3.构建网页

    (1) 浏览器根据 URL 内容生成 HTTP 请求,请求中包含请求文件的位置、请求文件的方式等等;

    (2) 服务器接到请求后,会根据 HTTP 请求中的内容来决定如何获取相应的 HTML 文件;

    (3) 服务器将得到的 HTML 文件发送给浏览器;

    (4) 在浏览器还没有完全接收 HTML 文件时便开始渲染、显示网页;

    (5) 在执行 HTML 中代码时,根据需要,浏览器会继续请求图片、音频、视频、CSSJS等文件,过程同请求 HTML

    浏览器渲染展示网页过程

    1.  HTML代码转化为DOM(DOM Tree)

    2.  CSS代码转化成CSSOMCSS Object Model

    3.  结合DOMCSSOM,生成一棵渲染树(包含每个节点的视觉信息)(Render Tree)

    4.  生成布局(layout),即将所有渲染树的所有节点进行平面合成

    5.  将布局绘制(paint)在屏幕上

    4. 断开连接(TCP的四次挥手)

    (1) 主机向服务器发送一个断开连接的请求;

    (2) 服务器接到请求后发送确认收到请求的信号;(此时服务器可能还有数据要发送至主机)

    (3) 服务器向主机发送断开通知(此时服务器确认没有要向主机发送的数据)

    (4) 主机接到断开通知后断开连接并反馈一个确认信号,服务器收到确认信号后断开连接;

    注意:这里的四次挥手中服务器两次向主机发送消息,第一次是回复主机已收到断开的请求,第二次是向主机确认是否断开,确保数据传输完毕。

    插件:

    1有了解过React.js吗?

    React.js 只是一个视图库

        1)声明式设计

        2)高效:通过对DOM的模拟,最大限度的减少与DOM的交互。

        3)灵活:可以与已知的框架或库很好的配合。

        4JSX:是js语法的扩展,不一定使用,但建议用。

        (5)组件:构建组件,使代码更容易得到复用,能够很好地应用在大项目的开发中。

        (6)单向响应的数据流:React实现了单向响应的数据流,从而减少了重复代码,这也是解释了它为什么比传统数据绑定更简单。

    2.angularvue的区别

    1.vue仅仅是mvvm中的view层,只是一个如jquery般的工具库,而不是框架,而angular而是mvvm框架。

    2.vue的双向邦定是基于ES5 中的 getter/setter来实现的,而angular而是由自己实现一套模版编译规则,需要进行所谓的“脏”检查,vue则不需要。因此,vue在性能上更高效,但是代价是对于ie9以下的浏览器无法支持。

    3.vue需要提供一个el对象进行实例化,后续的所有作用范围也是在el对象之下,而angular而是整个html页面。一个页面,可以有多个vue实例,而angular好像不是这么玩的。

    4.vue真的很容易上手,学习成本相对低,不过可以参考的资料不是很丰富,官方文档比较简单,缺少全面的使用案例。高级的用法,需要自己去研究源码,至少目前是这样。

    3.less的特点

    每次被问到这个我只能想起less中的定义变量,用太久less都忘了css不能嵌套,醉了醉了。

    1.  变量

    2.  混合(Mixins

    3.  嵌套规则

    4.  运算

    5.  函数

    6.  命名空间

    7.  作用域

    8.  注释

    9.  导入(Import

    4.less的原理

    本质上,less 包含一套自定义的语法及一个解析器,用户根据这些语法定义自己的样式规则,这些规则最终会通过解析器,less 把这些样式规则编译成浏览器可以识别的 css 样式。less 并没有裁剪 css 原有的特性,更不是用来取代 css 的,而是在现有 css 语法的基础上,为 css 加入程序式语言的特性。less 最终需要编译成 css 文件才能起到样式的效果,我们可以称 less css 样式生成工具。

    5. gulp的特点

    1.  使用 gulp.js,你的构建脚本是代码,而不是配置文件;

    2.  使用标准库(node.js standard library)来编写脚本;

    3.  插件都很简单,只负责完成一件事-基本上都是 20 行左右的函数;

    4.  任务都以最大的并发数来执行;

    5.  Gulp是一个基于流的构建系统,使用代码优于配置的策略。输入/输出(I/O)是基于流式的。

    作用:

    1.  SassLess编译

    2.  Css Js 图片压缩

    3.  Css Js 合并

    4.  Css Js 内联

    5.  Htmlinclude功能

    6.  Autoprefixer(自动处理浏览器css前缀)

    7.  自动刷新

    8.  去缓存

    9.  Handlebars模板文件的预编译

    10.雪碧图

    11.ESLint

    12.rem移动端适配方案

    6.Promise对象有以下两个特点。

    1.  对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是承诺,表示其他手段无法改变。

    2.  一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

    7.js的冒泡(Bubbling Event)和捕获(Capture Event)的区别

    js之事件冒泡和事件捕获详细介绍

    1.  冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。

    2.  捕获型事件(event capturing):事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)

    3.  DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件,但是,捕获型事件先发生。两种事件流会触及DOM中的所有对象,从document对象开始,也在document对象结束。

    4.  DOM事件模型最独特的性质是,文本节点也触发事件(IE中不会)

    示例
    假设一个元素div,它有一个下级元素p

    <div>
                <p>元素</p>
    </div>

    这两个元素都绑定了click事件,如果用户点击了p

         1.事件捕获

    当你使用事件捕获时,**父级元素先触发**,子级元素后触发,即div先触发,p后触发。

         2.事件冒泡

         3.当你使用事件冒泡时,**子级元素先触发**,父级元素后触发,即p先触发,div后触发。

    addEventListener函数,它有三个参数,第三个参数若是true,则表示采用事件捕获,若是false,则表示采用事件冒泡。
          IE
    只支持事件冒泡,不支持事件捕获。

    8.svngit的区别

    1. git是分布式的,svn不是。

    2.  gitsvn一样有自己的集中式版本库或服务器。但git更倾向于被使用于分布式模式,克隆版本库后即使没有网络也能够commit文件,查看历史版本记录,创建项目分支等,等网络再次连接上Push到服务器端。

    1. git把内容按元数据方式存储,而svn是按文件。

    4.  所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里。

    5.  git目录是处于你的机器上的一个克隆版的版本库,它拥有中心版本库上所有的东西,例如标签,分支,版本记录等。

    1. git没有一个全局的版本号,svn有。
    2. git的内容完整性优于svn

    8.  因为git的内容存储使用的是SHA-1哈希算法。

    1. git可以有无限个版本库,svn只能有一个指定中央版本库。

    10.svn中央版本库有问题时,所有工作成员都一起瘫痪直到版本库维修完毕或者新的版本库设立完成。

    11.每一个git都是一个版本库,区别是它们是否拥有活跃目录(Git Working Tree)。如果主要版本库(例如:置於GitHub的版本库)有问题,工作成员仍然可以在自己的本地版本库(local repository)提交,等待主要版本库恢复即可。工作成员也可以提交到其他的版本库!


    9对前端工程师这个职位你是怎么样理解的?

    a. 前端是最贴近用户的程序员,前端的能力就是能让产品从 90分进化到 100 分,甚至更好

    b. 参与项目,快速高质量完成实现效果图,精确到1px

    c. 与团队成员,UI设计,产品经理的沟通;

    d. 做好的页面结构,页面重构和用户体验;

    e. 处理hack,兼容、写出优美的代码格式;

    f. 针对服务器的优化、拥抱最新前端技术。

     

     

     

     

    扩展:

    1.自我介绍:除了基本个人信息以外,面试官更想听的是你与众不同的地方和你的优势。
    2.项目介绍
    3.如何看待前端开发?
    4.平时是如何学习前端开发的?
    5.未来三到五年的规划是怎样的?

    算法部分:

    1.编写一个方法 求一个字符串的字节长度

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

    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"));

    2.统计一个字符串出现最多的字母

    给出一段英文连续的英文字符窜,找出重复出现次数最多的字母

        输入 afjghdfraaaasdenas

        输出 a
    前面出现过去重的算法,这里需要是统计重复次数。
    function findMaxDuplicateChar(str) {  
      if(str.length == 1) {
        return str;
      }
      let charObj = {};
      for(let i=0;i<str.length;i++) {
        if(!charObj[str.charAt(i)]) {
          charObj[str.charAt(i)] = 1;
        }else{
          charObj[str.charAt(i)] += 1;
        }
      }
      let maxChar = '',
          maxValue = 1;
      for(var k in charObj) {
        if(charObj[k] >= maxValue) {
          maxChar = k;
          maxValue = charObj[k];
        }
      }
      return maxChar;
     
    }
     
    module.exports = findMaxDuplicateChar;

    统计字符串中字母个数或统计最多字母数

     

    var str = "aaaabbbccccddfgh";
    var obj  = {};
    for(var i=0;i<str.length;i++){
        var v = str.charAt(i);
        if(obj[v] && obj[v].value == v){
            obj[v].count = ++ obj[v].count;
        }else{
            obj[v] = {};
            obj[v].count = 1;
            obj[v].value = v;
        }
    }
    for(key in obj){
        document.write(obj[key].value +'='+obj[key].count+'&nbsp;'); // a=4  b=3  c=4  d=2  f=1  g=1  h=1 
    }

    3.JS数组去重

    以下是展示三种方法

    Array.prototype.unique1 = function () {
      var n = []; //一个新的临时数组
      for (var i = 0; i < this.length; i++) //遍历当前数组
      {
        //如果当前数组的第i已经保存进了临时数组,那么跳过,
        //否则把当前项push到临时数组里面
        if (n.indexOf(this[i]) == -1) n.push(this[i]);
      }
      return n;
    }
    
    Array.prototype.unique2 = function()
    {
        var n = {},r=[]; //n为hash表,r为临时数组
        for(var i = 0; i < this.length; i++) //遍历当前数组
        {
            if (!n[this[i]]) //如果hash表中没有当前项
            {
                n[this[i]] = true; //存入hash表
                r.push(this[i]); //把当前数组的当前项push到临时数组里面
            }
        }
        return r;
    }
    
    Array.prototype.unique3 = function()
    {
        var n = [this[0]]; //结果数组
        for(var i = 1; i < this.length; i++) //从第二项开始遍历
        {
            //如果当前数组的第i项在当前数组中第一次出现的位置不是i,
            //那么表示第i项是重复的,忽略掉。否则存入结果数组
            if (this.indexOf(this[i]) == i) n.push(this[i]);
        }
        return n;
    }

    4.去掉一组整型数组重复的值

     比如输入: [1,13,24,11,11,14,1,2]

     输出: [1,13,24,11,14,2]
     需要去掉重复的11 1 这两个元素。
    这道问题出现在诸多的前端面试题中,主要考察个人对Object的使用,利用key来进行筛选。
    /**
    * unique an array 
    **/
    let unique = function(arr) {  
      let hashTable = {};
      let data = [];
      for(let i=0,l=arr.length;i<l;i++) {
        if(!hashTable[arr[i]]) {
          hashTable[arr[i]] = true;
          data.push(arr[i]);
        }
      }
      return data
     
    }
     
    module.exports = unique;

    5.js操作获取和设置cookie

    //创建cookie
    function setCookie(name, value, expires, path, domain, secure) {
        var cookieText = encodeURIComponent(name) + '=' + encodeURIComponent(value);
        if (expires instanceof Date) {
            cookieText += '; expires=' + expires;
        }
        if (path) {
            cookieText += '; expires=' + expires;
        }
        if (domain) {
            cookieText += '; domain=' + domain;
        }
        if (secure) {
            cookieText += '; secure';
        }
        document.cookie = cookieText;
    }
    
    //获取cookie
    function getCookie(name) {
        var cookieName = encodeURIComponent(name) + '=';
        var cookieStart = document.cookie.indexOf(cookieName);
        var cookieValue = null;
        if (cookieStart > -1) {
            var cookieEnd = document.cookie.indexOf(';', cookieStart);
            if (cookieEnd == -1) {
                cookieEnd = document.cookie.length;
            }
            cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
        }
        return cookieValue;
    }
    
    //删除cookie
    function unsetCookie(name) {
        document.cookie = name + "= ; expires=" + new Date(0);
    }

     6.编写一个b继承a的方法

    function A(name){
        this.name = name;
        this.sayHello = function(){alert(this.name+” say Hello!”);};
    }
    function B(name,id){
        this.temp = A;
        this.temp(name);        //相当于new A();
        delete this.temp;       
         this.id = id;   
        this.checkId = function(ID){alert(this.id==ID)};
    }

    7.如何阻止事件冒泡和默认事件

    function stopBubble(e)
    {
        if (e && e.stopPropagation)
            e.stopPropagation()
        else
            window.event.cancelBubble=true
    }
    return false

    8.下面程序执行后弹出什么样的结果?

    function fn() {
        this.a = 0;
        this.b = function() {
            alert(this.a)
        }
    }
    fn.prototype = {
        b: function() {
            this.a = 20;
            alert(this.a);
        },
        c: function() {
            this.a = 30;
            alert(this.a);
        }
    }
    var myfn = new fn();
    myfn.b();
    myfn.c();

     

    9.下面程序的结果

    function fun(n,o) {
      console.log(o)
      return {
        fun:function(m){
          return fun(m,n);
        }
      };
    }
    var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);
    var b = fun(0).fun(1).fun(2).fun(3);
    var c = fun(0).fun(1);  c.fun(2);  c.fun(3);
    
    //答案:
    
    //a: undefined,0,0,0
    //b: undefined,0,1,2
    //c: undefined,0,1,1

    10.下面程序的输出结果

    var name = 'World!';
    (function () {
        if (typeof name === 'undefined') {
            var name = 'Jack';
            console.log('Goodbye ' + name);
        } else {
            console.log('Hello ' + name);
        }
    })();
    
    //Goodbye Jack

    11.快速 排序的思想并实现一个快排?

      “快速排序”的思想很简单,整个排序过程只需要三步:

      (1)在数据集之中,找一个基准点

      (2)建立两个数组,分别存储左边和右边的数组

      (3)利用递归进行下次比较

    <script type="text/javascript">
    
            function quickSort(arr){
                if(arr.length<=1){
                    return arr;//如果数组只有一个数,就直接返回;
                }
    
                var num = Math.floor(arr.length/2);//找到中间数的索引值,如果是浮点数,则向下取整
    
                var numValue = arr.splice(num,1);//找到中间数的值
                var left = [];
                var right = [];
    
                for(var i=0;i<arr.length;i++){
                    if(arr[i]<numValue){
                        left.push(arr[i]);//基准点的左边的数传到左边数组
                    }
                    else{
                       right.push(arr[i]);//基准点的右边的数传到右边数组
                    }
                }
                return quickSort(left).concat([numValue],quickSort(right));//递归不断重复比较
            }
            alert(quickSort([32,45,37,16,2,87]));//弹出“2,16,32,37,45,87”
     </script>

    手写数组快速排序:

    关于快排算法的详细说明,可以参考阮一峰老师的文章快速排序
    "快速排序"的思想很简单,整个排序过程只需要三步:
    (1)在数据集之中,选择一个元素作为"基准"(pivot)。
    (2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
    (3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
    参考代码:

    var quickSort = function(arr) {
      if (arr.length <= 1) { return arr; }
      var pivotIndex = Math.floor(arr.length / 2);
      var pivot = arr.splice(pivotIndex, 1)[0];
      var left = [];
      var right = [];
      for (var i = 0; i < arr.length; i++){
        if (arr[i] < pivot) {
          left.push(arr[i]);
        } else {
          right.push(arr[i]);
        }
      }
      return quickSort(left).concat([pivot], quickSort(right));
    };

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

    第一种(好用):

    function clone(obj) {
        var o;
        switch (typeof obj) {
            case "undefined":
                break;
            case "string":
                o = obj + "";
                break;
            case "number":
                o = obj - 0;
                break;
            case "boolean":
                o = obj;
                break;
            case "object": // object 分为两种情况 对象(Object)或数组(Array)
                if (obj === null) {
                    o = null;
                } else {
                    if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
                        o = [];
                        for (var i = 0; i < obj.length; i++) {
                            o.push(clone(obj[i]));
                        }
                    } else {
                        o = {};
                        for (var k in obj) {
                            o[k] = clone(obj[k]);
                        }
                    }
                }
                break;
            default:
                o = obj;
                break;
        }
        return o;
    }
    View Code

    第二种:

    Object.prototype.clone = function(){
    
                var o = this.constructor === Array ? [] : {};
    
                for(var e in this){
    
                        o[e] = typeof this[e] === "object" ? this[e].clone() : this[e];
    
                }
    
                return o;
        }

     13.如何获取UA?

    function whatBrowser() {  
            document.Browser.Name.value=navigator.appName;  
            document.Browser.Version.value=navigator.appVersion;  
            document.Browser.Code.value=navigator.appCodeName;  
            document.Browser.Agent.value=navigator.userAgent;  
        } 

    14.常规GruntFile.js && gulpFile.js

    ①.GruntFile.js

    <script>
        module.exports = function(grunt) {
            // 导入模块
            grunt.loadNpmTasks('grunt-contrib-uglify');
            grunt.loadNpmTasks('grunt-contrib-cssmin');
            grunt.loadNpmTasks('grunt-contrib-htmlmin');
            grunt.loadNpmTasks('grunt-contrib-imagemin');
            grunt.loadNpmTasks('grunt-contrib-watch');
    
            // 配置任务
            grunt.initConfig({
                // js压缩 默认加密压缩
                uglify: { // 主任务名称
                    options: { // [配置选项]
                        mangle: false // 是否加密压缩
                    },
                    a: { // 子任务名称
                        expand: true, // 是否分开压缩
                        src: 'js/*.js',    // 源文件
                        dest: 'build'    // 目标文件 自动创建源文件文件夹
                    }
                },
                cssmin: {
                    a: {
                        expand: true,
                        src: 'css/*.css',
                        dest: 'build'
                    }
                },
                htmlmin: {
                    options: {
                        removeComments: true,    // 是否移除注释
                        collapseWhitespace: false    // 是否去掉空白
                    },
                    a: {
                        src: '*.html',
                        dest: 'build'
                    }
                },
                // imagemin: {
                //     a: {
                //         expand: true, //分开执行
                //         cwd: 'images',
                //         src: ['**/*.{png,jpg}'],
                //         dest: 'build/images'
                //     }
                // },
                watch: {
                    a: {
                        files: ['*.html', 'css/*.css', 'js/*.js'],
                        tasks: ['cssmin', 'htmlmin', 'uglify']
                    }
                }
            });
    
            // 注册一个默认任务
            grunt.registerTask('default', ['uglify', 'cssmin', 'htmlmin', 'watch']);
        }
    </script>

    ②.gulpfile.js

    <script>
        // 导入模块
        var gulp = require('gulp');
        var cssmin = require('gulp-cssmin');
        var uglify = require('gulp-uglify');
        var htmlmin = require('gulp-htmlmin');
        var concat = require('gulp-concat');
        var rename = require('gulp-rename');    // 改名
    
        // 配置任务
        gulp.task('uglify:css', function() {
            gulp.src('css/*.css')
                .pipe(cssmin())        // 压缩
                .pipe(concat('all.min.css'))    // 合并
                .pipe(gulp.dest('build/css'))    // 输出
        });
        gulp.task('uglify:js', function() {
            gulp.src('js/*.js')
                .pipe(uglify())                    // 压缩
                .pipe(gulp.dest('build/js'))    // 输出
        });
        gulp.task('uglify:html', function() {
            gulp.src('*.html')
                .pipe(htmlmin({                    // 压缩
                    collapseWhitespace: true,
                    removeComments: true
                }))
                .pipe(gulp.dest('build'))        // 输出
        });
    
        gulp.watch('*.*', ['uglify:css', 'uglify:js', 'uglify:html']);
    
        gulp.task('default', ['uglify:css', 'uglify:js', 'uglify:html']);
    </script>
    <script>
        var gulp = require('gulp');
        var uglify = require('gulp-uglify');
        var clean = require('gulp-clean-css');
        var sass = require('gulp-sass');
    
        gulp.task('uglify',function(){
            return(
                gulp.src('./src/*.js')
                    .pipe(uglify())
                    .pipe(gulp.dest('dist'))
            )
        })
    
        gulp.task('minify-css',function(){
            return (
                gulp.src('./src/*.css')
                    .pipe(clean())
                    .pipe(gulp.dest('dist'))
            )
        })
    
        gulp.task('compile-sass',function(){
            return (
                gulp.src('./src/*.scss')
                    .pipe(sass().on('error', sass.logError))
                    .pipe(gulp.dest('dist'))
            )
        })
    
        gulp.task('default',function(){
            gulp.watch('./src/*.js',['uglify']);
            gulp.watch('./src/*.css',['minify-css']);
            gulp.watch('./src/*.scss',['compile-sass']);
        })
    </script>

    15.ajax过程 

    1. 获得ajax

    2. 打开地址

    3. 发送数据

    4. 接收数据

    <script>
     // 1.获得ajax
     if (window.XMLHttpRequest) { //查看当前浏览器XMLHttpRequest是否是全局变量
         var oAjax = new XMLHttpResquest();
     } else {
         var oAjax = new ActiveXObject('Microsoft.XMLHTTP'); //IE6,传入微软参数
     }
    
     // 2.打开地址
     switch (json.type.toLowerCase()) {
         case 'get':
             oAjax.open('GET', json.url + '?' + jsonToURL(json.data), true); // 提交方式(大写),url,是否异步
             oAjax.send(); // 3.发送数据
             break;
         case 'post':
             oAjax.open('POST', json.url, true);
             oAjax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
             oAjax.send(jsonToURL(json.data)); // 3.发送数据
             break;
     }
    
     // 4.接收数据
     oAjax.onreadystatechange = function() { //监控状态
         if (oAjax.readyState == 4) {
             json.complete && json.complete();
             if (oAjax.status >= 200 && oAjax.status < 300 ||
                 oAjax.status == 304) {
                 json.success && json.success(oAjax.responseText); //执行成功的回调函数, responseText为响应内容
             } else {
                 json.error && json.error(oAjax.status); //执行失败的回调函数
             }
         }
     };
    </script>

    16.less不依靠构建转css

    甩上gulp构建转化

    <script>
        var gulp = require('gulp'),
            less = require('gulp-less');
    
        gulp.task('testLess', function() {
            gulp.src(['src/less/index.less', 'src/less/detail.less']) //多个文件以数组形式传入
                .pipe(less())
                .pipe(gulp.dest('src/css')); //将会在src/css下生成index.css以及detail.css 
        });
    
        gulp.task('testWatch', function() {
            gulp.watch('src/**/*.less', ['testLess']); //当所有less文件发生改变时,调用testLess任务
        });
    </script>

    17、冒泡、快排

    ①、冒泡排序

    每次比较相邻的两个数,如果后一个比前一个小,换位置。
    时间复杂度:O(n^2)
    <script>
        var arr = [3, 1, 4, 6, 5, 7, 2];
    
        function bubbleSort(arr) {
            var len = arr.length;
            for (var i = len; i >= 2; --i) {
                for (var j = 0; j < i - 1; j++) {
                    if (arr[j + 1] < arr[j]) {
                        var temp;
                        temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
            return arr;
        }
    
        function bubbleSort2(arr) {
            var len = arr.length;
            for (var i = 0; i <= len - 1; i++) {
                for (var j = 0; j <= len - i; j++) {
                    if (arr[j + 1] < arr[j]) {
                        var temp;
                        temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
            return arr;
        }
    
        console.log(bubbleSort(arr));
        console.log(bubbleSort2(arr));
    </script>

    ②、快速排序

    采用二分法,取出中间数,数组每次和中间数比较,小的放到左边,大的放到右边。
    时间复杂度:O(nlog2(n))
    <script>
        var arr = [3, 1, 4, 6, 5, 7, 2];
    
        function quickSort(arr) {
            if(arr.length == 0) {
                return [];    // 返回空数组
            }
    
            var cIndex = Math.floor(arr.length / 2);
            var c = arr.splice(cIndex, 1);
            var l = [];
            var r = [];
    
            for (var i = 0; i < arr.length; i++) {
                if(arr[i] < c) {
                    l.push(arr[i]);
                } else {
                    r.push(arr[i]);
                }
            }
    
            return quickSort(l).concat(c, quickSort(r));
        }
    
        console.log(quickSort(arr));
    </script>

    18.数组的翻转(非reverse)

    <script>
        var arr=[1,2,3,4];
        var arr2=[];
        while(arr.length) {
            var num=arr.pop();
            arr2.push(num);
        }
        alert(arr2);
    </script>

    19.判断一个单词是否是回文?

    回文是指把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。比如 mamam redivider .

    很多人拿到这样的题目非常容易想到用for 将字符串颠倒字母顺序然后匹配就行了。其实重要的考察的就是对于reverse的实现。其实我们可以利用现成的函数,将字符串转换成数组,这个思路很重要,我们可以拥有更多的自由度去进行字符串的一些操作。

    function checkPalindrom(str) {  
        return str == str.split('').reverse().join('');
    }

     

     

    20.排序算法

    如果抽到算法题目的话,应该大多都是比较开放的题目,不限定算法的实现,但是一定要求掌握其中的几种,所以冒泡排序,这种较为基础并且便于理解记忆的算法一定需要熟记于心。冒泡排序算法就是依次比较大小,小的的大的进行位置上的交换。

    function bubbleSort(arr) {  
        for(let i = 0,l=arr.length;i<l-1;i++) {
            for(let j = i+1;j<l;j++) { 
              if(arr[i]>arr[j]) {
                    let tem = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tem;
                }
            }
        }
        return arr;
    }
    module.exports = bubbleSort;

    21.不借助临时变量,进行两个整数的交换

       输入 a = 2, b = 4 输出 a = 4, b =2

     

    这种问题非常巧妙,需要大家跳出惯有的思维,利用 a , b进行置换。

    主要是利用 + – 去进行运算,类似 a = a + ( b – a) 实际上等同于最后 的 a = b;

    function swap(a , b) {  
      b = b - a;
      a = a + b;
      b = a - b;
      return [a,b];
    }
     
    module.exports = swap;

    22.使用canvas 绘制一个有限度的斐波那契数列的曲线?

     

     数列长度限定在9

    斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列主要考察递归的调用。我们一般都知道定义

          fibo[i] = fibo[i-1]+fibo[i-2];

    生成斐波那契数组的方法

    function getFibonacci(n) {  
      var fibarr = [];
      var i = 0;
      while(i<n) {
        if(i<=1) {
          fibarr.push(i);
        }else{
          fibarr.push(fibarr[i-1] + fibarr[i-2])
        }
        i++;
      }
     
      return fibarr;
    }

    剩余的工作就是利用canvas arc方法进行曲线绘制了

     html

    <canvas></canvas>

    css

    canvas{
        width: 600px;
        height:480px;
        background: #000;
      }

    js

    var canvas = document.querySelector('canvas');
    
    canvas.width = 600;
    canvas.height = 480;
    
    var coor = {
      x: 300,
      y: 240,
    };
    
    var ctx = canvas.getContext('2d');
    
    function draw(r, n ,prevR) {
       if(n>2) {
         switch(n%4) {
          case 0 :
            coor.y = coor.y - 5 * prevR;
            coor.y = coor.y + 5 * r;
    
            break;
          case 1 :
            coor.x = coor.x + 5 * prevR;
            coor.x = coor.x - 5 * r;
            break;
          case 2 :
            coor.y = coor.y + 5 * prevR;
            coor.y = coor.y - 5 * r;
            break;
          case 3 :
            coor.x = coor.x - 5 * prevR;
            coor.x = coor.x + 5 * r;
            break;
        }
      }
      ctx.beginPath();
      ctx.arc(coor.x,coor.y,5*r,Math.PI*0.5*(n),Math.PI*0.5*(n-1),true);
      if(n>1) {
         switch(n%4) {
          case 0 :
            ctx.moveTo(coor.x - 5*r,coor.y);
    
            break;
          case 1 :
            ctx.moveTo(coor.x,coor.y + 5*r);
            break;
          case 2 :
           ctx.moveTo(coor.x + 5*r,coor.y);
            break;
          case 3 :
            ctx.moveTo(coor.x,coor.y-5*r);
            break;
        }
      }
      
      ctx.lineWidth = 1;
      ctx.strokeStyle = '#fff';
      ctx.stroke();
    }
    
    
    
    function getFibonacci(n) {
      var fibarr = [];
      var i = 0;
      while(i<n) {
        if(i<=1) {
          fibarr.push(i);
        }else{
          fibarr.push(fibarr[i-1] + fibarr[i-2])
        }
        i++;
      }
      
      return fibarr;
    }
    var data = getFibonacci(10);
    
    for(var i = 0,l=data.length;i<l;i++) {
      if(data[i]!=0) {
        draw(data[i],i,data[i-1]);
        
      }
    }

    23.找出下列正数组的最大差值比如:

         输入 [10,5,11,7,8,9]

         输出 6

     这是通过一道题目去测试对于基本的数组的最大值的查找,很明显我们知道,最大差值肯定是一个数组中最大值与最小值的差。

     

     function getMaxProfit(arr) {
     
        var minPrice = arr[0];
        var maxProfit = 0;
     
        for (var i = 0; i < arr.length; i++) {
            var currentPrice = arr[i];
     
            minPrice = Math.min(minPrice, currentPrice);
     
            var potentialProfit = currentPrice - minPrice;
     
            maxProfit = Math.max(maxProfit, potentialProfit);
        }
     
        return maxProfit;
    }

    24.随机生成指定长度的字符串:

    实现一个算法,随机生成指制定长度的字符窜。

        比如给定 长度 8  输出 4ldkfg9j

     

    function randomString(n) {  
      let str = 'abcdefghijklmnopqrstuvwxyz9876543210';
      let tmp = '',
          i = 0,
          l = str.length;
      for (i = 0; i < n; i++) {
        tmp += str.charAt(Math.floor(Math.random() * l));
      }
      return tmp;
    }
     
    module.exports = randomString;

    25.实现类似getElementsByClassName 的功能

    自己实现一个函数,查找某个DOM节点下面的包含某个class的所有DOM节点?不允许使用原生提供的 getElementsByClassName querySelectorAll 等原生提供DOM查找函数。

    
    function queryClassName(node, name) {  
      var starts = '(^|[ 
    
    	f])',
           ends = '([ 
    
    	f]|$)';
      var array = [],
            regex = new RegExp(starts + name + ends),
            elements = node.getElementsByTagName("*"),
            length = elements.length,
            i = 0,
            element;
     
        while (i < length) {
            element = elements[i];
            if (regex.test(element.className)) {
                array.push(element);
            }
     
            i += 1;
        }
     
        return array;
    }

     26.使用JS 实现二叉查找树(Binary Search Tree)

    一般叫全部写完的概率比较少,但是重点考察你对它的理解和一些基本特点的实现。 二叉查找树,也称二叉搜索树、有序二叉树(英语:ordered binary tree)是指一棵空树或者具有下列性质的二叉树:

    • 任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    • 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    • 任意节点的左、右子树也分别为二叉查找树;
    • 没有键值相等的节点。二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低。为O(log n)。二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。

     

    在写的时候需要足够理解二叉搜素树的特点,需要先设定好每个节点的数据结构

    class Node {  
      constructor(data, left, right) {
        this.data = data;
        this.left = left;
        this.right = right;
      }
     
    }

    树是有节点构成,由根节点逐渐延生到各个子节点,因此它具备基本的结构就是具备一个根节点,具备添加,查找和删除节点的方法.

    class BinarySearchTree {
     
      constructor() {
        this.root = null;
      }
     
      insert(data) {
        let n = new Node(data, null, null);
        if (!this.root) {
          return this.root = n;
        }
        let currentNode = this.root;
        let parent = null;
        while (1) {
          parent = currentNode;
          if (data < currentNode.data) {
            currentNode = currentNode.left;
            if (currentNode === null) {
              parent.left = n;
              break;
            }
          } else {
            currentNode = currentNode.right;
            if (currentNode === null) {
              parent.right = n;
              break;
            }
          }
        }
      }
     
      remove(data) {
        this.root = this.removeNode(this.root, data)
      }
     
      removeNode(node, data) {
        if (node == null) {
          return null;
        }
     
        if (data == node.data) {
          // no children node
          if (node.left == null && node.right == null) {
            return null;
          }
          if (node.left == null) {
            return node.right;
          }
          if (node.right == null) {
            return node.left;
          }
     
          let getSmallest = function(node) {
            if(node.left === null && node.right == null) {
              return node;
            }
            if(node.left != null) {
              return node.left;
            }
            if(node.right !== null) {
              return getSmallest(node.right);
            }
     
          }
          let temNode = getSmallest(node.right);
          node.data = temNode.data;
          node.right = this.removeNode(temNode.right,temNode.data);
          return node;
     
        } else if (data < node.data) {
          node.left = this.removeNode(node.left,data);
          return node;
        } else {
          node.right = this.removeNode(node.right,data);
          return node;
        }
      }
     
      find(data) {
        var current = this.root;
        while (current != null) {
          if (data == current.data) {
            break;
          }
          if (data < current.data) {
            current = current.left;
          } else {
            current = current.right
          }
        }
        return current.data;
      }
     
    }
     
    module.exports = BinarySearchTree;

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

     /**
     * 对象克隆
     * 支持基本数据类型及对象
     * 递归方法
     */
    function clone(obj) {
        var o;
        switch (typeof obj) {
            case "undefined":
                break;
            case "string":
                o = obj + "";
                break;
            case "number":
                o = obj - 0;
                break;
            case "boolean":
                o = obj;
                break;
            case "object": // object 分为两种情况 对象(Object)或数组(Array)
                if (obj === null) {
                    o = null;
                } else {
                    if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
                        o = [];
                        for (var i = 0; i < obj.length; i++) {
                            o.push(clone(obj[i]));
                        }
                    } else {
                        o = {};
                        for (var k in obj) {
                            o[k] = clone(obj[k]);
                        }
                    }
                }
                break;
            default:
                o = obj;
                break;
        }
        return o;
    }

    28.如何消除一个数组里面重复的元素?

    // 方法一:
    var arr1 =[1,2,2,2,3,3,3,4,5,6],
        arr2 = [];
    for(var i = 0,len = arr1.length; i< len; i++){
        if(arr2.indexOf(arr1[i]) < 0){
            arr2.push(arr1[i]);
        }
    }
    document.write(arr2); // 1,2,3,4,5,6

    29.在Javascript中什么是伪数组?如何将伪数组转化为标准数组?

    伪数组(类数组):无法直接调用数组方法或期望length属性有什么特殊的行为,但仍可以对真正数组遍历方法来遍历它们。典型的是函数的argument参数,还有像调用getElementsByTagName,document.childNodes之类的,它们都返回NodeList对象都属于伪数组。可以使用Array.prototype.slice.call(fakeArray)将数组转化为真正的Array对象。

    function log(){
          var args = Array.prototype.slice.call(arguments);  
    //为了使用unshift数组方法,将argument转化为真正的数组
          args.unshift('(app)');
     
          console.log.apply(console, args);
    };

    30.JavaScript实现二分法查找

    二分法查找,也称折半查找,是一种在有序数组中查找特定元素的搜索算法。查找过程可以分为以下步骤:
    (1)首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。
    (2)如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。
    (3)如果某一步数组为空,则表示找不到目标元素。
    参考代码:

    // 非递归算法
            function binary_search(arr, key) {
                var low = 0,
                    high = arr.length - 1;
                while(low <= high){
                    var mid = parseInt((high + low) / 2);
                    if(key == arr[mid]){
                        return  mid;
                    }else if(key > arr[mid]){
                        low = mid + 1;
                    }else if(key < arr[mid]){
                        high = mid -1;
                    }else{
                        return -1;
                    }
                }
            };
            var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
            var result = binary_search(arr,10);
            alert(result); // 9 返回目标元素的索引值       
    // 递归算法
            function binary_search(arr,low, high, key) {
                if (low > high){
                    return -1;
                }
                var mid = parseInt((high + low) / 2);
                if(arr[mid] == key){
                    return mid;
                }else if (arr[mid] > key){
                    high = mid - 1;
                    return binary_search(arr, low, high, key);
                }else if (arr[mid] < key){
                    low = mid + 1;
                    return binary_search(arr, low, high, key);
                }
            };
            var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
            var result = binary_search(arr, 0, 13, 10);
            alert(result); // 9 返回目标元素的索引值  

    31.写一个function,清除字符串前后的空格。(兼容所有浏览器)

    function trim(str) {
        if (str && typeof str === "string") {
            return str.replace(/(^s*)|(s*)$/g,""); //去除前后空白符
        }
    }

    32.使用正则表达式验证邮箱格式

     var reg = /^(w)+(.w+)*@(w)+((.w{2,3}){1,3})$/;
        var email = "example@qq.com";
        console.log(reg.test(email));  // true  

    参考:

    http://web.jobbole.com/88471/

    https://segmentfault.com/a/1190000008644536

    http://blog.csdn.net/kebi007/article/details/54882425#t4

    http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html

    http://www.cnblogs.com/GeniusLyzh/p/5272902.html

     
  • 相关阅读:
    .NET微服务调查结果
    发布基于Orchard Core的友浩达科技官网
    Followme Devops实践之路
    积极参与开源项目,促进.NET Core生态社区发展
    Service Fabric 与 Ocelot 集成
    “.Net 社区大会”(dotnetConf) 2018 Day 1 主题演讲
    Project file is incomplete. Expected imports are missing 错误解决方案
    稳定工作和创业之间的抉择
    回顾4180天在腾讯使用C#的历程,开启新的征途
    ML-Framework:ML.NET 0.3 带来新组件
  • 原文地址:https://www.cnblogs.com/Han39/p/7240959.html
Copyright © 2020-2023  润新知