前端面试知识点整理:

195 阅读5分钟

一、css

  1. position

(_1)_absolute 绝对定位 ,脱离了文档流,绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于html

(2)fixed 固定定位 ,与绝对定位相似,但元素的包含块为 viewport 视口。该定位方式常用于创建在滚动屏幕时仍固定在相同位置的元素。

(3)relative 相对定位 ,相对于其正常位置进行定位,不影响其他元素的偏移。

(4)sticky 粘性定位 ,可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。这是一个结合了 position:relativ_e 和 position:fixed 两种定位功能于一体的特殊定位。常见的吸顶、吸底(头部返回栏,底部切换栏_等)的效果都是使用这个属性。 注意:须指定 top 、 right 、 bottom 、 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。 并且 top 和 bottom 同时设置时,top 生效的优先级高,left 和 right 同时设置时,left 的优先级高。设定为 position:sticky 元素的任意父节点的 overflow 属性必须是 visible,否则 position:sticky 不会生效。如果 position:sticky 元素的任意父节点定位设置为 overflow:hidden,则父容器无法进行滚动,所以 position:sticky 元素也不会有滚动然后固定的情况。如果 position:sticky 元素的任意父节点定位设置为 position:relative | absolute | fixed,则元素相对父元素进行定位,而不会相对 viewport 定位。达到设定的阀值,也就是设定了 position:sticky 的元素表现为 relative 还是 fixed是根据元素是否达到设定了的阈值决定的。

(5)static 静态定位 ,HTML 元素默认情况下的定位方式为 static(静态),静态定位的元素不受 top、bottom、left 和 right 属性的影响,它始终根据页面的正常流进行定位。

(6)inherit 值如同其他 css 属性的 inherit 值,即继承父元素的 position 值。

2. overflow
3. 盒子模型

(1)标准盒模型(W3C盒子模型)

设置的宽高是对实际内容content的宽高进行设置,内容周围的border和padding另外设置;

即元素实际占位的宽高为:

width【height】= 设置的content的宽【高】 + padding + border + margin

css设置标准模型:Box-sizing:context-box (也是浏览器默认的盒模型)

(2)IE盒子模型(怪异盒模型)

设置的宽高是对实际内容content + 内边距(padding)+边框(border)之和的width和height进行设置的;

即元素实际占位的宽高为:

width(height)= 设置的width(height)+外边距margin

css设置Ie模型:box-sizing:border-box;

https://www.jianshu.com/p/e7238f7032a7

4、BFC

二、javascript

1、js数据类型

基本类型:string、number、boolean、null 、 undefined、symbol(es6,独一无二的值)

引用类型:object、array 、function

2 、基本数据类型与引用类型在存储上有什么区别?

基本数据类型:以栈的形式存储,保存与赋值指向数据本身,用typeof来判断类型,存储空间固定。

引用类型:以堆的形式存储,保存与赋值指向对象的一个指针,用instanceof 来判断类型,存储空间不固定。

注:1、Object.prototype.toString.call()对于所有基本数据类型都能进行判断,即使是null和undefined.

2、Array.isArray()   // 用于判断是否为数组

https://baijiahao.baidu.com/s?id=1706449062196213790&wfr=spider&for=pc

3、如何阻止时间冒泡?

w3c的方法是e.stopPropagation() , IE则是e.cancelBubble=true

4、如何阻止默认事件?

w3c的方法是e.preventDefault(),IE则是e.returnValue=false

5、原型,原型链?

在Javascript中一共有两种类型的值,原始值和对象值,每个对象都有一个内部属性 prototype,我们通常称之为原型,原型的值可以是一个对象,也可以是null,如果它的值是一个对象,则这个对象也一定有自己的原型,这样就形成了一条线性的链,我们称之为原型链。

总结:(1)__proto__和constructor属性是对象所独有的;

           (2)prototype属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__和constructor属性。

例子:(1function Foo(){}          var Boo = {name: “Boo”}         Foo.prototype = Boo         var f = new Foo()         console.log(f.__proto__ === Foo.prototype) // true         console.log(f.__proto__ === Boo) // true         Object.getPrototypeOf(f) === f.__proto__ // true2)访问一个对象的原型可以使用ES5中的Object.getPrototypeOf方法,或者ES6中的__proto__属性、
       原型链的作用是用来实现继承,比如我们新建一个数组,数组的方法就是从数组的原型上继承而来的

6、call和apply

call和apply都是为了解决改变this的指向。作用都是相同的,只是传值的方式不同。

function show(title) {console.log(`${title+this.name}`);}let lisi = {name: "李四"}let wangwu = {name: "王五"}show.call(lisi, "用户")show.apply(wangwu, ["用户2: "])// 用户1: 李四// 用户2: 王五

7、new关键字都做了什么?

new关键字与构造函数一起使用以创建对象:

function Employee(name,postion,yearHired){  this.name = name;  this.postion = position;  this.yearHired = yearHired;}const amp = new Employee(“Marko Polo”,”Software Developer”,2017);

new关键字做了4件事:

(1)创建空对象

(2)将空对象分配给this 值

(3)将空对象的__proto__指向构造函数的prototype

  (4) 如果没有使用显示return语句,则返回this

看下面事例:

function Person(){this.name = “kyle”}

根据上面的描述,new Person做了:

(1)创建一个空对象:var obj = {}

(2)将空对象分配给this值:this = obj

(3)将空对象的__proto__指向构造函数的prototype: this.__proto__=Person().prototype

(4)返回this:return this

8、splice

splite(start,deleteCount,val1,val2,…)从start 位置开始删除deleteCount项,并从该位置起插入val1,val2,…arr1 = [1,2,3,4,5];result = arr1.splice(2,2,7,8,9); // a: [1,2,7,8,9,5] b:[3,4]result = arr1.splice(0,1); // 同shift

9、join(sepaprator):数组拼接成字符串

将数组的元素拼接成一个字符串,以sepaprator 为分隔符,省略的话则默认用逗号分隔符

arr1 = [1,2,3,4,5]result=arr1.join(“|”); // a: [1,2,3,4,5] b:”1|2|3|4|5”

10、slice(start,end)数组截取

slice(start,end):返回从原数组中指定开始下标到结束下标之间的项组成的新数组,但不包括结束位置的项

arr1=[1,2,3,4,5]result = arr1.slice(2,5); // [3,4,5]result = arr1.slice(2); // [3,4,5] 在只有一个参数的情况下,slice()方法返回从该参数指定位置开
                           始到当前数组末尾的所有项result=arr1.slice(0); // 返回自身

11、reverse: 将数组反序

arr=[1,2,3,4,5]result=arr1.reverse(); // [5,4,3,2,1]

12、concat: 数组合并

// 返回一个新数组,是将参数添加到原数组中构成arr1=[1,2,3,4,5]result=arr1.concat(6,7); // a: [1,2,3,4,5; b: [1,2,3,4,5,6,7]13unshift shift 从数组开头开始添加或删除push pop 从数组末尾添加或者删除

14 、如何合并两个数组?数组删除一个元素?

// 三种方法
(1var arr1=[1,2,3];  var arr2=[4,5,6];  arr1 = arr1.concat(arr2); // arr1: [1,2,3,4,5,6](2) var arr1=[1,2,3];  var arr2=[4,5,6];  Array.prototype.push.apply(arr1,arr2); // arr1: [1,2,3,4,5,6] arr2: 不变(3)var arr1=[1,2,3];  var arr2=[4,5,6];  for(var i=0;i<arr2.length;i++){ arr1.push(arr2[i]); }// arr1: [1,2,3,4,5,6]

15、普通函数和箭头函数的区别?

(1)写法不一样。箭头函数比普通函数更加的简洁,比如,括号里面只有一个参数,括号可以省略,另外如果函数体中只有一行代码,花括号也可以省略。

(2 ) 箭头函数没有arguments, 但可以用展开运算符“ …” 解决;

function A(a){console.log(arguments)}A(2,’sdas’,’asda’); 
// Arguments(3)[2,’sdas’,’asda’,callee:f, Symbol(Symbol.iterator): f ]let C = (…c) => { console.log(c) }; C(3,82,32,111); // [3,82,32,111]

(3)this 作用域不同。箭头函数不绑定this,会捕获其所在的上下文的 this值,作为自己的this值。普通函数的this指向的是谁调用该函数就指向。

var obj = {  a: 10,  b: ()=>{  console.log(this.a); // undefined  console.log(this); // Window (postMessage: f, blur: f, focus: f, close: f  },  c: function() {  console.log(this.a); // 10  console.log(this); // {a: 10, b: f, c: f}  }}

(4)箭头函数没有原型属性,不能作为构造函数,不能使用new

(5)普通函数存在变量提升的现象

 // 普通函数fn1();function fn1() { console.log(“hello world”);}// 箭头函数fn2(); // 报错let fn2 = () => {console.log(“hello world”);}

(6)箭头函数不能当做Generator函数,不能使用yield关键字

16、js事件轮循

1、js 是一门单线程语言,从上往下执行的,首先,主线程读取js代码,此时是同步的环境 
2、当主线程检测到异步操作,就会交给其他异步线程处理,然后继续执行主线程的的任务 
3、异步任务执行完毕之后,判断异步任务的类型,异步任务可分成宏任务和微任务,像setTimeout、setInterval属于宏任务,promise.then属于微任务,不同的任务进入不同的队列,等待主线程空闲时候调用。 
4、当主线程的的同步任务执行完毕之后,开始执行微任务队列里面的所有微任务,执行完微任务,就执行宏任务队列里面所有的宏任务 
5、执行完成之后,主线程开始询问任务队列里面是否还有等待的任务,如果有则进入主线程继续执行 以上步骤重复执行就是事件轮询

console.log('script start');
setTimeOut(function(){
  console.log('setTimeOut');
},0);
new Promise(fuction(resolve){
   console.log('promise1');
   resolve();
}).then(function(){
   console.log('promise2');
});
console.log('script end');
流程如下:
1、打印script start,

2、遇到setTimeout放到宏任务队列里

3、打印promise1

4、将.then回调放入微任务队列里

5、打印script end

6、执行栈已清空,执行微任务队列打印promise2

7、微任务队列已清空,执行宏任务队列setTimeOut

8、所有任务队列清空

(如果还有任务的话则继续轮询 微任务 => 宏任务 => 微任务 => 宏任务…)

17、宏任务和微任务

18、promise

三、vue.js

1、数据双向绑定原理

2、组件传值

(1)父到子:props;

(2)子到父:this.$emit();

(3)在父组件中this.$refs.子组建ref[name]

(4)可以使用Eventbus时间总线进行父子组件之间的传值:

 // 首先创建一个单独的eventBus.js文件import Vue from ‘vue’export default new Vue()// 创建两个组件AB,在两个组件中引入eventBus.js并赋值给bus在A组件中触发自定义的事件:bus.$emit(“share”,msg)在B组件中绑定事件以及传过来的参数msg: bus.$on(“share”, val=>{console.log(val); // val就是msg})

(5)深层组件传值:祖先组件provide 注入,后代组件inject接收。

祖先组件:export default{ provide() { return { uploadId: this } } }后代组件: export default { inject: [‘uploadId’] }

3、vue 生命周期

(1)beforeCreate (创建前)

(2)created(创建后)

(3)beforeMount(载入前)

(4)mounted(载入后)

(5)beforeUpdate(更新前)

(6)updated(更新后)

(7)beforeDestroy(销毁前)

(8)destroyed(销毁后)

4、父子组件生命周期执行顺序

(1)挂载阶段

父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

(2)更新阶段

执行顺序:

父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated

(3)销毁阶段

执行顺序:

父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed

5、 vue怎么监听数组的变化的

6、vue2.0 和vue3.0有什么区别?

7、路由的原理

8、vuex  数据存储和响应原理

四、webpack

1 、webpack的优化:打包速度、打包体积、分包

2、webpack的打包原理

五、http协议、浏览器

1、http2.0

2 、页面输入地址到页面展示的过程

3、浏览器缓存

六、算法

1、diff算法

diff算法就是进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方,最后用patch记录的消息去局部更新Dom。

diff算法的步骤:用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中,当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较(diff),记录两棵树差异 把第二棵树所记录的差异应用到第一棵树所构建的真正的DOM树上(patch),视图就更新了。