来自慕课课程:前端跳槽面试必备技巧
1.一面/二面 面试技巧
面试技巧:准备要充分、知识要系统、沟通要简介、内心要诚实、态度要谦虚、回答要灵活
通信:跨域、前后端通信
安全:CSRF、XSRF、XSS
2.页面布局
题目:假设高度已知,请写出三栏布局,其中左栏、右栏宽度各为300px,中间自适应
答案:浮动解决方案、绝对定位解决方案、flexbox解决方案、表格布局解决方案、网格布局解决方案
引申思考:
1.各个方法的优缺点
2.假设高度已知去掉,不再只考虑水平方向,还要考虑中间高度问题,例如中间的内容有点多,撑开了,上面哪个方案还可以适应。
3.五个方案的浏览器兼容性如何?
4.实际应用中,哪个方案最优?
浮动布局常见问题是清除浮动,优点是兼容性比较好。
绝对定位好处是快捷,本身脱离文档流了,要求下面的定位要注意定位好位置,可使用性比较差。
Flex布局常用于移动端,针对上面两个布局不足提出的布局方案。
表格布局其实在一些场景很适应的,表格布局兼容性也不错,还有缺点是,三栏高度一个变化时另外两个也会变化。
网格布局借鉴CSS栅格,可以对比比较。
假设高度已知去掉,Flex和表格布局还可以用。
如果要求上图中间的字不往两边扩展,只显示在中间,解决方案是:BFC
页面布局小结:
1.语义化掌握到位
2.页面布局理解深刻
3.CSS基础知识扎实
4.思维灵活且积极向上
5.代码书写规范
常见布局:(可作为思考题)
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
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对象结束。
1.事件捕获阶段:实际目标 描述DOM事件捕获的具体流程: 事件捕获的思想就是不太具体的节点应该更早接收到事件,而最具体的节点最后接收到事件。 Event对象的常用应用: Event对象的常见应用: currentTarget和target的区别: 举个例子,事件代理中,;我们有十个子元素,我们补不一一给子元素添加事件,而是常给父级元素添加事件,这样当事件触发时,target返回的结果是当前触发事件中父元素的某个子元素,currentTarget就是处理该事件的元素,就是父元素,因为我们是为父元素添加事件响应的。 再看一个例子: 我们知道, 更加详细介绍查看: https://www.cnblogs.com/yewenxiang/p/6171411.html 自定义事件/模拟事件: 另一种自定义事件方法:CustomEvent 代码示例: 视频教程还需要看。 事件代理: 参考文章:https://www.cnblogs.com/starof/p/4066381.html 事件流的典型应用-事件代理 传统的事件处理中,需要为每个元素添加事件处理器。js事件代理则是一种简单有效的技巧,通过它可以把事件处理器添加到一个父级元素上,从而避免把事件处理器添加到多个子级元素上。(也是常考的JS优化方法) 具体可以查看上面链接讲解。 5.原型链 创建对象有几种方法: 原型、构造函数、对象实例、原型链: instanceof的原理: instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置(也就是原型找不到,会去找原型的原型) instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上(也就是判断实例对象p的 示例: 那么同样都是返回true,如何区分是上一个的实例,还是原型的原型的实例呢? instance of更多可以参考: new运算符: 视频还需要再看 6.面向对象 类与实例 类与继承 继承的本质就是原型链 通过Object.create创建,Child5的实例原型是Child5.prototype,Child5.prototype又等于Object.create()创建的中间对象,这个中间对象的原型对象是Parent5.prototype,这下Child5和Parent5就连接起来了,实现了继承,同时实现了父类和子类的隔离。 Object.create更多资料可以参考: 7.HTTP协议类 HTTP协议的主要特点、HTTP报文的组成部分、HTTP方法、POST和GET的区别、HTTP状态码、什么是持久连接、什么是管线化 HTTP协议的主要特点: 简单、灵活、无连接、无状态 HTTP报文的组成部分: HTTP方法: GET 获取资源 HTTP中POST和GET的区别: 上面13569是要记住。 HTTP状态码: 1xx:指示信息-表示请求已接收,继续处理 HTTP常用状态码: 管线化: 管线化技术——客户端可以发送多次请求到服务端,而不需要等待上一次请求得到响应的时候才能进行下一次请求。实现并行发送请求。 8.通信类 同源策略及限制、前后端如何通信、如何创建Ajax(原生)、跨域通信的几种方式 同源策略及限制: 同源策略限制是指从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。 源包含三个部分:协议、域名、端口 同源策略限制: 前后端如何通信: 1.Ajax 如何创建Ajax: 1.XMLHttpRequest对象的工作流程 ajax.html jsonp.js 跨域通信的几种方式: JSONP 问题:JSONP的原理和实现 9.安全类 CSRF、XSS、SQL注入 CSRF: 基本概念和缩写 CSRF(Cross-site request forgery),跨站请求伪造,攻击原理如下: CSRF防御措施: 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.算法类 排序、堆栈、队列、链表、递归、波兰式和逆波兰式 排序: 冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序、等等 主要记忆: 快速排序(https://segmentfault.com/a/1190000009426421)、 堆栈、队列、链表: 堆栈: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 技巧:能写多少是多少、可以适时请教面试官、真的不知道怎么写可以说可以用哪个算法其中原理是什么(
再到
就停止了。上图中为1~3.
2.处于目标阶段:事件在
3.冒泡阶段:事件又传播回文档。
event.preventDefault() //阻止默认事件
event.stopPropagation() //阻止冒泡
//如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。
//如果其中某个监听函数执行了 event.stopImmediatePropagation() 方法,则当前元素剩下的监听函数将不会被执行。
event.stoplmmediatePropagation()
//currentTarget 事件属性返回其监听器触发事件的节点,即当前处理该事件的元素、文档或窗口。
event.currentTarget()
//target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。
event.target
e.target
可以用来实现事件委托,该原理是通过事件冒泡(或者事件捕获)给父元素添加事件监听,e.target
指向引发触发事件的元素,如上述的例子中,e.target
指向用户点击的li
,由于事件冒泡,li
的点击事件冒泡到了ul
上,通过给ul添加监听事件而达到了给每一个li
添加监听事件的效果,而e.currentTarget
指向的是给绑定事件监听的那个对象,即ul
,从这里可以发现,e.currentTarget===this
返回true,而e.target===this
返回false。e.currenttarget
和e.target
是不相等的。
https://www.jianshu.com/p/1dd668ccc97a
https://www.cnblogs.com/yewenxiang/p/6171411.htmlvar eve = new Event();
eve.addEventListener('custom',function(){
console.log('custome');
});
ev.dispatchEvent(eve);
//第一种方法
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);
//原型链的作用(通过原型链添加属性和方法,实例公用)
M.prototype.say = function () {
console.log('say hi');
};
var o5 = new M('o5');
.__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
需要constructoro3.__proto__.constructor === M //true
https://www.cnblogs.com/SourceKing/p/5766210.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceofvar new2 = function (func) {
var o = Object.create(func.prototype);
var k = func.call(o);
if (typeof k === 'object') {
return k;
} else {
return o;
}
};
类的声明、生成实例
如何实现继承、继承的几种方式
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
POST 传输资源
PUT 更新资源
DELETE 删除资源
HEAD 获取报文头部
2xx:成功-表示请求已被成功接收
3xx:重定向-要完成请求必须进行进一步的操作
4xx:客户端错误-请求有语法错误或请求无法实现
5xx:服务器错误-服务器未能实现合法的请求
1.Cookie、LocalStorage和IndexDB无法读取
2.DOM无法获得
3.Ajax请求不能发送(Ajax不能处理跨域问题)
2.WebSocket
3.CORS
2.兼容性处理
3.事件的触发条件
4.事件的触发顺序
/**
* 功能类库
*/
/**
* [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;
Hash
postMessage
WebSocket
CORS
回答:上面几种方式实现原理还需要看视频教程,源码是上面JSONP.js的代码
攻击原理
防御措施
Token验证
Referer验证(验证来源)
隐藏令牌
选择排序(https://segmentfault.com/a/1190000009366805)、
希尔排序(https://segmentfault.com/a/1190000009461832)