前端面试技巧课程(2)

来自慕课课程:前端跳槽面试必备技巧

1.一面/二面 面试技巧

面试技巧:准备要充分、知识要系统、沟通要简介、内心要诚实、态度要谦虚、回答要灵活

通信:跨域、前后端通信
安全:CSRF、XSRF、XSS

2.页面布局

题目:假设高度已知,请写出三栏布局,其中左栏、右栏宽度各为300px,中间自适应

答案:浮动解决方案、绝对定位解决方案、flexbox解决方案、表格布局解决方案、网格布局解决方案

引申思考:
1.各个方法的优缺点
2.假设高度已知去掉,不再只考虑水平方向,还要考虑中间高度问题,例如中间的内容有点多,撑开了,上面哪个方案还可以适应。
3.五个方案的浏览器兼容性如何?
4.实际应用中,哪个方案最优?

浮动布局常见问题是清除浮动,优点是兼容性比较好。
绝对定位好处是快捷,本身脱离文档流了,要求下面的定位要注意定位好位置,可使用性比较差。
Flex布局常用于移动端,针对上面两个布局不足提出的布局方案。
表格布局其实在一些场景很适应的,表格布局兼容性也不错,还有缺点是,三栏高度一个变化时另外两个也会变化。
网格布局借鉴CSS栅格,可以对比比较。

假设高度已知去掉,Flex和表格布局还可以用。

前端面试技巧课程(2)_第1张图片

如果要求上图中间的字不往两边扩展,只显示在中间,解决方案是:BFC

页面布局小结:

1.语义化掌握到位
2.页面布局理解深刻
3.CSS基础知识扎实
4.思维灵活且积极向上
5.代码书写规范

常见布局:(可作为思考题)

前端面试技巧课程(2)_第2张图片

3.CSS盒模型

基本概念:

margin、padding、border、content,还有标准模型+IE模型

标准模型和IE模型的区别(后面专门写篇文章比较):

可以参考:https://www.cnblogs.com/ruanxh123/p/5639150.html

CSS如何设置这两种模型?:

box-sizing:context-box;(标准模型,浏览器默认是标准模型)
box-sizing:border-box;(IE模型)

JS如何设置获取盒模型对应的宽和高?:

1.dom.style.width/height(只能取出内联样式设置的宽和高)
2.dom.currentStyle.width/height(只有IE支持)
3.window.getComputedStyle(dom).width/height(其他浏览器也可以用)
4.dom.getBoundingClientRect().width/height(计算元素的绝对位置,left、top、width、height)

实例题(根据盒模型解释边距重叠):

还需要观看视频讲解

BFC(边距重叠解决方案):

a.BFC的基本概念

b.BFC的原理:

1.BFC这个元素的垂直方向的边距会发生重叠
2.BFC的区域不会与浮动元素的box重叠
3.BFC在页面上是一个独立的容器,外面的元素不会影响里面的元素,里面的因素也不会影响外面的元素
4.计算BFC高度的时候,浮动元素也会参与计算

c.如何创建BFC:

参考文章:https://blog.csdn.net/L1651430795/article/details/52016466

1.overflow:hidden、overflow的值不为”visible
2.float的值不为none时,即设置浮动就创建一个BFC、
3.position的值不是static或者relative时就是创建了BFC、
4.display属性“table-cell”, “table-caption”, or “inline-block”中的任何一个

d.BFC的使用场景

讲几个例子。

BFC更多详细介绍参考:

https://www.cnblogs.com/dojo-lzz/p/3999013.html
https://www.cnblogs.com/lhb25/p/inside-block-formatting-ontext.html

BFC使用实例代码:

还需要查看代码视频讲解



  
    
    CSS盒模型
    
  
  
      

1

2

3

我是浮动元素

4.DOM事件

DOM事件最重要是事件原理的掌握(捕获、冒泡的流程)、怎么注册事件(就是监听用户行为)、做响应时Event对象的应用

基本概念:DOM事件的级别

https://www.cnblogs.com/holyson/p/3914406.html

DOM0

element.onclick = function(){}

DOM2

//false指定冒泡或者是捕获
element.addEventListener('click',function{}.false)

DOM3

//事件类型加了很多
element.addEventListener('keyup',function(){},false)

DOM事件模型:

捕获(从上往下)、冒泡(从下往上)

DOM事件流:

可以参考文章:
https://www.cnblogs.com/starof/p/4066381.html
https://www.cnblogs.com/lihongfei0602/p/4062345.html

事件是文档或者浏览器窗口中发生的,特定的交互瞬间。

事件是javaScript和DOM之间交互的桥梁。

事件流描述的是从页面中接收事件的顺序。

问题:单击页面元素,什么样的元素能感应到这样一个事件?
答案:单击元素的同时,也单击了元素的容器元素,甚至整个页面。

事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。

事件传播的顺序对应浏览器的两种事件流模型:捕获型事件流和冒泡型事件流。
冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。即从DOM树的叶子到根。【推荐】
捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。即从DOM树的根到叶子。

事件捕获的思想就是不太具体的节点应该更早接收到事件,而最具体的节点最后接收到事件。

DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段

DOM标准采用捕获+冒泡。两种事件流都会触发DOM的所有对象,从document对象开始,也在document对象结束。

前端面试技巧课程(2)_第3张图片

1.事件捕获阶段:实际目标

在捕获阶段不会接收事件。也就是在捕获阶段,事件从document到再到就停止了。上图中为1~3.
2.处于目标阶段:事件在
上发生并处理。但是事件处理会被看成是冒泡阶段的一部分。
3.冒泡阶段:事件又传播回文档。

描述DOM事件捕获的具体流程:

事件捕获的思想就是不太具体的节点应该更早接收到事件,而最具体的节点最后接收到事件。

前端面试技巧课程(2)_第4张图片

Event对象的常用应用:

Event对象的常见应用:

event.preventDefault() //阻止默认事件
event.stopPropagation() //阻止冒泡
//如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。
//如果其中某个监听函数执行了 event.stopImmediatePropagation() 方法,则当前元素剩下的监听函数将不会被执行。
event.stoplmmediatePropagation()
//currentTarget 事件属性返回其监听器触发事件的节点,即当前处理该事件的元素、文档或窗口。
event.currentTarget()
//target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。
event.target 

currentTarget和target的区别:

举个例子,事件代理中,;我们有十个子元素,我们补不一一给子元素添加事件,而是常给父级元素添加事件,这样当事件触发时,target返回的结果是当前触发事件中父元素的某个子元素,currentTarget就是处理该事件的元素,就是父元素,因为我们是为父元素添加事件响应的。

再看一个例子:




  
  JS Bin


  
  • hello 1
  • hello 2
  • hello 3
  • hello 4

我们知道,e.target可以用来实现事件委托,该原理是通过事件冒泡(或者事件捕获)给父元素添加事件监听,e.target指向引发触发事件的元素,如上述的例子中,e.target指向用户点击的li,由于事件冒泡,li的点击事件冒泡到了ul上,通过给ul添加监听事件而达到了给每一个li添加监听事件的效果,而e.currentTarget指向的是给绑定事件监听的那个对象,即ul,从这里可以发现,e.currentTarget===this返回true,而e.target===this返回false。e.currenttargete.target是不相等的。

更加详细介绍查看:

https://www.cnblogs.com/yewenxiang/p/6171411.html
https://www.jianshu.com/p/1dd668ccc97a
https://www.cnblogs.com/yewenxiang/p/6171411.html

自定义事件/模拟事件:

var eve = new Event();

eve.addEventListener('custom',function(){
	console.log('custome');
});

ev.dispatchEvent(eve);

另一种自定义事件方法:CustomEvent

代码示例:

视频教程还需要看。

事件代理:

参考文章:https://www.cnblogs.com/starof/p/4066381.html

事件流的典型应用-事件代理

传统的事件处理中,需要为每个元素添加事件处理器。js事件代理则是一种简单有效的技巧,通过它可以把事件处理器添加到一个父级元素上,从而避免把事件处理器添加到多个子级元素上。(也是常考的JS优化方法)

具体可以查看上面链接讲解。

5.原型链

创建对象有几种方法:

//第一种方法
var o1 = {name:'01'};
var o11 = new Object({name:'o11'});

//第二种方法
var M = function(){this.name='o2'};
var o2 = new M();

//第三种方法
var P = {name:'o3'};
var o3 = Object.create(P);


  
    
    原型链
  
  

    
  

原型、构造函数、对象实例、原型链:

前端面试技巧课程(2)_第5张图片

//原型链的作用(通过原型链添加属性和方法,实例公用)
M.prototype.say = function () {
          console.log('say hi');
      };
var o5 = new M('o5');

instanceof的原理:

instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置(也就是原型找不到,会去找原型的原型)

instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上(也就是判断实例对象p的.__proto__是否等于构造函数Person的.prototype)

示例:
Person的原型在p的原型链中

function Person(){};
var p =new Person();
console.log(p instanceof Person);//true

//原型的原型也是true
var M = function (name) { this.name = name; };
var o3 = new M('o3');
o3 instance of M //true
o3 instance of Object //true
原理:
o3.__proto__ = M.prototype
M.prototype.__proto__ = Object.prototype

那么同样都是返回true,如何区分是上一个的实例,还是原型的原型的实例呢?
需要constructor

o3.__proto__.constructor === M   //true

instance of更多可以参考:
https://www.cnblogs.com/SourceKing/p/5766210.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof

前端面试技巧课程(2)_第6张图片

new运算符:

前端面试技巧课程(2)_第7张图片

视频还需要再看

var new2 = function (func) {
       var o = Object.create(func.prototype);
       var k = func.call(o);
       if (typeof k === 'object') {
          return k;
       } else {
          return o;
       }
};

6.面向对象

类与实例
类的声明、生成实例

类与继承
如何实现继承、继承的几种方式

继承的本质就是原型链



  
    
    面向对象
  
  
    
  

通过Object.create创建,Child5的实例原型是Child5.prototype,Child5.prototype又等于Object.create()创建的中间对象,这个中间对象的原型对象是Parent5.prototype,这下Child5和Parent5就连接起来了,实现了继承,同时实现了父类和子类的隔离。

Object.create更多资料可以参考:
https://www.cnblogs.com/94pm/p/9113434.html
https://www.cnblogs.com/leijee/p/7490822.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create

7.HTTP协议类

HTTP协议的主要特点、HTTP报文的组成部分、HTTP方法、POST和GET的区别、HTTP状态码、什么是持久连接、什么是管线化

HTTP协议的主要特点:

简单、灵活、无连接、无状态

HTTP报文的组成部分:

前端面试技巧课程(2)_第12张图片

HTTP方法:

GET 获取资源
POST 传输资源
PUT 更新资源
DELETE 删除资源
HEAD 获取报文头部

HTTP中POST和GET的区别:

前端面试技巧课程(2)_第13张图片

上面13569是要记住。

HTTP状态码:

1xx:指示信息-表示请求已接收,继续处理
2xx:成功-表示请求已被成功接收
3xx:重定向-要完成请求必须进行进一步的操作
4xx:客户端错误-请求有语法错误或请求无法实现
5xx:服务器错误-服务器未能实现合法的请求

HTTP常用状态码:

前端面试技巧课程(2)_第14张图片

前端面试技巧课程(2)_第15张图片

管线化:

管线化技术——客户端可以发送多次请求到服务端,而不需要等待上一次请求得到响应的时候才能进行下一次请求。实现并行发送请求。

前端面试技巧课程(2)_第16张图片

前端面试技巧课程(2)_第17张图片

8.通信类

同源策略及限制、前后端如何通信、如何创建Ajax(原生)、跨域通信的几种方式

同源策略及限制:

同源策略限制是指从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。

源包含三个部分:协议、域名、端口

同源策略限制:
1.Cookie、LocalStorage和IndexDB无法读取
2.DOM无法获得
3.Ajax请求不能发送(Ajax不能处理跨域问题)

前后端如何通信:

1.Ajax
2.WebSocket
3.CORS

如何创建Ajax:

1.XMLHttpRequest对象的工作流程
2.兼容性处理
3.事件的触发条件
4.事件的触发顺序

ajax.html



  
    
    通信类
  
  
    

    

    
    
  

jsonp.js

/**
 * 功能类库
 */
 /**
  * [util 工具类]
  * @type {Object}
  */
 var util = {};

 /**
  * [function 返回数组的指定项]
  * @param  {[type]} array [description]
  * @param  {[type]} item  [description]
  * @return {[type]}       [description]
  */
 util.indexOf = function (array, item) {
     for (var i = 0; i < array.length; i++) {
         if (array[i] === item) {
             return i;
         }
     }
     return -1;
 };

 /**
  * [function 判断是否为函数]
  * @param  {[type]} source [description]
  * @return {[type]}        [description]
  */
 util.isFunction = function (source) {
     return '[object Function]' === Object.prototype.toString.call(source);
 };

 /**
  * [isIE 判断是不是ie]
  * @return {Boolean} [如果是ie返回版本号,不是则返回false]
  */
 util.isIE = function () {
     var myNav = navigator.userAgent.toLowerCase();
     return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
 };

 /**
  * [function 对象浅复制]
  * @param  {[type]} dst [description]
  * @param  {[type]} obj [description]
  * @return {[type]}     [description]
  */
 util.extend = function (dst, obj) {
     for (var i in obj) {
         if (obj.hasOwnProperty(i)) {
             dst[i] = obj[i];
         }
     }
 };

 /**
  * [function 获取一个随机的5位字符串]
  * @param  {[type]} prefix [description]
  * @return {[type]}        [description]
  */
 util.getName = function (prefix) {
     return prefix + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
 };

 /**
  * [function 在页面中注入js脚本]
  * @param  {[type]} url     [description]
  * @param  {[type]} charset [description]
  * @return {[type]}         [description]
  */
 util.createScript = function (url, charset) {
     var script = document.createElement('script');
     script.setAttribute('type', 'text/javascript');
     charset && script.setAttribute('charset', charset);
     script.setAttribute('src', url);
     script.async = true;
     return script;
 };

 /**
  * [function jsonp]
  * @param  {[type]} url      [description]
  * @param  {[type]} onsucess [description]
  * @param  {[type]} onerror  [description]
  * @param  {[type]} charset  [description]
  * @return {[type]}          [description]
  */
 util.jsonp = function (url, onsuccess, onerror, charset) {
     var callbackName = util.getName('tt_player');
     window[callbackName] = function () {
         if (onsuccess && util.isFunction(onsuccess)) {
             onsuccess(arguments[0]);
         }
     };
     var script = util.createScript(url + '&callback=' + callbackName, charset);
     script.onload = script.onreadystatechange = function () {
         if (!script.readyState || /loaded|complete/.test(script.readyState)) {
             script.onload = script.onreadystatechange = null;
             // 移除该script的 DOM 对象
             if (script.parentNode) {
                 script.parentNode.removeChild(script);
             }
             // 删除函数或变量
             window[callbackName] = null;
         }
     };
     script.onerror = function () {
         if (onerror && util.isFunction(onerror)) {
             onerror();
         }
     };
     document.getElementsByTagName('head')[0].appendChild(script);
 };

/**
 * [json 实现ajax的json]
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
 util.json = function (options) {
     var opt = {
         url: '',
         type: 'get',
         data: {},
         success: function () {},
         error: function () {},
     };
     util.extend(opt, options);
     if (opt.url) {
         var xhr = XMLHttpRequest
            ? new XMLHttpRequest()
            : new ActiveXObject('Microsoft.XMLHTTP');
         var data = opt.data,
             url = opt.url,
             type = opt.type.toUpperCase(),
             dataArr = [];
         for (var k in data) {
             dataArr.push(k + '=' + data[k]);
         }
         if (type === 'GET') {
             url = url + '?' + dataArr.join('&');
             xhr.open(type, url.replace(/\?$/g, ''), true);
             xhr.send();
         }
         if (type === 'POST') {
             xhr.open(type, url, true);
             xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
             xhr.send(dataArr.join('&'));
         }
         xhr.onload = function () {
             if (xhr.status === 200 || xhr.status === 304) {
                 var res;
                 if (opt.success && opt.success instanceof Function) {
                     res = xhr.responseText;
                     if (typeof res ==== 'string') {
                         res = JSON.parse(res);
                         opt.success.call(xhr, res);
                     }
                 }
             } else {
                 if (opt.error && opt.error instanceof Function) {
                     opt.error.call(xhr, res);
                 }
             }
         };
     }
 };

 /**
  * [function crc32加密]
  * @param  {[type]} str [description]
  * @return {[type]}     [description]
  */
 util.crc32 = function (url) {
     var a = document.createElement('a');
     a.href = url;
     var T = (function () {
         var c = 0,
             table = new Array(256);
         for (var n = 0; n != 256; ++n) {
             c = n;
             c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
             c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
             c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
             c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
             c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
             c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
             c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
             c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
             table[n] = c;
         }
         return typeof Int32Array !=== 'undefined' ? new Int32Array(table) : table;
     })();
     var crc32_str = function (str) {
         var C = -1;
         for (var i = 0, L = str.length, c, d; i < L;) {
             c = str.charCodeAt(i++);
             if (c < 0x80) {
                 C = (C >>> 8) ^ T[(C ^ c) & 0xFF];
             } else if (c < 0x800) {
                 C = (C >>> 8) ^ T[(C ^ (192 | ((c >> 6) & 31))) & 0xFF];
                 C = (C >>> 8) ^ T[(C ^ (128 | (c & 63))) & 0xFF];
             } else if (c >= 0xD800 && c < 0xE000) {
                 c = (c & 1023) + 64;
                 d = str.charCodeAt(i++) & 1023;
                 C = (C >>> 8) ^ T[(C ^ (240 | ((c >> 8) & 7))) & 0xFF];
                 C = (C >>> 8) ^ T[(C ^ (128 | ((c >> 2) & 63))) & 0xFF];
                 C = (C >>> 8) ^ T[(C ^ (128 | ((d >> 6) & 15) | ((c & 3) << 4))) & 0xFF];
                 C = (C >>> 8) ^ T[(C ^ (128 | (d & 63))) & 0xFF];
             } else {
                 C = (C >>> 8) ^ T[(C ^ (224 | ((c >> 12) & 15))) & 0xFF];
                 C = (C >>> 8) ^ T[(C ^ (128 | ((c >> 6) & 63))) & 0xFF];
                 C = (C >>> 8) ^ T[(C ^ (128 | (c & 63))) & 0xFF];
             }
         }
         return C ^ -1;
     };
     var r = a.pathname + '?r=' + Math.random().toString(10).substring(2);
     if (r[0] != '/') {
         r = '/' + r;
     }
     var s = crc32_str(r) >>> 0;
     var is_web = location.protocol.indexOf('http') > -1;
     return (is_web ? [location.protocol, a.hostname] : ['http:', a.hostname]).join('//') + r + '&s=' + s;
 };

 export default util;

跨域通信的几种方式:

JSONP
Hash
postMessage
WebSocket
CORS

问题:JSONP的原理和实现
回答:上面几种方式实现原理还需要看视频教程,源码是上面JSONP.js的代码

9.安全类

CSRF、XSS、SQL注入

CSRF:

基本概念和缩写
攻击原理
防御措施

CSRF(Cross-site request forgery),跨站请求伪造,攻击原理如下:

前端面试技巧课程(2)_第18张图片

CSRF防御措施:
Token验证
Referer验证(验证来源)
隐藏令牌

XSS:

XSS(cross-site scripting)跨域脚本攻击

攻击原理:https://www.imooc.com/learn/812

攻击措施:https://www.imooc.com/learn/812

SQL注入:*

可以参考:https://www.imooc.com/learn/883

10.算法类

排序、堆栈、队列、链表、递归、波兰式和逆波兰式

排序:

冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序、等等

前端面试技巧课程(2)_第19张图片

主要记忆:

快速排序(https://segmentfault.com/a/1190000009426421)、
选择排序(https://segmentfault.com/a/1190000009366805)、
希尔排序(https://segmentfault.com/a/1190000009461832)

堆栈、队列、链表:

堆栈:https://juejin.im/entry/58759e79128fe1006b48cdfd

队列:https://juejin.im/entry/58759e79128fe1006b48cdfd

链表:https://juejin.im/entry/58759e79128fe1006b48cdfd

更多可以参考:http://huang303513.github.io/index.html

递归:

递归:https://segmentfault.com/a/1190000009857470

波兰式和逆波兰式:

波兰式和逆波兰式:

理论:http://www.cnblogs.com/chenying99/p/3675876.html

源码:https://github.com/Tairraos/rpn.js/blob/master/rpn.js

技巧:能写多少是多少、可以适时请教面试官、真的不知道怎么写可以说可以用哪个算法其中原理是什么

你可能感兴趣的:(前端)