如下问题基本针对于大厂一面和中等公司的一面二面,更多关于项目里的问题还需根据自身参考。javascript
语义标签,加强型表单,视频和音频,Canvas绘图,SVG绘图,地理定位,拖放API,Web Worker。
css
一块独立渲染区域。如下会造成BFC:html
做用:防止margin重叠,自适应两栏布局,清除内部浮动。前端
水平居中:text-align:center,,flex,position:absolute+transformvue
垂直居中:line-height,flex,position:absolute+transform,table-cellhtml5
水平垂直居中:flex,position:absolute+transform.java
static
是默认值relative
相对定位 相对于自身原有位置进行偏移,仍处于标准文档流中absolute
绝对定位 相对于最近的已定位的祖先元素, 有已定位(指position
不是static
的元素)祖先元素, 以最近的祖先元素为参考标准。若是无已定位祖先元素, 以body
元素为偏移参照基准, 彻底脱离了标准文档流。fixed
固定定位的元素会相对于视窗来定位,这意味着即使页面滚动,它仍是会停留在相同的位置。一个固定定位元素不会保留它本来在页面应有的空隙。display:none指的是元素彻底不陈列出来,不占据空间,涉及到了DOM结构,故产生reflow与repaintnode
visibility:hidden指的是元素不可见但存在,保留空间,不影响结构,故只产生repaint(脱离文档流)webpack
!important>inline>ID>class>taggit
这个问题呢,基本上是必问的。因此这一题,咱们从js的变量提及,从内存空间提及:
其中,JavaScript中变量类型有两种:
Undefined, Null, Boolean, Number, String, Symbol
)一共6种Object
)基础类型的值保存在栈中,这些类型的值有固定大小,"按值来访问";
引用类型的值保存在堆中,栈中存储的是引用类型的引用地址(地址指针),"按引用访问",引用类型的值没有固定大小,可扩展(一个对象咱们能够添加多个属性)。
所以进行拷贝的时候便分为两种拷贝:
关于js执行上下文:
执行上下文(Execution Context): 函数执行前进行的准备工做(也称执行上下文环境)
js中执行上下环境(上下文):
由于js是单线程,所以,js代码执行就相似于出栈,入栈过程。js中,全局永远在栈底,代码示例:
function foo () {
function bar () {
return 'I am bar';
}
return bar();
}
foo();复制代码
从这里能够看出执行上下文的生命周期:
关于上下文不一样阶段的做用可参考这篇文章
什么是原型:
每一个函数默认都有一个 prototype
属性,它就是咱们所说的 "原型",或称 "原型对象"。每一个实例化建立的对象都有一个 __proto__
属性(隐式原型),它指向建立它的构造函数的 prototype
属性。
什么是原型链:(基本是基于构造函数)
访问一个对象的属性时,会先在其基础属性上查找,找到则返回值;若是没有,会沿着其原型链上进行查找,整条原型链查找不到则返回 undefined
。这就是原型链查找。
function a(){};
a.prototype.name = "追梦子";
var b = new a();
console.log(b.name); //追梦子复制代码
所以从原型咱们能够谈到继承:
1.原型继承
// 建立父类一个类
function Father(name){
//属性
this.name = name || 'father'
// 实例方法
this.run = function(){
console.log(this.name + '正在跑步!');
}
}
//原型上的方法
Father.prototype.sayName = function() {
console.log(this.name+'正在跑步');
}
//原型链继承
function Son(){
this.subName = '儿子'
}
// 建立Son的实例,并将原型指向Father
Son.prototype = new Father()
Son.prototype.saySubName = function() {
console.log(this.subName+'正在跑步');
}
var son = new Son()
console.log(son.sayName()) // father正在跑步
console.log(son) //能够看看son的原型指向复制代码
// 建立父类一个类
function Father(name){
//属性
this.color = ['r','e']
}
//原型链继承
function Son(){}
Son.prototype = new Father()
var sonOne = new Son()
sonOne.color.push('d')
console.log(sonOne.color)//["r", "e", "d"]
var sonTwo = new Son()
console.log(sonTwo.color)//["r", "e", "d"]
特色:基于原型链,既是父类的实例,也是子类的实例
缺点:对于上 引用型值的继承容易形成全部实例共享复制代码
2.构造函数继承
// 建立父类一个类
function Father(name){
//属性
this.color = name || ['r','e']
}
//原型上的方法
Father.prototype.sayColors = function() {
console.log(this.color);
}//构造函数继承
function Son(){
Father.call(this) //只有函数才会有call,apply,bind
}
// 实例1
var sonOne = new Son()
// 实例二
var sonTwo = new Son()
sonOne.color.push('d')
console.log(sonOne.color)//["r", "e", "d"]
console.log(sonTwo.color)// ["r", "e"]
console.log(sonTwo)
console.log(sonTwo instanceof Son) // true
console.log(sonTwo instanceof Father) //false
console.log('是否继承了原型上方法', sonTwo.sayColors()) // error
特色: 能够实现多继承
缺点:只能继承父类实例的属性和方法,不能继承原型上的属性和方法,而且复用性太弱。复制代码
3.组合式继承:(原型继承+构造继承)
function Father(colors){
//属性
this.color = colors || ['r','e']
}
//原型上的方法
Father.prototype.sayColors = function() {
console.log(this.color);
}
//构造函数继承
function Son(name, color){
Father.call(this, color) //第二次调用Father()
this.name = name
this.sayName = function(){
console.log(this.name)
}
}
Son.prototype = new Father() //第一次调用Father()
var sonOne = new Son('儿子1', ['r','e', 'd'])
sonOne.sayColors() //["r", "e", "d"]
sonOne.sayName() //儿子1
var sonTwo = new Son('儿子2', ['g','r', 'e'])
sonTwo.sayColors() //["g", "r", "e"]
sonTwo.sayName() //儿子2
console.log(sonTwo) //如下图片是sonTwo
特色:既继承了实例的属性和方法,也继承了原型上的属性和方法
缺点:调用了两次父类构造函数,生成了两份实例
复制代码
4.寄生式组合继承(不进行两次调用,直接将父类原型复制给子类原型)
function Father(colors){
//属性
this.color = colors || ['r','e']
}
//原型上的方法
Father.prototype.sayColors = function() {
console.log(this.color);
}
//构造函数继承
function Son(name, colors){
Father.call(this, colors)
this.name = name
this.sayName = function(){
console.log(this.name)
}
}
function jisheng(subPro,superPro){
let pro = Object(superPro)
pro.constructor = subPro
subPro.prototype = pro }
jisheng(Son,Father)
var sonOne = new Son('儿子1', ['r','e', 'd'])
sonOne.sayColors() // ['r','e', 'd']
sonOne.sayName() // 儿子1
var sonTwo = new Son('儿子2', ['g','r', 'e'])
sonTwo.sayColors() // ['g','r', 'e']
sonTwo.sayName() // 儿子2
console.log(sonTwo) //如下是sonTwo的截图复制代码
什么是做用域:(针对变量)
至关于针对这些变量的访问权限的合集。(至关于一个省(全局做用域)下的各类市,县。。。都有不一样的地盘)
var globaValue = '我是省做用域';
function chengdu() {
var fooValue = '我是chengdu做用域'; function wuhou() {
var barValue = '我是wuhou做用域'; }
}
function mianyang() {
var otherValue = '我是mianyang做用域';
}复制代码
什么是做用域链:和原型链同样,是一个查找过程
var a = 1;
var b = 2;
function b(){
var a = 2;
function c(){
var a = 3;
console.log(a);
console.log(b);
} c();
}
b();//3 2
当在c的做用域中找到a,就中止查找,打印a,继续向上找b,b函数的做用域中没有b,
则继续沿着做用域链往上找,在全局中找到b。复制代码
所以从做用域咱们能够谈到闭包:闭包就是指有权访问另外一个函数做用域中的变量的函数。
// 如下就是闭包的应用
function test(){
var arr = [];
for(var i = 0;i < 10;i++){ //i是在test做用域里
arr[i] = function(){ //函数二做用域
return i;
};
}
for(var a = 0;a < 10;a++){
console.log(arr[a]());
}
}
test(); //打印10个10,由于i在test执行的时候最后 for循环遍历i变为10,所以在函数二的做用域中没有i,
就向上找。
//变量被保存在了内存中function test(){
var a = 1
return function(){
a++
console.log(a)
}
}
var func = test()
func() // 2
func() // 3
//闭包中的this指向
var name = "The Window";
var obj = {
name: "My Object",
getName: function(){
return function(){
return this.name;
};
}
};
console.log(obj.getName()()); // 其实是在全局做用域中调用了匿名函数,this指向了window。
//这里要理解函数名与函数功能(或者称函数值)是分割开的,不要认为函数在哪里,
//其内部的this就指向哪里。匿名函数的执行环境具备全局性,所以其 this 对象一般指向 window。复制代码
1. 建立一个新的对象,this变量引用该对象,同时还继承了该函数的原型
2. 属性和方法都被添加到this 引用的对象中去
3. 新建立的对象由this所引用,而且最后隐式的返回this
promise解决异步的三种状态
(1) promise 对象初始化状态为 pending
(2) 当调用resolve(成功),会由pending => fulfilled
(3) 当调用reject(失败),会由pending => rejected
注意promsie状态 只能由 pending => fulfilled/rejected, 一旦修改就不能再变
在说区别以前,咱们先看一个例子
var p1 = new Promise(function(resolve, reject){
resolve(1);
})
setTimeout(function(){
console.log("will be executed at the top of the next Event Loop");
},0)
p1.then(function(value){
console.log("p1 fulfilled");
})
setTimeout(function(){
console.log("will be executed at the bottom of the next Event Loop");
},0)
p1 fulfilled
will be executed at the top of the next Event Loop
will be executed at the bottom of the next Event Loop复制代码
。
JavaScript经过任务队列管理全部异步任务,而任务队列还能够细分为MacroTask Queue(宏任务)和MicoTask Queue(微任务)两类。
MacroTask Queue(宏任务队列)主要包括setTimeout,setInterval, setImmediate, requestAnimationFrame, NodeJS中的`I/O等。
MicroTask Queue(微任务队列)主要包括两类:
独立回调microTask:如Promise,其成功/失败回调函数相互独立;
复合回调microTask:如 Object.observe, MutationObserver 和NodeJs中的 process.nextTick ,不一样状态回调在同一函数体;
总的来讲就是若是代码按顺序执行,就是一个进入是最大的宏任务,先执行第一个宏任务而后执行宏任务里的微任务,在执行下一个宏任务。
都是Tcp链接,最大的区别就是:
GET产生一个TCP数据包;POST产生两个TCP数据包。
对于一个数据请求来讲,能够分为发起网络请求、后端处理、浏览器响应三个步骤。而浏览器则能帮助咱们在第一步和第三步优化性能,减小数据请求。
其中,缓存位置分为四种:
Service Worker(运行在浏览器背后的独立线程,必须使用https保障安全)
Memory Cache(内存中的缓存,读取速度快,缓存持续性很短)
Disk Cache(存储在硬盘中的缓存,读取速度慢)
Push Cache(推送缓存,以上三种缓存都没有命中时,它才会被使用,会话中存在)
关于浏览器缓存能够参照“深刻理解浏览器缓存机制”,如下是浏览器缓存过程分析(图来自网络):
是否须要向服务器从新发起HTTP请求将缓存过程分为两个部分:
- 强制缓存(不会向服务器发送请求,从缓存中读取)
- 协商缓存(强制缓存失效,浏览器从新携带缓存标识发起请求,从而让服务器决定是否启用缓存的过程)
前端清理缓存的几种方法:
//不缓存meta标签
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="0">
//form表单
<body onLoad="javascript:document.yourFormName.reset()">
//ajax请求时
cache:false ||
beforeSend :function(xmlHttp){
xmlHttp.setRequestHeader("If-Modified-Since","0");
xmlHttp.setRequestHeader("Cache-Control","no-cache");
},
//url参数上加随机数或者随机时间
复制代码
为何须要cookie和session?
http是无状态的,服务端不能跟踪客户端的状态。
cookie机制:
若是不在浏览器中设置过时时间,cookie被保存在内存中,生命周期随浏览器的关闭而结束,这种cookie简称会话cookie。若是在浏览器中设置了cookie的过时时间,cookie被保存在硬盘中,关闭浏览器后,cookie数据仍然存在,直到过时时间结束才消失。
Cookie是服务器发给客户端的特殊信息,cookie是以文本的方式保存在客户端,每次请求时都带上它
session机制:
当服务器收到请求须要建立session对象时,首先会检查客户端请求中是否包含sessionid。若是有sessionid,服务器将根据该id返回对应session对象。若是客户端请求中没有sessionid,服务器会建立新的session对象,并把sessionid在本次响应中返回给客户端。一般使用cookie方式存储sessionid到客户端,在交互中浏览器按照规则将sessionid发送给服务器。若是用户禁用cookie,则要使用URL重写,能够经过response.encodeURL(url) 进行实现;API对encodeURL的结束为,当浏览器支持Cookie时,url不作任何处理;当浏览器不支持Cookie的时候,将会重写URL将SessionID拼接到访问地址后。
cookie:大小限制4KB,会浪费一部分发送cookie时使用的带宽,要正确的操纵cookie是很困难的。
webStorage包括如下两种:数据存储大小是5MB,字符串类型
localstorage:永久保存,除非手动清除clear()。
sessionstorage:临时保存,关闭了浏览器窗口后就会被销毁
原理: 恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的 (html代码/javascript代码) 会被执行,从而达到恶意攻击用户的特殊目的。
解决方法:过滤危险节点,cookie设置成httponly
原理:CSRF攻击者在用户已经登陆目标网站以后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操做的请求,达到攻击目的。
解决方法:尽可能使用POST,限制GET;浏览器Cookie策略;加验证码;Referer Check;Anti CSRF Token服务端加token,在提交请求时附上,看是否与服务端一致。
HTTP
请求数DNS
查询CDN
DOM
元素数量DOM
操做JavaScript
和 CSS
JavaScript
、 CSS
、字体、图片等CSS Sprite
iconfont
iframe
使用src
为空Object.defineProperty复制代码
hash
---- 利用URL中的hash(“#”):HashHistory.push(),HashHistory.replace()
利用History
interface在 HTML5中新增的方法:pushState(), replaceState()
pushState设置的新URL能够是与当前URL同源的任意URL;而hash只可修改#后面的部分,故只可设置与当前同文档的URL
pushState设置的新URL能够与当前URL如出一辙,这样也会把记录添加到栈中;而hash设置的新值必须与原来不同才会触发记录添加到栈中
pushState经过stateObject能够添加任意类型的数据到记录中;而hash只可添加短字符串
pushState可额外设置title属性供后续使用
v-if: 移除在dom中的显示,将dom元素移除
v-show: dom元素还在,至关于display:none
display:none --元素被隐藏, 和 visibility: hidden
重排和重绘:重排包括重绘,重绘不必定包括重排
引发重排:
(1)页面渲染初始化时;(这个没法避免)
(2)浏览器窗口改变尺寸;
(3)元素尺寸改变时;
(4)元素位置改变时;
(5)元素内容改变时;
(6)添加或删除可见的DOM 元素时。
git pull至关于git fecth + git merge。git fecth只能改变远程仓库里的代码,本地head不能改变。
为何须要source-map,为了解决代码通过编译打包出错以后定位问题。
webpack官网一共有11种,无非就是包括:打包后(none),生成后的代码,转换后的代码(仅限行:每行一个映射),原始源代码(仅限行),原始源代码,无源代码内容。对于开发环境,一般但愿更快速的 source map,须要添加到 bundle 中以增长体积为代价,可是对于生产环境,则但愿更精准的 source map,须要从 bundle 中分离并独立存在。
如下是开发环境经常使用推荐的:
配置:devtool: 'cheap-eval-source-map'
生产环境是最好不要看到源码,推荐devtool:none