前端总结

104 阅读13分钟

为什么 JavaScript 是单线程

  • javaScript 的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript 的主要用途是与用户互动,以及操作 DOM。这决定了它只能是单线程 (假定JavaScript 同时有两个线程,一个线程在某个 DOM 节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准)

JS 中数据类型(八种)

 基本数据类型(值类型):
   	  String 字符串
   	  Number 数值
   	  Boolean 布尔值
   	  null 空值
   	  undefined 未定义
     ES6中新增:
   	  BigInt 大型数值
   	  Symbol 唯一性
   	  
   	引用数据类型(引用类型):Object 对象
   	 内置对象 FunctionArrayDateRegExpError 等都是属于 Object 类型

var let const 共同及区别 🔥

 var 全局变量  作用于全局  可以重复声明
   	 let const 局部变量  作用于块级作用域 不存在变量提升 暂时性死区   如 {} 不可重复声明
   	 如:暂时性死区
   	    console.log(name) ❌  若在声明之前使用变量,就会报错。  
   	    let name=1
   	 const 声明变量是要初始化值  声明常量 不可更改 声明引用类型时可修改其属性
   	 如:const a; ❌   const a = 1;✅
   		const a =1;    a=2const a={n:1}  a.n=2

new 实现 🔥

 1.首先创一个新的空对象。
 2.根据原型链,设置空对象的 __proto__ 为构造函数的 prototype 。
 3.构造函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)。
 4.判断函数的返回值类型,如果是引用类型,就返回这个引用类型的对象。

原型和原型链?🔥

每一个实例对象都有一个私有属性__proto__,指向它的构造函数的原型对象(prototype)。

原型链的核心就是依赖对象的_proto_的指向,当自身不存在的属性时,就一层层的扒出创
建对象的构造函数,直至到Object时,就没有_proto_指向了。

浅拷贝和深拷贝🔥

深拷贝和浅拷贝是只针对ObjectArray这样的引用数据类型的
   浅拷贝
      Object.assgin() 实现浅拷贝
      ... 扩展运算符
      for in 遍历 添加到新的变量中
      concat() slice()
      
   深拷贝
      递归实现深拷贝
       JSON.parse(JSON.stringify())  JSON对象实现深拷贝 不能处理函数。

同源和跨域🔥

同源策略:
	同源策略是浏览器的一种安全策略,所谓同源是指,域名,协议,端口完全相同。
		  
	跨域解决方案:
	 1.JSONP 只能通过 GET script 标签的 src 属性传递数据。(不推荐使用) 
		   本质是利用了 <script src="">标签具有可跨域的特性,由服务端返回一个预先定义好的JS函数的调用,并且将服务器数据以该函数参数的形式传递过来。此方法需要前后端配合完成。
   2.后端配置跨域资源共享(CORS3.nginx反向代理解决跨域(前端常用)

promise和async await的区别 🔥

首先说说两者的概念
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,简单地说,Promise好比容器,里面存放着一些未来才会执行完毕(异步)的事件的结果,而这些结果一旦生成是无法改变的
实现原理
说到底,Promise 也还是使用回调函数,只不过是把回调封装在了内部,使用上一直通过 then 方法的链式调用,使得多层的回调嵌套看起来变成了同一层的,书写上以及理解上会更直观和简洁一些。

async await也是异步编程的一种解决方案,他遵循的是Generator 函数的语法糖,他拥有内置执行器,不需要额外的调用直接会自动执行并输出结果,它返回的是一个Promise对象。
两者的主要用法、语法就不赘述了,感兴趣的同学可以自行查阅 es6中文文档

两者的区别
 1. Promise的出现解决了传统callback函数导致的“地域回调”问题,但它的语法导致了它向纵向发展行成了一个回调链,遇到复杂的业务场景,这样的语法显然也是不美观的。而async await代码看起来会简洁些,使得异步代码看起来像同步代码,await的本质是可以提供等同于”同步效果“的等待异步返回能力的语法糖,只有这一句代码执行完,才会执行下一句。
 2. async awaitPromise一样,是非阻塞的。
 3. async await是基于Promise实现的,可以说是改良版的Promise,它不能用于普通的回调函数。
简单来看,这两者除了语法糖不一样外,他们解决的问题、达到的效果是大同小异的,我们可以在不同的应用场景,根据自己的喜好来选择使用

script标签中defer和async的区别是什么 🔥

<script>	在 HTML 中的顺序	 阻塞
<script async>	网络请求返回顺序	可能阻塞,也可能不阻塞
<script defer>	在 HTML 中的顺序	不阻塞

字符串()方法

  查找字符串 【🔥】【🔥】
        获取字符串中指定内容的索引
         indexOf() 是从前向后查找字符串的位置,
   	  lastIndexOf() 是从后向前寻找
         includes() 字符串中是否包含指定的内容 返回布尔值 true false
   	  
   	  startsWith() 字符串是否以指定的内容开头
   	  endsWith() 字符串是否以指定的内容结尾
   	  
    字符串截取  【🔥】 【🔥】
   	 slice()
   	 新字符串 = str.slice(开始索引, 结束索引) 包左不包右
   	 
   	 substring()
   	 新字符串 = str.substring(开始索引, 结束索引) 包左不包右。
   	 
   	 但不同之处在于
   	 substring()不能接受负值作为参数。如果传递了一个**负值**,则默认使用 0substring()还会自动调整参数的位置,如果第二个参数小于第一个,则自动交换。比如说, `substring(1, 0)`相当于截取的是第一个字符。
   	 
   	 substr()
   	 字符串 = str.substr(开始索引, 截取的长度)  ECMAscript 没有对 substr()方法进行标准化,因此不建议使用它。
   	 
   	 concat()   '1'+'e' 也是连接
   	 新字符串 = str1.concat(str2); //连接两个字符串
   	 
   	 split() 字符串转换为数组 【🔥】
   	 新的数组 = str.split(分隔符) 
   	 

内置对象 Number 的常见方法

   	 isInteger() 判断是否为整数
   	 toFixed() 小数点后面保留多少位 【🔥】
   	 
   	 Math对象的属性  
   	  Math.PI 圆周率 
   	  Math.abs()  **返回绝对值** 
   	  Math.random() 生成0-1之间的**随机浮点数** | 取值范围是 [01) 
   	  Math.floor()  **向下取整**(往小取值) 
   	  Math.ceil()  **向上取整**(往大取值) 
   	  Math.round()  四舍五入取整(正数四舍五入,负数五舍六入) 
   	  Math.max(x, y, z)   返回多个数中的最大值 
   	  Math.min(x, y, z)   返回多个数中的最小值 
   	  Math.pow(x,y)  乘方:返回 x 的 y 次幂 
   	  Math.sqrt()  开方:对一个数进行开方运算

数组的方法清单 => Array.方法

	  isArray()  判断是否为数组 
		   布尔值 = Array.isArray(被检测的数组)
		  toString() 数组转换为字符串
		  字符串 = 数组.toString();
		  
		   push()     【🔥】向数组的**最后面**插入一个或多个元素,返回结果为新数组的**长度**   - 会改变原数组 
		   pop()      删除数组中的**最后一个**元素,返回结果为**被删除的元素**          -  会改变原数组 
		   unshift()  【🔥】在数组**最前面**插入一个或多个元素,返回结果为新数组的**长度**    -  会改变原数组 
		   shift()    删除数组中的**第一个**元素,返回结果为**被删除的元素**            -  会改变原数组 
                                                                     
		   slice()    【🔥】从数组中**提取**指定的一个或多个元素,返回结果为**新的数组**                - 不会改变原数组 
		   splice()   【🔥】从数组中**删除**指定的一个或多个元素,返回结果为**被删除元素组成的新数组**   -会改变原数组   
		                                                                                                       
		   fill()     填充数组:用固定的值填充数组,返回结果为**新的数组** 
		   
		   join()   【🔥】将数组转换为字符串,返回结果为**转换后的字符串**(不会改变原来的数组)。
		   sort()   【🔥】 方法需要好好理解
		   // 自定义排序规则
		   let result = arr.sort(function (a, b) {
		       return a - b; // 升序排列
		       // return b - a; // 降序排列
		   });
		   
		   find()  【🔥】找出**第一个**满足「指定条件返回 true」的元素;如果没找到,则返回 undefinedfindIndex()  【🔥】找出**第一个**满足「指定条件返回 true」的元素的 index。
		   
		   every() 和 some() 的使用场景【🔥】
		   every() 全部真,才为真。当你需要让数组中的每一个元素都满足指定条件时,那就使用 every()。
		   some() 一个真,则为真,点到为止。数组中只要有一个元素满足指定条件时,就停止遍历。那就使用 some()。
		   
           forEach() 不能改变原数组 
		   如果你需要通过 forEach 修改原数组,
		   建议用 forEach 里面的参数 2 和参数 3 来做,具体请看下面的标准做法。
		   let numArr = [1, 2, 3];
		   numArr.forEach((item, index, arr) => {
		       arr[index] = arr[index] * 2;
		   });
		   console.log(JSON.stringify(numArr));
		   
		   map()  【🔥】
		   reduce() 【🔥】
		   
		   filter() 【🔥】对数组中的**每一项**运行回调函数,该函数返回结果是 true 的项,将组成新的数组(返回值就是这个新的数组)。不会改变原数组。
		

vue


	1.v-if v-show  【🔥】 简单
	  共同点:控制元素显示隐藏
	  不同点:v-if   每次都会重新添加/删除DOM元素  
		      v-show 是样式display:none 隐藏
      应用场景:频繁的切换 推荐使用 v-show,反正 v-if (具体看需求使用)
		  
	2.v-cloak 【🔥】 和CSS 规则一起用的时候,能够解决差值表达式闪烁问题
		  
	3.v-html v-text 🔥 简单
	   v-text是纯文本, v-html会被解析成html元素 
	   v-html渲染数据可能会非常危险,因为它很容易导致 XSS(跨站脚本攻击)
		  
	4.组件传值🔥
	   $emit/$on 通过一个空的Vue实例作为中央事件总线(事件中心)
	     var Event=new Vue();
		 Event.$emit(事件名,数据);
	 	 Event.$on(事件名,data => {});
			 
	常见使用场景可以分为三类:
			 
		父子通信:
		  父向子传递数据是通过 props,子向父是通过 events($emit);通过父链 / 子链也可以通信($parent / $children);ref 也可以访问组件实例;provide / inject API;$attrs/$listeners
			 
	    兄弟通信:
			 Bus (事件中心);Vuex
			 
		跨级通信:
			 Bus(事件中心); Vuex;provide / inject API;$attrs/$listeners
			 
	5.watch  computed
	  watch
	   添加deep属性,表明要深度遍历
       添加immediate属性,表明 立即执行
       不支持缓存,数据变,直接会触发相应的操作;
       支持异步;
      computed
       支持缓存,只有依赖数据发生改变,才会重新进行计算
       不支持异步,当computed内有异步操作时无效,无法监听数据的变化
     
     
    6.$nextTick是什么
      nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用nextTick,则可以在回调中获取更新后的 DOM
      
    7.vue生命周期 (官网,太多不想写了)
    
    
    8. scoped作用及实现原理
     实现组件的私有化, 当前style属性只属于当前模块.
     PostCSS给一个组件中的所有dom添加了一个独一无二的动态属性,然后,给CSS选择器额外添加一个对应的属性选择器来选择该组件中dom,这种做法使得样式只作用于含有该属性的dom——组件内部dom

    9.vue路由模式及实现原理
      两种模式:hash模式(默认)、history模式(需配置mode: 'history')
     实现原理:
      #就是hash符号,中文名哈希符或锚点
      利用了window可以监听onhashchange事件,url中的哈希值(#后面的值)如果有变化,前端是可以做到监听并做一些响应(搞点事情),这么一来,即使前端并没有发起http请求他也能够找到对应页面的代码块进行按需加载

     history 模式:利用了 HTML5 History Interface    中新增的 pushState() 和 replaceState()  方法。这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求
     
    10Vue渲染过程浅析
     1.把模板编译为render函数
     2.实例进行挂载, 根据根节点render函数的调用,递归的生成虚拟dom
     3.对比虚拟dom,渲染到真实dom
     4.组件内部data发生变化,组件和子组件引用data作为props重新调用render函数,生成虚拟dom, 返回到步骤3
      

vuex面试题点击查看


1.css只在当前组件起作用
答:在style标签中写入scoped即可 例如:<style scoped></style>

2.v-if 和 v-show 区别
答:v-if按照条件是否渲染,v-show是display的block或none;

3.$route和$router的区别
答:$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等。

4.vue.js的两个核心是什么?
答:数据驱动、组件系统

5.vue几种常用的指令
答:v-for 、 v-if 、v-bind、v-on、v-show、v-else

6.vue常用的修饰符?
答:.prevent: 提交事件不再重载页面;.stop: 阻止单击事件冒泡;.self: 当事件发生在该元素本身而不是子元素的时候会触发;.capture: 事件侦听,事件发生的时候会调用

7.v-on 可以绑定多个方法吗?
答:可以

8.vue中 key 值的作用?
答:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM9.什么是vue的计算属性?
答:在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。好处:①使得数据处理结构清晰;②依赖于数据,数据更新,处理结果自动更新;③计算属性内部this指向vm实例;④在template调用时,直接写计算属性名即可;⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。

10.vue等单页面应用及其优缺点
答:优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。
11.怎么定义 vue-router 的动态路由? 怎么获取传过来的值
答:在 router 目录下的 index.js 文件中,对 path 属性加上 /:id,使用 router 对象的 params.id 获取。

前端面试必备之十大经典排序算法

1. 冒泡排序【🔥】
function bubbleSort(arr) {
   var len = arr.length;
   for (var i = 0; i < len - 1; i++) {
       for (var j = 0; j < len - 1 - i; j++) {
           if (arr[j] > arr[j+1]) {        // 相邻元素两两对比
               var temp = arr[j+1];        // 元素交换
               arr[j+1] = arr[j];
               arr[j] = temp;
           }
       }
   }
   return arr;
}
2. 选择排序【🔥】
function selectionSort(arr) {
   var len = arr.length;
   var minIndex, temp;
   for (var i = 0; i < len - 1; i++) {
       minIndex = i;
       for (var j = i + 1; j < len; j++) {
           if (arr[j] < arr[minIndex]) {     // 寻找最小的数
               minIndex = j;                 // 将最小数的索引保存
           }
       }
       temp = arr[i];
       arr[i] = arr[minIndex];
       arr[minIndex] = temp;
   }
   return arr;
}
3.插入排序 【🔥】
function insertionSort(arr) {
   var len = arr.length;
   var preIndex, current;
   for (var i = 1; i < len; i++) {
       preIndex = i - 1;
       current = arr[i];
       while(preIndex >= 0 && arr[preIndex] > current) {
           arr[preIndex+1] = arr[preIndex];
           preIndex--;
       }
       arr[preIndex+1] = current;
   }
   return arr;
}

Git常见单词

常规操作
git init 	创建仓库
git clone 克隆代码
git status 查看当期状态
git fetch 拉取所有分支
git add 添加
git commit 缓存
commit 操作
撤销commit 
git reset  b14bb52记录回滚代码不回滚
git reset --hard b14bb52 讲提交记录和代码全部回滚
git log 查看版本
git reflog 查看所有版本


把本地仓库提交远程仓库
1.建立本地仓库和远程仓库的链接
git remote -v  查看仓库地址
git remote add origin [git远程地址]  建立 本地和远程连接
git remote rm origin [git远程地址]    删除本地和远程连接

提交代码之前最好先拉代码
git pull origin master
提交代码
git push origin master