前端朋友出去问到的面试题 2020-10-9

1、var let const 区别 暂时性死区

	函数提升优先于变量提升,函数提升会把整个函数挪到作用域顶部,变量提升只会把声明挪到作用域顶部

	var 存在提升,我们能在声明之前使用。 let 、 const 因为暂时性死区的原因,不能在声明前使用

	var 在全局作用域下声明变量会导致变量挂载在 window 上,其他两者不会

	let 和 const 作用基本一致,但是后者声明的变量不能再次赋值

2、js 如何实现继承, class、原型继承、组件继承

	1 > 改变原型对象的指向 将子类函数 (B) 的 prototype 指向父类构造函数的 (A) 的一个实例化对象 (a) 那么
	
	      这个子类的构造函数构造出的实例化对象 (b) 就可以访问 (A) 的属性和方法 
	    
	      缺陷 : 由于 B 的 prototype 改变 那么保存在原来 B 中的 prototype 得属性和方法 就无法访问

	      解决方案 : 先进行原型指向的改变 在定义子类的原型属性与方法

	2 > 借用构造函数实现继承 利用 call 方法 或 apply 方法 借用父代的构造函数 在子代构造函数中加入添加父代

	      构造函数.call(this.父代形参列表) 同时在子代形参中加入父代形参列表 相当于在子代构造函数中 也写入了

	      父代构造函数中定义的属性和方法 

	      优点 : 可在子代构造函数实例化对象时自己初始化父代的属性和方法 不再是继承的固定实现

	      缺点 : 无法进行原型链查找 无法访问父代原型中的属性及方法

	3 > 组合继承法 A . 改变 prototype 指向子代与父代之间形成的原型链 可以继承父代原型的属性和方法

		       B . 借用父代的构造函数,实现继承和父代构造函数内的属性与方法 可以实例化子代时自己初始化这些属性与方法

3、事件流 事件捕获,处于目标阶段、事件冒泡、事件委托

	stopPropagtion( ) 阻止事件冒泡

	preventDefualt( ) 阻止默认行为

	事件委托利用的是 事件冒泡的原理 

4、this 指向 - ES6 之前 this, ES6 箭头函数 this

	在 es6 之前

	    1 > 全局打印 this 指向 window 

	    2 > (不开启严格模式) this 指向 windeo 严格模式 this 指向 undefind

	    3 > 定时任务中 this 指向 windeo 

	    4 > 事件绑定 this 指向事件类型 也就是点之前的事件源

	    5 > 对象方法中 this 指向当前对象

	    6 > 构造函数中的 this 指向 new 出来的实例

	es6 之后

	    1 > 箭头函数不绑定 this 关键字 箭头函数中的 this 指向的是函数定义位置的上下文中的 this 箭头函数指向定义位置中的 this

	          指向

	    2 > 箭头函数内部 不能使用 arguments 来获取实参 使用剩余参数写法 获取所有实参

	    3 > 箭头函数不是构造函数 不能实例化

5、如何改变 this 指向,call、apply、bind

	   call : 调用 call 函数 会立即执行 改变this指向 第一个参数是要修改的 this指向 传递多个参数使用 , 隔开 如果传参为空或null 则默

	           认为全局传参 不改变this指向 

	   apply : 调用了 apply 函数会立即执行 改变 this 指向 第一个参数是要修改 this 指向 传递参数用数组形式 不改变 this 指向

	   bind : 调用了 bind 方法 函数不会立即执行 返回一个改变了 this 指向的新函数 第一个参数是要修改的 this 指向 传递多个参数

	             使用 , 隔开 如果不需要改变 this 指向的话  第一个参数 传递 null 

6、什么是跨域,如何解决跨域, jsonp(原理)、代理 proxy

	   跨域 : 就是从一个域名去请求另一个域名的资源 跨域时浏览器不能执行其他域名网站的脚本 是由浏览器同源策略造成 为啥要跨域

	            因为在实际开发中经常会有跨域的情况, 公司很多项目 会有很多子域名 各个项目或者网站之间需要相互调用对方的资源所以要跨域

	  如何解决跨域 : 1 > 通过 josnp 实现跨域 原理 : 是利用 script 标签的跨域能力 来发送请求

		        2 > 设置 script 的 src 属性 一定要设置回调函数  

		        3 > 第三方代理 实现跨域

		        4 > document.domain + iframe跨域 ( iframe 被淘汰的技术 ) 

		        5 > location.hash + iframe ( iframe 被淘汰的技术 ) 

		        6 > window.name + iframe跨域 ( iframe 被淘汰的技术 ) 

		        7 > postMessage跨域

		        8 > 跨域资源共享(CORS)

		        9 > WebSocket协议跨域

7、get、post 请求区别是什么、ajax 的原理 XMLHttpRequest

	   get 请求参数 在 url 中显示 使用 post 不会显示出来

	   get 发送数据量小 post 请求发送数据量大 

	   get 请求 需要注意缓存问题 post 请求  不需要担心这个问题

	   ajax 的原理   第一步:创建XMLHttpRequest对象

		      var xhr = new XMLHttpRequest();
			
		      第二步:告诉Ajax对象要向哪发送请求,以什么方式发送请求

		      xhr.open('get', 'http://localhost:3000/first');

		      第三步:发送请求

		      xhr.send();

		      第四步:获取服务器端响应到客户端的数据

		      xhr.onload = function (){ console.log(xhr.responseText) }

8、Promise、await、async

	  promise 是一个 josn 对象 使用 promise 必须要 then 来处理所得到的的 JOSN 对象

	  async 函数可以代码更简洁 不需要像 promise 一样 不需要then 也不需要定义多余的data变量 避免了代码嵌套

	  await 必须写在 async 函数中 async 会隐式的返回一个 promise await 不能在最外层代码使用

9、面向对象三角形画图,构造函数 、prototype、实例对象__proto_(查找规则)

   创建一个构造函数(属性、方法), 并生成实例,

	  利用构造函数来创建实例  要和 new 一起使用 

	  创建对象的三种方式 利用 new Object ( ) 的方式

			利用对象字面量的方式 { }
	
			利用构造函数创建对象

	  new 在执行时 会做四件事 

			在内存中创建一个新的空对象

			让 this 指向这个新的对象

			执行构造函数里面的代码 给这个新对象添加属性和方法

			返回这个新对象 ( 所以构造函数中不需要 return )

   	 JS 规定 每一个构造函数都有一个 prototype 属性 指向另一个对象 --> 原型对象

	 每个对象都有一个__proto__ 指向 构造函数的 prototype 原型对象 他们都有一个

	 constructor 属性 constructor 称为构造函数 因为他指回构造函数本身

	 查找规则 : 当访问一个对象的属性 ( 包括方法 )时, 首先查找这个对象自身有没有该

	 属性 如果没有就查找他的原型 ( 也就是__proto__ 指向的 prototype 原型对象) 以此

	 类推 一直找到 Object 为止 ( null )

10、Vue 生命周期,必会, created ~ mounted 之间 Vue 做了哪些东西

	 生命周期 : 第一阶段 : beforeCreate 初始化的过程 这时候 data 数据访问不到 同时 methods 方法也不能调用

			只能访问一些生命周期的钩子函数 也可以说 只能访问 vue 提供的一些方法

		第二阶段 : created 阶段 vue 中的 data 和 methods 已经初始化完成 能访问到 data 中的数据, 以及

		               methods 中的方法 若想最早发送 axios 请求 获取数据 最早应该在 created 中

		第三阶段 : beforeMount 阶段 是 vue 对代码进行编译阶段 若网速特慢 则页面能看到插值表达式 vue

		               开始从 data 中获取数据 取出来数据和插值表达式以及指令等进行结合渲染 该阶段是在内存

		               中进行,也就是说 页面上看不到具体数据

		第四阶段 : mounted 这是 vue 创建阶段的第四个生命周期 表示代码在内存中编译成功 并渲染到页面中

		               用户可看到已渲染好的页面 当执行完 mothods 就代表 vue 实例已经创建好 此时 我们可以对

		               页面元素进行操作
		
		第五阶段 : beforeUpdate 这是 vue 运行的第五个阶段 是运行阶段的第一个生命周期 此时页面中显示的

		               数据还是旧的 但是 data 中的数据已经是最新的了

		第六阶段 : updated 这是 vue 第六个阶段 是运行阶段的第二个生命周期 此时页面显示的数据和 data 

		               中的数据都是最新的 这一步 vue 根据 data 中的最新数据生成了一份新的 DOM 结构在内存中

		               当最新的 DOM 树被渲染到页面的时候 就完成了 data --> view 的更新与渲染

		第七阶段 : beforeDestroy 解除绑定 销毁子组件以及事件监听器

		第八阶段 : destroyed 销毁完毕

11、v-if 和 v-show,以及他们的区别,Vue 指令

	v-if 是 "真正" 的条件渲染 因为他会确保在切换过程中 条件快内的事件监听器和子组件适当的被销毁和重建 简单的说

	就是 DOM 元素结构是否能够渲染

	v-show 在频繁切换显示与否的时候 使用 v-show ; 是控制元素是否显示 不会操作 DOM 

12、什么是渐进式框架,

	声明式渲染 --> 组件系统 --> 客户端路由 --> 集中式状态管理 --> 项目构建

	说白了 就是现在已经有一个应用项目 可以在其中的一两个页面来使用 vue 带来更丰富的交互体验 但是想

	在前端实现更多的 更加复杂的逻辑功能 vue 的核心库和生态系统也是可以满足相关业务需求的

13、嵌套路由获取参数

	1 > 如果是模块化机制,需要调用 Vue.use ( VueRouter ) 

	2 > 定义路由组件

	3 > 定义路由

	4 > 创建 router 实例

	5 > 创建和挂载根实例

	6 > 嵌套路由是通过 children ,他同样是一个数组

	7 > 动态路由的创建 主要是用 path 属性过程中 使用动态路径参数 以冒号开头 如 :id 当匹配到这个路由时 参数值会被

	      设置到 this.$router.params下 可以通过这个属性来获取到动态参数

14、Vue 组件之间传值 父 --> 子 子 -->父 兄弟 var bus = new Vue() | Vuex

	父传子 父 : 引入子组件 <child : 方法名 = "传入的值"></child>    子 : 在 props 中接收["方法名"] 

	子传父 子 : this.$emit( '字方法名', 传的值)           父 : 在 html 中 < child @字方法名 = "字方法名">< /child >

	兄弟传方法一   传 : 引入 bus.js 文件 bus.$emit ( '传方法名', 传的值 ) 接 : 在 mounted 中  bus.$on("传方法名", (传的值) => {} )

	兄弟传方法二   传 : 为了方便我们的操作 我们就不用引入 bus.js 而是直接调用 this.$root.$emit("传方法名", 传的值)

		      接 : this.$root.$off ('传方法名')         this.$root.$on('传方法名' , function (传的值) {} )

		      这里的 this.$root.$off( '传方法名' ) 就是为了每一次的进入的时候都要关闭一下

15、Vue 响应式原理 或者 v-model 原理, v-bind、v-on:input

	当你把一个普通的 JS 对象传入 Vue 实例 作为 data 选项 Vue 将遍历次对象的所有属性 并使用 Object.defineProperty 把这些数据

	全部转为 getter/setter  每个组件实例 都有对应的一个 watcher 实例 他会在组件渲染的过程中把"接触"过得数据属性记录为依赖 之

	后当依赖项的 setter 出发时 ,  会通知 watcher 从而使他关联的组件重新渲染

16、移动端如何适配页面 viewport 网达、新安网

	通过设置 < meta name = "viewport"> 视口标签来视口初始大小 供移动设备使用

	视口分为 布局视口  视觉视口  理想视口 ( 理想视口 通过 <meta name = "viewport" content = "width = device-width, initial-scale = 1.0"> 来实现 )

	百分比方案 使用百分比 来定义宽度 高度 用 px 固定 根据可视区的实时尺寸来进行调整 尽可能的使用各种分辨率 通常使用 max-width/min-width
	
	rem - flexible 是相对长度单位 rem 方案中的演示设计为相对于根元素 font-size 及计算值的倍数 根据屏幕宽度 设置 html 标签的 font-size 在布局时使用

	      rem 单位布局 达到自适应的目的  是弹性布局的一种实现方式
	
	flex 

17、你遇到过哪些兼容性问题, 点击高亮、前缀

	不同浏览器的标签默认外补丁margin和内补丁padding不同  解决方案 使用CSS通配符*,设置内外补丁为0 即 : *{ margin: 0; padding: 0;}

	如何解决兼容性问题 : 浏览器 CSS 样式初始化  浏览器私有属性 CSS hack (针对不同浏览器写不同的特定CSS样式)

18、模块化、组件化

	哪些问题 CMD\AMD\CommonJS
	
	ES6\ import export default

19、js 异步原理 单线程 + 事件队列

	打印顺序是什么?为什么?
	console.log('1')
	
	setTimeout(function () {
		console.log('2')
	}, 0)
	
	console.log('3')
	
	打印的是 1、3、2'

	JS 是单线程的 同步和异步的任务 将同步代码放在执行栈中依次执行 将异步代码放在执行队列中

	执行栈 --- 放置的是同步代码

	执行队列 (任务队列) --- 异步任务 ( 绑定事件/定时任务/ajax请求 )

	JS执行顺序 1 > 就是把同步任务推入主线程 异步任务推入任务队列中

		 2 > 把执行栈中的同步任务 推入到主线程中 开始执行

		 3 > 执行栈为空后 读取任务队列中的微任务 推入执行栈

		 4> 循环执行任务队列 知道任务列表为空

20、你对自己未来两年计划是是什么?

21、你对前端怎么看

猜你喜欢

转载自blog.csdn.net/weixin_48116269/article/details/109171699