待做
- 链接1
- 链接2
- 链接4
- 链接5
- 链接6
- 链接7
- 链接8
框架出处:
套路
- 举例
- 将不会的变成会的
- 侃侃而谈
HTML 押题
-
你是如何理解 HTML 语义化的 第一种举例, 段落用 p, 边栏用 aside, 主要内容用 main 标签。
header、nav 、article 、section 、aside 、footer
第二种举例,在很早之前,一部分同事在写html时,喜欢用 table 来布局。 table 是用来展示表格的。这其实违反了 HTML 语义化 后来有了专门写 css 的前端,他们会使用 DIV+CSS 布局,主要是用 float 和 绝对定位布局。已经有了 HTML 语义化的意思。 最后,专业化的前端希望使用恰当的标签来展示内容。而不是全用div,会尽量使用 nav, header, aside, h1, ul, p, main 等标签。
第三种,对面试官说请看[我的博客]//
-
meta viewport 是做什么用的,怎么写?
死背: 控制页面在移动端不要缩小显示
复制代码
一开始,所有页面都是给手机准备的, 乔布斯推出 iphone 3GS, 页面是不适应手机屏幕的,所以乔布斯的工程师想了一个办法,默认把手机模拟成980px,页面缩小。后来, 智能手机开始普及,这个功能在部分网站b谁需要了,所以我们就用 meta:vp 让手机不要缩小我的网页。
-
canvas 元素是干什么的?
MDN 的 canvas
画板项目:
CSS 押题
- (必考) 说说盒模型
-
举例
context-box: width == 内容区宽度
border-box: width == 内容区宽度 + padding + border
- css reset 和 normalize.css 有什么区别
- 考英语:
- reset 重置, 之前的样式我不要, a{color: red;}, 抛弃默认样式
- normalize 让所有浏览器的标签都跟标准规定的默认样式一致,各浏览器上的标签默认样式基本统一。
-
(必考) 如何居中
- 平时总结
- 水平居中:
- 内联:父元素上写 ta:c;
- 块级:ml: a; mr: a;
- 垂直居中:
- 水平居中:
- 平时总结
-
选择器的优先级如何确定?
- 选择器越具体,优先级越高。 #yyy > .yyy
- 相同优先级,写在后面的覆盖写在前面的。
- color: red!important; 优先级最高。 想办法把他们写的差不多长。
-
BFC 是什么
- 举例:
- o:h 清除浮动 但是对于清楚浮动有更好的方法 .clearfix 最好不要用 o:h 来清除浮动
- o:h 取消父子 margin 合并 也有别的方式解决,padding-top: .1px
- 举例:
-
如何清除浮动
- o:h (并不是一种特别好的解决方案)
- .clearfix 写在父元素上
.clearfix::after { content: ''; display: block; clear: both; } .clearfix { zoom: 1; /* IE 兼容 */ }复制代码
JS 押题
-
JS 有哪些数据类型
string, number, bool, undefined, null, object, symbol
object 包含了数组,函数, 正则,日期等对象
一旦出现(数组、函数、正则、日期、NaN) 直接滚
-
(必考)Promise 怎么使用
- then
$.ajax().then(成功函数, 失败函数)复制代码
- 链式 then
$.ajax().then(成功函数, 失败函数).then(成功函数2, 失败函数2)复制代码
- 如何自己生成 Promise 对象
function xxx() { return new Promise(function(resolve, reject) { setTimeout(() => { resolve() 或者 reject() }, 3000) }) } xxx.then()复制代码
- then
-
(必考) 手写一下 Ajax?
答对不加分,打错直接滚
let ajax = function(method, path, headers, data, responseCallback) { // frank fang let xhr = new XMLHttpRequest() xhr.open('POST', '/xxxx') xhr.onreadystatechange = function() { if(xhr.readyState = 4 && xhr.status === 200) { responseCallback() // log(xhr.responseText) } } xhr.send() }复制代码
-
(必考) 闭包是啥
function getAdder() { let n = 0 return function () { n += 1 } } let adder = getAdder() adder() // n === 1 adder() // n === 2 console.log(n) // n is not defined复制代码
-
这段代码中的 this 指的是?
- fn() 里面的 this 就是 window
- fn() 是 strict mode , this 就是 undefined
- a.b.c.fn() 里面的 this 就是 a.b.c
- new Fn() 里面的 this 就是新生成的实例
- () => {console.log(this)} 箭头函数不改变 this 的指向
-
(必考) 什么是立即执行函数? 使用立即执行函数的目的是什么
;(function() { var neme}()) ;(function() { var neme})() !!!!!!function() { var neme}() ~function() { var neme}() 复制代码
制造出一个函数作用域, 防止全局污染
ES 6 新语法
{ let name}复制代码
-
async/awit 语法了解么? 目的是什么?
function returnPromise() { return new Promise(function(resolve, reject) { setTimeout(()=>{ resolve('guakun') }, 3000) }) } returnPromise().then((result) => { result === 'guakun' }) let result = await returnPromise() result === 'guakun'复制代码
目的是把异步代码写成同步
-
如何实现深拷贝
i. 通过 JSON
let a = {} let b = JSON.parse(JSON.stringify(a))复制代码
缺点: JSON 不支持函数、引用、undefined、RegExp、Date
ii. 递归拷贝
function getType(obj) { let toString = Object.prototype.toString let map = { '[object String]' : 'string', '[object Number]' : 'number', '[object Boolean]' : 'boolean', '[object Undefined]' : 'undefined', '[object Null]' : 'null', '[object Object]' : 'object', '[object Function]' : 'function', '[object Array]' : 'array', '[object Date]' : 'date', '[object RegExp]' : 'regExp', } if (obj instance Element) { return 'element' } return map[toString.call(obj)] } function deepClone(obj) { let obj2 let type = getType(obj) if( type === 'array') { obj2 = [] for (let index = 0; index < obj.length; index++) { obj2.push(deepClone(obj[i])) } } else if (type ==== 'object') { obj2 = {} for( let key in obj) { ohj2[key] = deepClone(obj[key]) } } else { return data } return obj2 }复制代码
iii. 环
iv. RegExp、Date、Set、Symbol、WeakMap
-
如何实现数组去重
i. 计数排序的逻辑(局限于正整数)
let a = [4, 2, 5, 6, 3, 5, 4] let hashtab = {} for(let index = 0; index < a.length; index++) { if(! a[index] in hashTab) { hashTab[a[index]] = true } } console.log(Object.keys(hashTab)) function getInt(arr) { let newArr = [] newArr = arr.map((item) => item-0) return newArr } console.log(getInt(Object.keys(hashTab)))复制代码
ii. Set 去重
Array.from(new Set(a))复制代码
iii. WeakMap
-
如何使用正则实现 string.trim()?
function trim(string) { return string.replace(/^\s+|\s+$/g, '') } 复制代码
-
JS 原型是什么?
举例
a. let a = [1, 2, 3]
b. 只有 1,2,3, length 4个key
c. 为什么可以 a.push(), push怎么来的
d. a.proto = Array.prototype
e. push 就是沿着 a.proto 找到的, 也就是 Array.prototype.push
f. Array.prototype 还有很多方法, 如 join、pop、slice、splice
g.Array.prototype 就是 a 的原型 (proto)
-
ES6 中的 class 了解么?
- 把 mdn 的 class 章节看完
- 掌握一个例子
补充一个
-
JS 如何实现继承
- 原型链
function Animal() { this.body = 'body' } Animal.prototype.move = function() { console.log('move') } function Human(name) { Animal.apply(this, arguments) this.name = name } // Human.prototype._proto_ = Animal.prototype // 非法 let f = function() {} f.prototype = Animal.prototype Human.prototype = new f() Human.prototype.useTools = function() { console.log('use tools') } let guakun = new Human('guakun')复制代码
- 使用 extends 关键字
class Animal{ constructor(){ this.body = 'body' } move() { console.log('move') }}class Human extends Animal { constructor(name) { super() this.name = name } useTools() { console.log('use tools') }}let guapi = new Human('guapi')复制代码
-
所有 == 的问题 反着答(弃疗)
DOM 押题
-
DOM 事件的模型是什么?
- 冒泡
- 捕获
-
移动端的触摸事件了解么?
i. touchstart touchmove touchend touchcancle
ii. 模拟 swipe 事件:记录两次 touchmove 的位置差,如果后一次在前一次的右边,说明右滑了。(忽然想到轮播 css js)
-
事件委托是什么?有什么好处?
i. 假设父元素有 4 个儿子, 我不监听这四个儿子, 而是监听父元素,看触发事件的是哪个儿子, 这就是事件委托。
ii. 可以监听尚未出生的儿子(动态生成的元素) 省监听器
function listen(elemnet, eventType, selector, fn) { element.addEventListener(eventType, e => { if(e.target.matches(selector)) { fn.call(el, e, el) } }) } // 应付面试的版本复制代码
// 完美事件委托 来自造轮子function listen(element, eventType, selector, fn) { elemnet.addEventListener(eventType, e => { let el = e.target while(!el.matches(selector)) { if(element === el) { el = null break } el = el.parentNode } el && fn.call(el, e, el) })}listen(ul, 'click', li, () => {})ul > li*5 > span复制代码
HTTP 押题
-
HTTP 状态码知道哪些?
去看 吧
-
301 和 302 的区别是什么
i. 301永久重定向,浏览器会记住
ii.302 临时重定向
-
HTTP 缓存怎么做
- Catche-Control: max-age=300
- 避开缓存
-
Cache-Control 和 Etag 的区别是什么
自己查一下
-
Cookie 是什么? Session是什么?
-
Cookie
- HTTP 响应通过设置 Set-Cookie 设置 Cookie
- 浏览器访问指定域名必须带上 Cookie 作为 Request Header
- Cookie 一般用来记录用户信息
-
Session
- Session 是服务端的内存(数据)
- Session 一般通过在 Cookie 里记录 SessionID 实现
- SeesionID 一般是随机数
-
-
LocalStorage 和 Cookie 的区别是什么?
- Cookie 会随请求被发送到服务器上,LocalStrorage不会
- Cookie 大小一般在 4kb 以下, localstorage 一般 5mb 左右
-
(必考) GET 和 POST 的区别是什么?
- 参数。 GET 的参数放在 url 的查询参数里,POST 的参数(数据) 放在请求消息体里。
- 安全(都不安全)。 GET 没有 POST 安全
- GET的参数(url 查询参数)有长度限制,一般是 1024 个字符。 POST 的参数(数据) 没有长度限制(也有 4~10mb 限制)
- 包。 GET请求只需要发一个包,POST请求需要发两个以上包(因为POST有消息体)(其实,GET也可以用消息体)
- GET用来读数据, POST用来写数据,POST不幂等(幂等的意思是不管发多少次请求, 结果都一样。)
-
(必考) 怎么跨域? JSONP是什么? CORS是什么? postMessage是什么?
- JSONP
- CORS
- postMessage 看下 MDN
Vue 押题
-
(必考) Vue有哪些生命周期钩子函数?
-
(必考)Vue 如何实现组件通信?
- 父子通信(使用 Props 传递数据、使用 v-on 绑定自定义事件)
- 爷孙通信(通过两对父子通信,爷爷之间父子通信,爸儿之间父子通信)
- 兄弟通信
-
Vuex 的作用是什么?
-
VueRouter 路由是什么?
- 看文档 博客
-
Vue 的双向数据绑定是如何实现的?有什么缺点?
- 看文档,
-
Computed 计算属性的用法? 跟 Methods 的区别。
React 押题
-
React 生命周期
-
实例化
- getDefaultProps
- getInitialState
- componentWillMount
- render
- componentDidMount
-
存在期
- componentWillRecieveProps
- shouldComponentUpdate
- componentWillUpdate
- componentDidUpdate
-
销毁期
- componentWillUnmount
-
-
React Render 做了什么
-
调用 setState 之后发生了什么?
算法押题
-
排序(背诵冒泡排序、选择排序、计数排序、快速排序、插入排序、归并排序)
- js Array.prototype.sort 方法了解一下?
const swap(arr, a, b) { // a, b 是下标 let t = arr[a] arr[a] = arr[b] arr[b] = t }复制代码
const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0] window.Array.prototype.sort.call(arr, function(a, b) { return a - b }) arr复制代码
- 冒泡
const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0] const bubleSort = function(arr) { for(let j = arr.length; j > 1; j--) { for(let i = 0; i < arr.length - 1; i++) { if (arr[i] > arr[i+1]) { let t = arr[i] arr[i] = arr[i+1] arr[i+1] = t } } } return arr } const x = bubleSort(arr) x复制代码
- 选择
const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0] const selectSort = function() { let index for(let i = 0; i < arr.length; i++) { index = i for(let j = i + 1; j < arr.length; j++) { if(arr[index] > arr[j]) { index = j } } if(index !== i) { let t = arr[i] arr[i] = arr[index] arr[index] = t } } return arr } const x = selectSort(arr) x复制代码
- 计数
// 有一定的局限 只能用于整数 const counterSort = function() { }复制代码
-
快速
const arr = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8] const quickSort(arr) { if(arr.length <= 1) { return arr } let midPos = Math.floor(arr.length / 2) // 调用了 js 原生 api 懒得写了 大体就是用 二分的思想吧--。 }复制代码
-
插入
// 从后往前比较 知道碰到比当前项还要小的前一项时 将这一项插入到前一项的后面复制代码
- 归并
-
二分查找法
-
翻转二叉树
第三个二叉树暂时先放弃了....
安全押题
-
什么是 XSS(跨站脚本攻击(Cross Site Scripting)) 攻击? 如何预防?
- 举例
div.innerHTML = useComment // 某用户提交了恶意评论 userComment = // 恶意代码就被执行了, 这就是 XSS复制代码
-
预防
-
不要使用 innerHTML, 改成 innnerText, script 就会被当成文本,不执行
-
如果你一定要使用 innerHTML, 字符过滤
- 把 < 替换成
<
- 把 > 替换成
>
- 把 & 替换成
&
- 把 " 替换成
'
- 把 ' 替换成
"
- 把 < 替换成
替换上面5个字符即可,更多
- 使用 CSP Content Security Policy
-
-
什么是 CSRF(Cross-site request forgery 跨站请求伪造) 攻击? 如何预防?
-
过程
- 用户在 登录
- 用户切换到 (恶意网站)
- 发送一个 请求, 让当前用户添加 hacker 为好友
- 用户在不知不觉中添加了 hacker 为好友
- 用户没有想发这个请求,但是 hacker 伪造用户发请求的假象。
-
避免
- 检查 referer, 可以拒绝来自 的请求
- csrf_tocken 解决
-
Webpack 题
-
转译出来的文件过大怎么办?
- 使用 code split
- 写法 import('xxx').then(xxx => {console.log(xxx)})
- xxx 模块就是按需加载的
-
转译速度慢怎么办?
- 不会呀.... 想死
- 换台电脑吧...
-
写过 webpack loader 么?
发散题
-
从输入 URL 到页面展现中间发生了什么?
- DNS 查询DNS缓存
- 简历 TCP 连接(三次握手) (连接复用...)
- 发送 HTTP 请求 (请求的四部分????)
- 后台处理请求
- 监听80端口
- 路由
- 渲染 HTML 模板
- 生成响应
- 发送HTTP 响应
- 关闭 TCP 连接(四次挥手)
- 解析HTML
- 下载 css(缓存...
- 解析 css
- 下载 JS (缓存
- 解析 JS
- 下载图片
- 解析图片
- 渲染 DOM 树
- 渲染样式树
- 执行js
-
你一年工作经验是否足以胜任工作
- 开始问 直接凉
- 中间 最后问.. 他想压价
- 我... 给他看之前的项目?
-
你遇到过最难的问题是什么?
一波三折()
- 最开始 websocket 服务器的搭建,遇到一部分数据处理的问题
- 去网上搜索解决方案..
- 发现数据依然不符合预期
- 网上的代码不能很好的满足需求
- emms... 面向stackoverflow编程吧...
-
你的期望薪资是多少?
+2000(压价用)
-
实在不会
- 承认
- 询问详细细节: 你问的是不是 xxx 方面的解决方案
- 寻找相近话题
代码题
-
map + parseInt
// 给出 [1, 2, 3].map(parseInt) 的输出结果 parseInt(1,0, array) // 1 parseInt(2,1, array) // NaN parseInt(3,2, array) // NaN复制代码
-
a.x = a = {}
var a = {n:1}; var b = a; a.x = a = {n:2};复制代码
-
(a == 1 && a == 2 && a == 3) 可能为 true
能(弃疗)
- 原理
a = { value: 0, toString(){ a.value += 1 return a.value }}复制代码
京东笔试题:
-
手写 Ajax 工具类,例如 request(url, option)
const request = function(url, option) { let xhr = new XMLHttpRequest() xhr.open(option, url) xhr.onreadystatechange = function() { if(xhr.readyState === 4 && xhr.status === 200) { // responseCallback() console.log(xhr.responseText) } } }复制代码
-
跨域有哪些解决方案。 说说JSONP的实现。
function jsonp(setting) { settings.data = settings.data || {} settings.key = settings.key || 'callback' settings.callback = settings.callback || function() {} settings.data[settings.key] = '__onGetData__' window.__onGetData__ = function(data) { settings.callback(data) } let script = document.createElement('script') let query = [] for(let key in settings.data) { query.push(key + '=' + encodeURIComponent(settings.data[key])) } script.src = settings.url + '?' + query.join('&') document.head.appendChild(script) document.head.removeChild(script) } jsonp({ url: 'http://photo.sina.cn/aj/index', key: 'jsoncallback', data: { page: 1, cate: 'recommend', }, callback: function(ret) { console.log(ret) } })复制代码
-
CORS-跨域资源访问
-
-
js有哪些实现继承的方式。 闭包是什么?
- class extends
- 闭包
- 第一种说法 闭包可以用来间接访问一个变量,闭包可以用来隐藏一个变量
- 第二种说法: 闭包返回一个函数,这个函数可以操作其他函数内部的变量
function getAdder() { let n = 0 return function() { n++ console.log('n: ', n) } } let adder = getAdder() adder() adder()复制代码
-
写一个函数把手机号格式化: 13499991212 => 134 9999 1212
-
写出一下代码的输出结果
let leng = 1 function fn() { console.log(this.leng) } let obj = { leng: 2, method1: function(fn) { fn() // undefined fn.call(this) // 2 arguments[0]() // undefined }, method2: function() { document.addEventListener('click', evt => this.method3(evt.type), false) }, method3: function(type) { console.log(type + ' : ' + this.leng ) // 'click: 2' }, } obj.method1(fn) obj.method2(fn) // 点击页面之后打印什么?复制代码
-
写出下面代码的输出结果
let reg = /abc/g let str = 'abcd' reg.test(str) // true reg.test(str) // false复制代码
-
写出一个复制对象的方法 包括浅复制 和 深复制
// 浅 let person = { age: 18, name: 'guakun', hobby: { first: 'code', second: 'code', } } let person2 = {} for(key in person) { person2[key] = person[key] }复制代码
-
写出下面代码的输出结果
console.log(1)setTimeout(function() { console.log(2)}, 0)console.log(3)复制代码
-
写出下面代码的输出结果
let p1 = {name: 'john', age: 30} let p2 = {name: 'lucy', age: 20} function modify1(obj) { p1 = {name: 'backus'} } function modify2(obj) { obj.name = 'guakun' } modify1(p1) modify2(p2) console.log(p1) // {name: 'backus'} console.log(p2) // {name: 'guakun', age: 20}复制代码
-
如何实现以下效果
function add(num1) { return function(num2) { console.log(num1+num2) }}add(2)(5)复制代码
-
解释一下变量提升(hoisting)
-
事件对象的 target 和 currentTarget 属性有什么区别
- event.target 返回的是触发事件的元素
- event.currentTarget 返回的是绑定事件的元素
-
DOM 事件流是什么,各浏览器的兼容性
捕获和冒泡 兼容性的问题我不会
-
load 和 DOM ready 有什么区别?
-
写一个找出数组中重复元素的函数, 例如[0, 1, 2, 3, 4, 1, 4] 返回[1, 4]
//计数排序 let a = [0, 1, 2, 3, 4, 1, 4] let hashTab = {} let repeateHashTab = {} for(let index = 0; index < a.length; index++) { if(!(a[index] in hashTab)){ hashTab[a[index]] = true } else { repeateHashTab[a[index]] = true } } console.log(Object.keys(repeateHashTab)) function getInt(arr) { let newArr = [] newArr = arr.map((item) => item-0) return newArr } console.log(getInt(Object.keys(hashTab)))复制代码
-
如何提高滚动事件的性能
-
防抖
防抖技术即是可以把多个顺序地调用合并成一次,也就是在一定时间内,规定事件被触发的次数。
// 防抖动函数 function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate & !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; var myEfficientFn = debounce(function() { // 滚动中的真正的操作 }, 250); // 绑定监听 window.addEventListener('resize', myEfficientFn); 复制代码
-
节流
防抖函数确实不错,但是也存在问题,譬如图片的懒加载,我们希望在下滑过程中图片不断的被加载出来,而不是只有当停止下滑时候,图片才被加载出来。 这个时候,我们希望即使页面在不断被滚动,但是滚动 handler 也可以以一定的频率被触发(譬如 250ms 触发一次),这类场景,就要用到另一种技巧,称为节流函数(throttling)。 节流函数:只允许一个函数在 X 毫秒内执行一次。 与防抖相比,节流函数最主要的不同在于它保证在 X 毫秒内至少执行一次我们希望触发的事件 handler。 同样是利用定时器,看看简单的示例
// 简单的节流函数 function throttle(func, wait, mustRun) { var timeout, startTime = new Date(); return function() { var context = this, args = arguments, curTime = new Date(); clearTimeout(timeout); // 如果达到了规定的触发时间间隔,触发 handler if(curTime - startTime >= mustRun){ func.apply(context,args); startTime = curTime; // 没达到触发间隔,重新设定定时器 }else{ timeout = setTimeout(func, wait); } }; }; // 实际想绑定在 scroll 事件上的 handler function realFunc(){ console.log("Success"); } // 采用了节流函数 window.addEventListener('scroll',throttle(realFunc,500,1000)); 复制代码
-
-
谈下对 Promise 的理解
一种优雅的异步解决方案 // q function Promise() { return } let promise = new Promise(function(x, y) { setTimeout(()=>{ x(101) }, 3000) }) promise.then((z) => { console.log(z) }) // a function Promise(fn) { let status = 'pending' function successNotify() { status = 'resolved' toDoThen() } function failNotify() { status = 'rejected' toDoThen() } function toDoThen() { if(status === 'resolved') { for(let i=0; i< successArray.length; i++) { successArray[i].call() } } else if(status === 'rejected') { for(let i=0; i
-
写出下面代码的输出结果(es6)
let x = 3function fn (y = x) { let x = 4 console.log(y)}fn()// out: 3复制代码