面试准备:
-
ES6新特性(ES6是ECMAscript的规范,js进行实现)
-
let、const
-
不存在变量提升(预解析)
console.log(c); //输出undefined var c = "c"; //解析顺序: var c; console.log(c); c = "c"; console.log(d); //报错 let d = "D";
-
同一个作用域下重复声明
var a = 1; var a = 100; console.log(a); //输出100 let b = 1; let b = 100; console.log(b); //报错
-
区别作用域
function aa(){ var n = 10; if(true){ var n = 100; } console.log(n); //输出100 var属于函数作用域 } function aa(){ let n = 10; if(true){ let n = 100; } console.log(n); //输出10 let属于块级作用域(一大括号对应一个块级) }
-
const声明一个只读常量 ,一旦声明之后就不可改变,并在声明的时候必须进行赋值操作
-
-
箭头函数(变量名 = 参数 => 返回值)
let f = v => v; //es5 let f = function(v){ return v; }
-
set(类数组,是一个对象,成员唯一【python里的集合】)
const s = new Set(); s.add(1); s.add(2); // 链式写法 s.add(1).add(2); // 去重处理 var arr = [1,1,2,8,9,5,4,3,8,9,5,4]; var arr1 = [...new Set(arr)]; // 扩展运算符(序列化)
-
map(类对象,是一个对象,成员唯一)
const a = new Map(); a.set("name","aa").set("age",18); for(let [key,value] of a){ }
-
-
瀑布流布局(各种大小的图片放进容器中不变形也不留白【等宽不等高的图片】)
//html //<div class="box"><img src="..." /></div> $(window).on("load",function(){ waterFall(); }) function waterFall(){ // 求出列数 var box = $(".box"); var boxWidth = box.outerWidth(); //当前图片宽度 outerwidth() innerWidth() width() var screenWidth = $(window).width(); //整个屏幕宽度 var cols = parseInt(screenWidth/boxWidth); //创建高度数组 var heightArr = []; //遍历图片,第一排不需要定位,其他的定位处理 $.each(box,function(index,item){ //取出图片高度 var boxHeight = $(item).outerHeight(); if(index < cols){ //判断是否第一排 heightArr[index] = boxHeight; }else{ //最小图片的高度 //数组中最小的值 var minBoxHeight = Math.min(...heightArr); //最小索引 $.inArray() 用于查找数组中的指定值,返回索引(未找到返回-1) var minBoxIndex = $.inArray(minBoxHeight,heightArr); $(item).css({ position:"absolute", left:minBoxIndex*boxWidth + "px", top:minBoxHeight + "px" }) heightArr[minBoxIndex] += boxHeight; } }) }
-
防抖与节流
防抖:指触发事件后在n秒内函数只执行一次,若在n秒内再次触发则重新计算(页面的下拉刷新加载下一页)
节流:指连续发生的事件在n秒内只执行一次函数(搜索引擎,即时查询)
// 防抖(先等待再执行) function debounce(func,wait){ let timeout; return function(){ if(timeout) clearTimeout(timeout); timeout = setTimeout(function(){ func.apply(this); // 执行func函数 },wait) } } // 防抖(先执行再等待) function debounce(func,wait){ let timeout; return function(){ if(timeout) clearTimeout(timeout); // 取消之前的任务 let callNow = !timeout; timeout = setTimeout(function(){ timeout = null; // 清空定时器 },wait); if(callNow) func.apply(this); // 第一次执行 } } // 节流(定时器的方式) function throttle(func,wait){ let timeout; return function(){ if(!timeout){ timeout = setTimeout(function(){ timeout = null; func.apply(this); //修改this指向 },wait) } } } // 节流(事件戳的方式) function throttle(func,wait){ let prev = 0; // 记录时间 return function(){ let now = Date.now(); // 当前时间 if(now - prev > wait){ func.apply(this); prev = now; // 重置记录时间 } } }
-
call–apply–bind的用法
this指针,在ES5中指向的事调用它的对象
apply可以调用一个函数,并更改this指向 函数名.aaply(作用域对象) 将函数放到特定的作用域对象中执行,改变this指针指向该对象
call也可以调用一个函数,并更改this指向 函数名.call(作用域对象) 将函数放到特定的作用域对象中执行,改变this指针指向该对象
bind用于绑定一个作用域对象到该函数中
// call的实现原理 Function.prototype.mycall = function(ctx){ ctx = ctx || window; ctx._fn = this; let arg = [...arguments].slice(1); // 截取数组,数组第一个元素为对象本身 let result = ctx._fn(...arg); delete ctx._fn; return result; } // call和apply的区别 var a = { name:"aaa", fn:function(a,b){ console.log(a+b) } } var b = a.fn; b.apply(a,[1,2]) //参数为对象 + 数组 b.call(a,1,2) //参数为对象 + 多个参数 var c = b.bind(a,1,2) //绑定作用域对象 c(); /// var o = {name:"abc"}; function test(){ console.log(this.name); } test(); // 输出undefined test.apply(o); // 输出abc
-
作用域,this,变量提升,预解析,事件循环,等待队列
// 1 var a = 10; function test(){ a = 100; console.log(a); // 100 console.log(this.a); // 10 this指向window对象(全局) var a; // 变量提升 console.log(a); // 100 } // 2 (function(){ var a = b = 3; //b=3;var a=b; b指向全局变量 })() console.log(b); // 3 console.log(a); // undefined // 3 异步任务放到等待队列中等待执行,主线程执行完毕再执行等待队列中的任务 for(var i=1;i<=3;i++){ setTimeout(function(){ console.log(i); // 3个4 },0) } for(let i=1;i<=3;i++){ setTimeout(function(){ console.log(i); // 1、2、3 改为let之后识别块级作用域 },0) } // 4 function aa(n){ // 因为预解析和变量提升的问题 var n = undefined;n = n; console.log(n); // 123 var n = 456; console.log(n); // 456 } var n = 123; aa(n); // 5 无调用者就指向window var a = 123; function f1(){ console.log(n); // 123 } function f2(){ var n = 456; f1(); } f2(); console.log(n); // 123 // 6 var length = 100; function f1(){ console.log(this.length); // 注意this的指向 } var obj = { x:10, f2:function(){ f1(); // 无调用者 this指向window 输出100 arguments[0](); //arguments[0]==f1,无调用者,作用域为arguments对象 输出2 } } obj.f2(f1,1); // 7 function f(){ console.log(this.a); } var obj = { a:2, f:f } var f2 = obj.f; var a = "aaa"; f2(); // 无调用者 输出aaa obj.f(); // 有调用者 输出2 // 8 function f(s){ console.log(this.a,s); return this.a + s; } var obj = { a = 2 } var f2 = function(){ // 无形参 由arguments对象接收 return f.apply(obj,arguments); // return f.call(obj.[...argument]); } var b = f2(3); console.log(b); // 9 (function e(num){ console.log(num); // 输出fn 预解析函数优先级>参数>var var num = 10; function num(){}; })(100) // 10 function n (){ arr = 10; // let无变量提升 直接报错不往下执行 brr = 10; let arr; var brr; console.log(arr); console.log(brr); }
-
前端跨域多种实现方式
- webpack proxy
- jsonp
- nginx的反向代理
- webpack plugin(webpack-dev-middleware)
- cors
- websocket
-
实现一个物理像素
#box{ width:200px; height:200px; position:relative; } #box:before{ content:""; position:absolute; left:0; botton:0; width:100%; height:1px; background:#000; } @media screen and (-wenkit-min-device-pixel-ratio:2){ #box:before{ transform:scaleY(0.5); } } @media screen and (-wenkit-min-device-pixel-ratio:3){ #box:before{ transform:scaleY(0.33333); } }
-
实现垂直水平居中
-
定位
#box{ width:500px; height:500px; position:relative; } #box .box{ width:200px; height:200px; // 方案1 position:absolute; top:0; left:0; right:0; bottom:0; margin:auto; // 方案2 position:absolute; top:50%; left:50%; margin-left:-100px; margin-top:-100px; // 方案3 position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); }
-
弹性盒子
#box{ width:500px; height:500px; // 新版本 display:flex; justify-content:center; align-items:center; // 老版本 display:-webkit-box; -webkit-box-pack:center; -webkit-box-align:center; } #box .box{ width:200px; height:200px; }
-
-
综合面试题(对象、作用域、变量提升、原型链)
function Foo(){ getName = function(){alert(1);}; return this; } Foo.getName() = function(){alert(2);}; Foo.prototype.getName = function(){alert(3);}; var getName = function(){alert(4);}; function getName(){alert(5);}; // 解析 变量提升 function Foo(){ getName = function(){alert(1);}; return this; } // var getName; function getName(){alert(5);}; //两个同名,保留了函数 Foo.getName() = function(){alert(2);}; Foo.prototype.getName = function(){alert(3);}; getName = function(){alert(4);}; //重新赋值,覆盖上面的alert(4)函数 执行Foo()之后重新赋值为alert(1) //下列的输出结果 Foo.getName(); // 2 getName(); //4 Foo().getName(); //解析为(Foo()).getName() --> window.getName(); 输出1 先执行Foo()函数,修改了getName()函数 getName(); //经过重新赋值 输出1 new Foo.getName(); //new (Foo.getName)() --> new (function(){alert(2);}) 输出2 new Foo().getName(); //(new Foo()).getName() --> foo.getName() 沿着原型链向上找 找到Foo.prototype.getName = function(){alert(3);} 输出3 new new Foo().getName(); //new((new Foo()).getName)() --> new (foo.getName) --> new (function(){alert(3);})() 输出3
-
从输入url地址到网页渲染完成,发生了什么?
-
dns解析(将域名解析为IP地址,浏览器缓存–>系统dns缓存–>路由器dns缓存–>网络运营商dns缓存–>递归搜索)
-
tcp链接(tcp三次握手)
- 第一次握手,由浏览器发起,告诉服务器我要发送请求。
- 第二次握手,,由服务器发起,告诉浏览器我准备接收了。
- 第三次握手,由浏览器发起,告诉服务器我要发送了
-
发送请求(请求报文:HTTP协议的通信内容)
-
接收响应(响应报文)
-
渲染页面
注意:这5个步骤不一定按照顺序执行,如果dom树或cssom树被修改了,可能会执行多次布局和渲染,在实际页面中,步骤往往执行多次
- 遇见HTML标记,浏览器调用HTML解析器解析成token并构建dom树;
- 遇见style/link标记,浏览器调用css解析器,处理css标记并构建cssom树;
- 遇到script标记,调用JavaScript解析器,处理JavaScript代码(绑定事件,修改dom树/cssom树);
- 将dom树和cssom树合并成一个渲染树;
- 根据渲染树来计算布局,计算每个节点的几何信息(布局);将各个节点的颜色绘制到屏幕上(渲染)
-
断开连接(tcp四次挥手)
- 第一次挥手,由浏览器发起,告诉服务器我东西发送完成(请求报文);
- 第二次挥手,由服务器发起,告诉浏览器我都弄西接收完成(请求报文);
- 第三次挥手,由服务器发起,,告诉浏览器我东西发送完成(响应报文);
- 第四次挥手,由服浏览器发起,告诉服务器我东西接收完成(响应报文);
-
-
闭包的概念
闭包是一个密闭的容器,类似于set、map容器,存储数据的
闭包是一个对象,存放数据的格式为key:value
闭包的形成条件:1.函数嵌套。2.内部函数调用了外部函数的局部变量
闭包的优点:延长局部变量的声明周期
闭包的缺点:内存泄漏
注意点:1.合理使用闭包。2.及时销毁避免内存泄漏
function fun(n,o){ console.log(n); return { fun:function(m){ return fun(m,n) } } } var a = fun(0); //undefined a.fun(1); //0 a.fun(2); //0 a.fun(3); //0 var b = fun(0).fun(1).fun(2).fun(3); //undefined,0,1,2 var c = fun(0).fun(1); //undefined,0 c.fun(2); // 1 c.fun(3); // 1
-
对比react和vue
- 相同点
- 都有组件化开发和虚拟dom
- 都支持props进行父子组件间的数据通信
- 都支持数据驱动视图,不直接操作真实dom,更新状态数据界面就自动更新
- 都支持服务端渲染
- 都有支持native的方案,react有react-native,vue有weex
- 不同点
- 数据绑定:vue实现了数据的双向绑定,react数据流动是单向的
- 组件写法不一样,react是jsx,vue推荐做法是webpack+vue-loader的单文件组件格式
- state对象在react应用中不可变,需要使用setState方法更新状态,在vue中state对象不是必须的,数据由data属性在vue对象中管理
- 虚拟dom不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树,而react每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制
- react严格上只针对MVC的view层,而vue则是MVVM模式
- 相同点
-
vue组件间的通信方式
- 通信种类
- 父组件向子组件通信
- 子组件向父组件通信
- 隔代组件通信
- 兄弟组件通信
- 实现通信方式
- props
- 通过一般属性实现父向子通信
- 通过函数属性实现子向父通信
- 缺点:隔代组件和兄弟组件通信比较麻烦
- vue自定义事件
- vue内置实现,可以代替函数类型的props
- 绑定监听:<MyComp @eventName=“callback”>
- 触发事件:this.$emit(“eventName”,data)
- 缺点:只适合子向父通信
- vue内置实现,可以代替函数类型的props
- 消息订阅与发布
- 需要引入消息订阅与发布的实现库,如:pubsub-js
- 订阅消息:PubSub.subscribe(“msg”,function(msg,data){})
- 发布消息:PubSub.publish(“msg”,data)
- 优点:此方式可实现任意关系组件间通信
- 需要引入消息订阅与发布的实现库,如:pubsub-js
- vuex
- 是什么:vuex是vue官方提供的集中式管理vue多组件共享状态数据的vue插件
- 优点:对组件间关系没有限制,且相比于pubsub库管理更集中,更方便
- slot
- 是什么:专门用来实现父向子传递带数据的标签
- 注意:通信的标签模板是父组件中解析好后再传递给子组件的
- props
- 通信种类
-
vuex管理状态的机制
- 在state中保存状态–>在mutation中定义函数–> s t o r e . c o m m i t ( 函 数 名 , 状 态 值 ) 更 改 状 态 − − > store.commit(函数名,状态值)更改状态--> store.commit(函数名,状态值)更改状态−−>store.state.状态名读取状态
-
vue的MVVM实现原理
- vue作为MVVM模式的实现库的2种技术(模板解析、数据绑定)
-
flex:1代表什么
flex属性是flex-grow、flex-shrink和flex-basis属性的简写,默认值为0 1 auto,还有1和auto可选,flex:1;表示让所有弹性盒模型对象的子元素都有相同的长度,且忽略它们内部的内容
-
axios的实现原理
axios原理还是属于XMLHttpRequest,因此需要实现一个ajax,还需要一个promise对象来对结果进行处理
//ajax var Ajax={ get: function(url, fn) { // XMLHttpRequest对象用于在后台与服务器交换数据 var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onreadystatechange = function() { // readyState == 4说明请求已完成 if (xhr.readyState == 4 && xhr.status == 200) { // 从服务器获得数据 fn.call(this, xhr.responseText); } }; xhr.send(); } } //axios var Axios = { get: function(url) { return new Promise((resolve, reject) => { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onreadystatechange = function() { // readyState == 4说明请求已完成 if (xhr.readyState == 4 && xhr.status == 200) { // 从服务器获得数据 resolve(xhr.responseText) } }; xhr.send(); }) }, }
-
Git的具体特点,pull和fetch得到区别
-
Git和SVN的区别
-
浏览器加载速度慢,怎么实现预渲染
-
知道的网页制作会用到的图片格式有哪些
png、jpeg、gif、svg、Webp、Apng
- Webp:这个格式是谷歌开发的一种旨在加快图片加载速度的图片格式,图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器带宽资源和数据空间,Facebook等知名网站已经开始测试并使用Webp格式
- Apng:是PNG的位图动画扩展,可以实现png格式的动态图片效果,在04年诞生,但一直得不到各大浏览器厂商的支持,知道日前得到了iOS Safari8 的支持,有望代替GIF成为下一代动态图标准
-
事件绑定的三种方式
- 标签内绑定 ( div>)
- js事件绑定(div1.onclick = “”)
- 符合W3C标准的绑定(addEventListener/attachEvent)
-
html5新特性
- 语义化标签
- 增强型表单(color,date,datetime…)
- 视频和音频
- Canvas绘图
- 地理定位
- 拖放API
- Web Worker
- Web Storage
- WebSocket
-
css3新特性
- 过渡 transition
- 动画 animation (@keyframes + 动画名定义动画,在选择器中animation: 动画名 + 时间进行调用)
- 形状转换 transform
- 选择器
- 阴影 box-shadow
- 边框 border-image
- 背景 background-clip
- 弹性布局 Flex
- 栅格布局 grid
- 媒体查询
-
es6新特性
-
const、let
-
模板字符串
-
箭头函数函数参数默认值
-
扩展运算符(…)
-
解构赋值
const student = { name:"aa", age:22, sex:"bb" } const {name,age,sex} = student;
-
对象超类(允许在对象中使用super方法)
-
for…of和for…in
-
class定义类
-
promise
-
async…await
-