html部分
- (必考) 你是如何理解 HTML 语义化的?
最开始的时候是PHP后端不会用CSS编写HTML,他们用table来进行网页布局。这严重违反了HTML的语义。后来就出现了会css的前端,他们用flaot和绝对定位进行网页布局,稍微符合了HTML语义化的要求。再后来,前端专业化,他们 了解HTML的个标签的作用,用h1,p,aside,main等语义化标签进行编写页面,而不是单纯的div。 - meta viewport 是做什么用的,怎么写?
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
一开始所有的网页都是给pc准备的,后来乔布斯推出iPhone 3gs,页面是不适应手机屏幕的,苹果的工程是想了一个办法,将手机屏幕模拟成980px的网页。页面进行对应的缩放,在后来随着智能手机的普及,这个方法部分网站不需要了,所以我们就是用标签告诉设备不要缩放我们的网页。
- canvas 元素是干什么的?
是 HTML5 新增的元素,可用于通过使用JavaScript中的脚本来绘制图形。例如,它可以用于绘制图形,制作照片,创建动画,甚至可以进行实时视频处理或渲染。
我用canvas做过一个小项目canvas小画板
css部分
-
盒模型
两种盒模型:1.content-box: width=content 2.border-box: width=content+padding+border (兼容性要求不高的用,直接设置*{box-sizing:border-box})
-
reset.css重制样式,消除因每个浏览器自带的默认样式带来的样式不统一.normalize.css标准化css样式,使所有浏览器的样式基本统一.
-
css实现居中
水平居中:
内联元素:父元素加上:text-align:center 块级元素:margin:0 auto
垂直居中:
1.tabel标签自带的,会使子元素垂直居中 2.使用伪元素. .parent:before{ display:inline-block; height"100%; vertical-align: middle;} .son{ display:inline-block; height"100%; vertical-align: middle; } .parent:after{ display:inline-block; height:100%; vertical-align: middle; } 3.对父元素使用display:table,子元素使用dispaly:table-row: .parent{ display:table; } .tr{ display:table-row; } .td{ display:table-cell; } 4.使用绝对定位position:absolute;(使用margin或者transform: translate(-50%,-50%);) .parent{ height: 600px; position: relative; } .child{ width: 300px; position: absolute; top: 50%; left: 50%; margin-left: -150px; height: 100px; margin-top: -50px; } 5.使用transform .parent{ height: 600px; position: relative; } .child{ position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); } 6.flex布局实现水平垂直的居中
4.优先级
1.选择器越具体优先级越高 2.优先级相同,后面的会覆盖掉前面的 3.!important优先级最高
-
Formatting context(格式化上下文BFC)
具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。1.避免外边距的合并 2.清除浮动 .clearfix:after{ display:block; content:'', clear:both; } 3.阻止元素被浮动元素覆盖
-
清除浮动
.clearfix:after{ content:''; display:block; clear:both } .clearfix{zoom:1;}//兼容ie
js部分
参考:https://juejin.im/post/5c6ad9fde51d453c356e37d1?utm_source=gold_browser_extension
- ES6语法知道哪些,分别怎么用
参考:https://juejin.im/entry/58f21df95c497d006c87469e - 循环与setTimeout结合题目
for( var i =0 ; i < 10; i++ ){
setTimeout(() => {
console.log(i)
},10)
}
// 输出 10个10
使用立即执行函数或者let声明i
for (var i = 0; i < 10; i++) {
((i) => {
setTimeout(function() { console.log(i); }, 100 * i);
})(i);
}
or
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i)
},10)
}
-
函数防抖和函数节流
节流例子:
let cd =false; button.onclick=()=>{ if(cd){ // }else{ fn(); cd=true; let timerId=setTimeout(()=>{ cd=false; },3000) } }
防抖:
let timerId=null; button.onclick=function(){ if(timerId){ window.clearTimeout(timerId) }else{ fn(); timerId=null; } }
-
js七中数据类型:
string number bool undefined null object symbal
-
promise
let request=new Promise((resolve,reject)=>{ if(ok){ resolve() }else{ reject() } })
Promise.all(iterable) 方法返回一个 Promise 实例,只有iterable中的所有promise都resolve,该函数才会resolve;iterable中若有一个promise时reject,则返回reject;iterable为空则返回resolve
Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise,resolve或reject,返回的 promise就会resolve或reject。
var promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(reject, 100, 'two');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value);
// Both resolve, but promise2 is faster
},function(value) {
console.log(value);
// Both resolve, but promise2 is faster
});
-
手写一个AJAX
var request= new XMLHttpRequest() request.open('GET','path') request.onreadystatechange=()=>{ if(request.readystate===4&&request.status<400){ console.log('ok') }else{ console.log('error') } } request.send();
-
闭包
防止内存泄露
举例子:function add(){ let a=4; return function (){ a++ } } let adder=add(); adder()
-
this的指向
this===‘undefined’ =>window
obj.fn() =>obj
()=>{} =>外面的this
new Object()=>实例
fn.call(xx) =>xx
fn.apply(xx)=>xx
fn.bind(xx)=>xx
正确参考:https://zhuanlan.zhihu.com/p/23804247
-
立即执行函数
!function(){}() (function(){})()
目的:造出一个函数作用域,防止污染全局变量
-
async/await 语法了解吗?目的是什么?
let promise=()=>{ return new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve('1') },200) }) } async function promise2(){ let result =await promise(); console.log(result) console.log('2') } promise2(); //1,2
目的:把异步代码写成同步代码。
-
捕获异常
try{ }catch(err){ console.log(err.message) }
-
如何实现深拷贝
i.Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象. var x = { a: 1, b: { f: { g: 1 } }, c: [ 1, 2, 3 ] }; var y = Object.assign({}, x); console.log(y.b.f === x.b.f); // true ii.Array的concat()和slice() iii.JSON对象的 let newobject=JSON.parse(JSON.stringify(object)) 缺点:json不支持函数\undefined\Date\正则..... iiii.用递归实现深拷贝 function clone(object){ var object2 if(! (object instanceof Object) ){ return object }else if(object instanceof Array){ object2 = [] }else if(object instanceof Function){ object2 = eval(object.toString()) }else if(object instanceof Object){ object2 = {} } for(let key in object){ object2[key] = clone(object[key]) } return object2 }
-
去除字符串的空格
//去除首尾空格 1.str.trim() 2.正则 function trim(str){ return str.replace(/^\s+|s+$/g,'') } //去掉所有空格,包括首尾、中间 3.str.replace(" ", "");
-
数组的去重
i.indexof() let arr2 for(let i=0;i<arr.length;i++){ if(arr.indexof(arr[i])===i){ arr2[i]=arr[i] } } ii.计数排序去重(只能是正整数) let hash={} for(let i=0;i<arr.length;i++){ if(arr[i] in hash){} else{hash[arr[i]=true} } let arr2=hash.keys()//此时数组的每一项都是字符串 arr2.map(()=>{}) iii.set对象 let arr2=Array.from(new Set(arr))
-
原型原型链https://blog.csdn.net/wang_liuyong/article/details/82747120
-
继承
i.es5实现继承 function Human(){ this.a=1; } function fn (){}; fn.prototype=Human.protype; function Man(){ Human.apply(this,arguments); this.b=2; } Man.protype=new fn(); Man.protype.construct=Man ii.es6的class实现继承 class Human{ constructor(name){ this.name = name } run(){ console.log("我叫"+this.name+",我在跑") return undefined } } class Man extends Human{ constructor(name){ super(name) this.gender = '男' } fight(){ console.log('糊你熊脸') } }
dom题目
-
dom事件模型
i.事件的冒泡: ii.事件的捕捉,发生事件时,一般是先捕获后冒泡 iii.如果是监听元素是被点击的元素,则捕获和冒泡的顺序是由监听的顺序决定的的
-
移动端的触摸事件有哪些
touchstart: //手指放到屏幕上时触发 touchmove: //手指在屏幕上滑动式触发 touchend: //手指离开屏幕时触发 touchcancel: //系统取消touch事件的时候触发
https://segmentfault.com/a/1190000009884458
ii.模拟 swipe 事件:记录两次 touchmove 的位置差,如果后一次在前一次的右边,说明向右滑了。
-
手写一个拖拽函数
https://jsbin.com/yudevasiyu/10/edit?html,js,outputvar drgging=false; var position=null; drg.addEventListener('mousedown',(e)=>{ drgging=true; position=[e.clientX,e.clientY] }) document.addEventListener('mousemove',(e)=>{ if(drgging){ drg.style.left=e.clientX-position[0]+'px'; drg.style.top=e.clientY-position[1]+'px'; console.log(drg.style.left) } }) drg.addEventListener('mouseup',(e)=>{ drgging=false; })
3.事件委托
i.将监听器绑定在父元素上,看触发事件是哪个子元素,然后执行对应的函数
ii.可以监听动态生成的子元素,节省监听器
function listern(element,eventType,selector,fn){
element.addEventListener(eventType,(e)=>{
if(e.currentTarget.matches(selector)){
fn.call(el,e)
}
})
}
http题目
-
http常用的状态码有哪些
//请求成功 200 请求成功 //需要进一步处理 301 永久重定向 302 临时重定向 //客户端出错 400 bad request 404 找不到页面 //服务器出错 500 服务器错误
http的缓存机制
参考:https://blog.csdn.net/eroswang/article/details/8302191
-
Etag 服务器响应时给请求URL标记
HTTP协议规格说明定义ETag为“被请求变量的实体标记”(参见14.19)。简单点即服务器响应时给请求URL标记,并在HTTP响应头中将其传送到客户端,类似服务器端返回的格式: Etag:“5d8c72a5edda8d6a:3239″ 客户端的查询更新格式是这样的: If-None-Match:“5d8c72a5edda8d6a:3239″ 如果ETag没改变,则返回状态304。 即:在客户端发出请求后,HttpReponse Header中包含Etag:“5d8c72a5edda8d6a:3239″ 标识,等于告诉Client端,你拿到的这个的资源有表示ID:5d8c72a5edda8d6a:3239。当下次需要发Request索要同一个URI的时候,浏览器同时发出一个If-None-Match报头(Http RequestHeader)此时包头中信息包含上次访问得到的Etag:“5d8c72a5edda8d6a:3239″标识。 If-None-Match:“5d8c72a5edda8d6a:3239“ ,这样,Client端等于Cache了两份,服务器端就会比对2者的etag。如果If-None-Match为False,不返回200,返回304(Not Modified) Response。
-
Expires
给出的日期/时间后,被响应认为是过时。如Expires:Thu, 02 Apr 2009 05:14:08 GMT, bug:用户可以通过更改本地时间来控制缓存
-
Cache-control(控制缓存)web性能优化/但是不会存储用户信息
1.可以在服务器的路由里设置响应头response.setHeader(‘Cache-Control’,’max-age=30’)浏览器在响应头里发现这个设置会30秒内不重新加载(必须是相同的URL才能缓存) 2.一般来说不给首页设置缓存 3.可以通过更改URL来重新加载缓存过的数据 Etag是请求之后,发现该资源已经响应过且没有被修改,服务器返回304;如果发现资源不一样才会返回相应的请求的的资源 Cache-Control 是读取本地缓存不会重新发送请求
-
cookie 一般4k左右
1.cookie是http请求响应中的一部分 2.服务器通过Set-Cookie头给客户端一段字符串 3.客户端每次访问相同的域名网页时必须带上这段字符串 4.客户端在一段时间内保存这个Cookie 5.cookie默认在用户关闭页面时失效,但是后端可以设置cookie的有效期
-
session
session是基于cookie实现的,因为cookie传输的数据是明文的,所以就通过session加密,将用户数据存在服务器上session内存里,通过id来找出对应的cookie 1.将sessionId(随机数)通过cookie发给客户端 2.客户端访问服务器时,服务器读取sessionID 3.服务器有一块内存(哈希表),保存了所有的session 4.通过sessionID我们可以获取对应用户的隐私信息,如ID、email 5.这块内存(哈希表)就是服务器上所有的session
-
localStorage(操作本地存储)
1.html5技术提供的一个API 2.window.localStorage.getItem/window.localStorage.setItem/window.localStorage.removeItem/window.localStorage.clear 3.localStorage是一个浏览器上的hash 4.session是服务器上的一个hash 5.localStorage存的是字符串,长和JSON一起使用(1.JSON.parse()2.JSON.stringify) 用法 1.跨页面记录数据 let prompt=localStorage.getItem(‘prompt’); if(!prompt){ alert(‘你好’); localStorage.setItem(‘prompt’,true); } 特点: 1.localStorage跟http无关 2.http不会带上loclStorage的值 3.只有相同域名的页面才能读取localStorage 4.每个页面的localStorage最大存储量为5mb左右(每个浏览器不一样) 5.常用场景:记录一些不敏感的信息如:是否已经提示过,不能记录一些私密信息安全信息 6.不会过期,只能手动清除
-
sessionStorage
1.2.3.4.5同上 6.在用户关闭页面时失效
必考)GET 和 POST 的区别是什么?
参数:GET 的参数放在 url 的查询参数里,POST 的参数(数据)放在请求消息体里。
GET 的参数(url查询参数)有长度限制,一般是 1024 个字符。
POST 的参数(数据)没有长度限制(扯淡,4~10Mb 限制)
安全:GET 没有 POST 安全(都不安全)
包:GET 请求只需要发一个包,POST 请求需要发两个以上包(因为 POST 有消息体)
语义:GET 获取数据,POST 提交数据,POST 不幂等(幂等的意思就是不管发多少次请求,结果都一样。)
(必考)怎么跨域?JSONP 是什么?CORS 是什么?postMessage 是什么?
https://blog.csdn.net/wang_liuyong/article/details/81569383
JSONP
CORS
postMessage 看一下 MDN
vue押题
-
watch 和 computed 以及methods的区别
computed 和 methods 相比,最大区别是 computed 有缓存: 如果 computed 属性依赖的属性没有变化, 那么 computed 属性就不会重新计算。methods 则是看到一次计算一次。 watch 和 computed 相比,computed 是计算出一个属性, 而 watch 则可能是做别的事情(如上报数据)
-
Vue 有哪些生命周期钩子函数?分别有什么作用?
//组件创建 beforeCreate created //组件挂载 beforeMount mounted //此时发送请求 //组件更新 beforeUpdate updated //组件销毁 beforeDestroy destroyed
-
vue的数据响怎么做到的?原理?
v-model 当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter; 注意:受到Object.defineProperty属性的限制,Vue 不能检测到对象属性的添加或删除,所以需要向的数据,必须添加一个初始值; 可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上(vm.$set也行)
-
vue组件之间的通信
父子组件:使用 v-on 通过事件通信 爷孙组件:使用两次 v-on 通过爷爷爸爸通信,爸爸儿子通信实现爷孙通信 任意组件:使用 eventBus = new Vue() 来通信,eventBus.$on 和 eventBus.$emit 是主要API provide/inject 任意组件:使用 Vuex 通信
-
vuex
vuex仅仅是一个管理状态的工具,保证状态可以以一种可以预测的方式发生变化,并没有任何永久存储的功能。
页面刷新最终解决办法还是h5缓存.
vuex只是将页面的某个状态存在全局,一个state内,当页面刷新,还是用h5的缓存保存state的上的值而已。
vuex就相当于一个全局变量,
实现思路:
i.export default new Vuex.store({})新建一个store 仓库
ii.在跟组件中注册该仓库,new vue ({
el:’#app’,
store,
})
这样store就会注入到所有子组件中,子组件可以通过this.$store来访问到该仓库
iii.通过mapAction()将store中提交更改状态的方法映射到子组件中,子组件通过映射的方法来更改整个项目的状态 -
VueRouter
Vue Router 是 Vue.js 官方的路由管理器。重定向别名: “重定向”的意思是,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b /a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样 导航守卫: router.beforeEach((to, from, next) => { // ... }) 懒加载: const Foo = () => Promise.resolve({ /* 组件定义对象 */ }) import('./Foo.vue') // 返回 Promise
react
-
受控组件 V.S. 非受控组件
<FInput value={x} onChange={fn}/> 受控组件 <FInput defaultValue={x} ref={input}/> 非受控组件 区别受控组件的状态由开发者维护,非受控组件的状态由组件自身维护(不受开发者控制
-
React 有哪些生命周期函数?分别有什么用?(Ajax 请求放在哪个阶段?)
-
React 如何实现组件间通信?
1.父子靠 props 传函数 2.爷孙可以穿两次 props 3.任意组件用 Redux(也可以自己写一个 eventBus)
-
shouldComponentUpdate 有什么用?
用于在没有必要更新 UI 的时候返回 false,以提高渲染性能
-
虚拟 DOM 是什么?
-
什么是高阶组件?
-
React diff 的原理是什么?
-
Redux 是什么?
-
connect 的原理是什么?
6.12面试题目总结
异步相关
for(ver i=0;i<10;i++){ setTimeout()=>{ consoel.log(i)}}
以上代码输出的结果
答案:
输出