前端面试(一)

161 阅读11分钟
code.jpeg

前端面试(一)

1、vue的响应式原理?

Vue 的响应式原理是核心是通过 ES5 的保护对象的 Object.defindeProperty 中的访问器属性中的 get和 set 方法,data 中声明的属性都被添加了访问器属性,当读取 data 中的数据时自动调用 get 方法,当修改 data 中的数据时,自动调用 set 方法,而检测到数据的变化,会通知观察者 Wacher,观察者 Wacher自动触发重新render 当前组件(子组件不会重新渲染),生成新的虚拟 DOM 树,Vue 框架会遍历并对比新虚拟 DOM 树和旧虚拟 DOM 树中每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真实 DOM 树上.

2、vue的data中添加一个属性可以直接响应吗?

不能,不会触发vue的响应,如果要触发,则可以使用$set()添加

3、call apply bind的区别?谁可以改变this指向。

总结:
1、三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefinednull,则默认指向全局window2、三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入。
3、bind 是返回绑定this之后的函数,便于稍后调用;apply 、call 则是立即执行 

4、水平垂直居中的属性

 // 常用
 display: flex;
 align-items: center;
 justify-content: center;

5闭包是什么

闭包是指有权访问另一个函数作用域中的变量的函数

6、闭包的优缺点?

优点:

变量长期驻扎在内存中 避免全局变量的污染 可以定义私有属性和私有方法

缺点:

常驻内存 会增大内存的使用量 使用不当会造成内存泄露 可以改变父函数内部变量的值

7、闭包的使用场景

采用函数引用方式的setTimeout调用

回调

设计私有的方法和变量

8、this.$nextTick()的使用场景?

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

9、数组去重的方法

forEach循环数组,使用indexOf()判断是否存在重复的值,

es6语法中的 set方法去重

10、普通函数与箭头函数在this指向上的区别?

普通函数的this指向是window

箭头函数的this指向是父级

11、var let const的区别

重复定义修改值声明提升块级作用域循 环
var可以可以严格来说不支持(function可以)可以
let不可以可以不会支持可以
const不可以不可以(除数组和对象)不会支持不可以

1、var声明变量可以重复声明,而let不可以重复声明

2、var是不受限于块级的,而let是受限于块级

3、var会与window相映射(会挂一个属性),而let不与window相映射

4、var可以在声明的上面访问变量,而let有暂存死区,在声明的上面访问变量会报错

5、const声明之后必须赋值,否则会报错

6、const定义不可变的量,改变了就会报错

7、const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错

12、vue中如何全局定义方法

1、将方法挂载在Vue.prototype上

2、利用全局混入(mixin)

3、全局函数

4、使用全局方法Vue.use()【自定义插件】

13、在CSS中定位(position)的属性?

1、relative(相对定位):这类定位是通参考自身静态位置来进行定位,通过top(上)、bottom(下)left(左)、右(right)来进行定位,如果没有定位偏移量,对元素本身没有任何影响。且不脱离文档流,会保留空...

2、absolute(绝对定位): 通过top、bottom、left、right根据最近的父元素(含有position:relative/absolute/fixed属性)。默认情况根据可视窗口进行定位,有父元素时根据父元..s

3、Static(默认值;没有定位可以用于取消元素之前的定位设置。)

4、fixed(固定定位):始终相对于整个浏览器窗口进行固定, 会使元素完全脱离文档流。

14、Css样式选择器的优先级

!important>内联样式(非选择器)>ID选择器>类选择器>标签选择器>通配符选择器( *)

15、跨域请求是什么以及解决方案?

跨域请求是什么?:

因为浏览器有同源策略的存在,同源策略是协议、主机、端口号都有一致的url才可以交互。 解决方案:

跨域问题就是在浏览器使用ajax进行跨域请求的问题。

① JSONP方法:

前端:使用script标签引用其他的源,在script标签设计之初就允许使用它在别的源中区请求脚本。

后端:因为script标签会被浏览器执行,所以服务端要在真实数据外包一层js函数,在js函数外面添加一层作为传输的JSON格式回传给客户端 总结:简单来说,不直接获取服务端数据,而是给数据包裹js函数变成不一样的JSON数据回传给客户端,缺点是JSONP只支持get请求,不支持post请求

② CORS方法: CORS原理:当浏览器在进行跨域请求时,会在请求中添加头部origin表明自己的协议、主机、端口号,当服务器接收到请求,并获取到origin头部时,如果要允许请求的话,就要添加头部 Access-Control-Allow-Origin(协议、主机、端口号)到响应中。客户端就知道可不可以进行跨域请求了 image_EfMO5dDQha.png ③ 服务器代理方法: 后端:服务器端设置反向代理(nginx)反向代理在将请求转给服务器 原理:因为反向代理与服务器的交互都属于服务器之前的沟通,因此就解决了跨域问题(常用)

16、cookie 、localStorage、sessionStorage的区别?

cookie:

localStorage: 永久存储,可以自行删除(同步)

sessionStorage: 临时存储,关闭浏览器页面,自动删除sessionStorage

cookielocalStoragesessionStorage
大小4Kb10Mb5Mb
兼容H4/H5H5H5
访问任何窗口任何窗口同一窗口
有效期手动设置窗口关闭
存储位置浏览器与服务器浏览器浏览器
与请求一起发送
语法复杂简易简易

17、fetch API

fetch\_get请求:                                   fetch\_post请求:

image_cUGG9kiXHz.pngimage_oyzBelzklp.png

18、vue中的组件传值?

image_nvLPcb8q8n.png

19、History模式与Hash模式有什么区别?

1、vue-router有三个模式,其中History模式与 Hash更为常用。两者的差别在显示形式以及部署上; 2、hash模式在地址栏显示时已经是已哈希的形式:#/xxx,这种方式使用和部署都比较简单;history模式url看起来更加优雅美观,但是应用再部署时需要做一些特殊的配置,web服务器要做回退处理,否则就会出现出现刷新页面404的问题 3、在实现上不管是那种模式,最终都是通过监听popstate事件触发路由跳转处理,url显示不同只是显示效果上的不同

20、如何从零开始实现vuex?

1、vuex是一个状态管理的库或者模式,要确保存储在store中的状态以可预期的方式变更。
    1)、要实现一个vuex中store的存储全局状态
    2)、要提供修改状态所需的Api`commit(type,payload)`,`dispatch(type,payload)`
2、要实现 Store 时,可以定义Store类,构造函数接收选项 options ,设置属性state对外暴露状态,提供commit和dispatch修改属性state。这里需要设置state为响应式对象,同时将Store定义为一个插件。
3`commit(type payload)` 方法中可以获取用户传入的`mutations`并执行它,这样可以按用户提供的方法修改状态。`dispatch(type,payload)`类似,但需要注意它可能是异步的,需要返回一个Promise给用户以处理结果

Store的实现:

class Store {
	constructor(options) {
		this.state = reactive(options.state)
		this.options = options
	}
	commit(type, payload) {
		this.options.mutations[type].call(this, this.state, payload)
	}
}

21、vuex中actions与mutations有什么区别?

要修改vuex中的store中的数据只能通过`mutatins`进行修改
`actions`只能通过提交`mutations`修改状态,不可以直接修改Stroe数据,可以进行任意的异步操作

22、防抖与节流?


防抖和节流作为前端性能优化的方式之一

解决的问题:高频动作带来的函数多次调用的问题
  1、页面滚动scroll
  2、浏览器窗口resize
  3、输入框input
  4、键盘keypress
  
防抖的定义:在一定时间间隔N秒后才执行该事件,若N秒中被重新触发,则重新开始计时
  1、输入框连续输入值后,只等到最后一次输入完成才出发查询的动作
  2、点赞,表单提交等动作,防止被重复提交
节流的定义:在一定时间中只运行一次,若在N秒中被再次触发,则只有第一次生效
  1、滚动加载:监听页面滚动到底部时触发
  2、拖拽场景:固定时间只执行一次,防止高频率的位置变动

23、GET请求和POST请求的本质区别?

GET在浏览器回退时是无害的,而POST会再次提交请求。
GET产生的URL地址可以被Bookmark,而POST不可以。
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会设保留。
GET请求在URL中传送的参数是有长度限制的,而PGST没有。
对参数的数据类型,GET只接受ASCll字符,而POST没有限制。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递教感信息
GET参数通过URL传递,POST放在Request body中。

总结:
1get请求和post请求都是TCP链接
2、http是个人行为准则,而TCP才是GET和POST怎么实现的基本。
3GET产生一个TCP数据包,而POST产生两个TCP数据包,复杂的说就是get请求是直接将http header和data一起发送个后端服务器,而post请求时,先发送header服务器响应后再发送data数据。

24、再浏览器中输入一个域名,这之间输入一个域名到页面显示出来中间经历了哪些操作?

  在浏览器中输入域名会有一个DNS服务器解析,获取一个IP地址,通过IP地址访问服务器之后会返回一个html,然后再下载css文件以及js文件,下载完成后再渲染页面。

25、this的绑定规则?

1、默认绑定 ==> 独立调用

1.全局环境中,this默认绑定到window
  console.log(this === window);//true
2.函数独立调用时,this默认绑定到window
function foo() {
  	console.log(this === window);
  }
  foo(); //true
3.被嵌套的函数独立调用时,this默认绑定到window
  //虽然test()函数被嵌套在obj.foo()函数中,但test()函数是独立调用,而不是方法调用。所以this默认绑定到window
var a = 0;
  var obj = {
  	a: 2,
  	foo: function() {
  		function test() {
  			console.log(this.a);
  		}
  		test();
  	}
  }
  obj.foo(); //0

4.如果调用obj.foo()本身,foo()函数中的this指向调用函数的对象,即obj对象
var a = 0;
  var obj = {
  	a: 2,
  	foo: function() {
  		console.log(this.a);
  	}
  }
  obj.foo(); //2

5.IIFE立即执行函数实际上是函数声明后直接调用执行
 var a = 0;
  function foo() {
  	(function test() {
  		console.log(this.a); //this指向window
  	})()
  };
  var obj = {
  	a: 2,
  	foo: foo
  }
  obj.foo(); //0

6.由于闭包的this默认绑定到window对象,但又常常需要访问嵌套函数的this,所以常常在嵌套函数中使用var that = this,然后在闭包中使用that替代this,使用作用域查找的方法来找到嵌套函数的this

2、显式绑定 ==> 间接调用

通过call()、apply()、bind()方法把对象绑定到this上,叫做显式绑定。对于被调用的函数来说,叫做间接调用

var a = 0;

function foo() {
	console.log(this.a);
}
var obj1 = {
	a: 1
};
var obj2 = {
	a: 2
};
foo.call(obj1); //1
foo.call(obj2); //2

API:
javascript中新增了许多内置函数, 具有显式绑定的功能, 如数组的5个迭代方法: map()、 forEach()、 filter()、 some()、 every()
var id = 'window';

function foo(el) {
	console.log(el, this.id);
}
var obj = {
	id: 'fn'
};
[1, 2, 3].forEach(foo); //1 "window" 2 "window" 3 "window"
[1, 2, 3].forEach(foo, obj); //1 "fn" 2 "fn" 3 "fn"

3、隐式绑定 ==> 方法调用

当函数作为对象里的方法被调用时, this 是调用该函数的对象
function foo() {
	console.log(this.a);
};
var obj1 = {
	a: 1,
	foo: foo,
	obj2: {
		a: 2,
		foo: foo
	}
}

//foo()函数的直接对象是obj1,this隐式绑定到obj1
obj1.foo(); //1

//foo()函数的直接对象是obj2,this隐式绑定到obj2
obj1.obj2.foo(); //2

隐式丢失:
  隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到window。这种情况容易出错却又常见
var a = 0;

  function foo() {
  	console.log(this.a);
  };
  var obj = {
  	a: 2,
  	foo: foo
  }
  //把obj.foo赋予别名bar,造成了隐式丢失,因为只是把foo()函数赋给了bar,而bar与obj对象则毫无关系
  var bar = obj.foo;
  bar(); //0

4、new绑定 ==> 构造函数调用

如果函数或者方法调用之前带有关键字new,它就构成构造函数调用。对于this绑定来说,称为new绑定。理解new一个对象发生的过程。this指向创建的新对象。
function fn() {
	this.a = 2;
}
var test = new fn();
console.log(test.a); //2