为什么 JavaScript 是单线程
- javaScript 的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript 的主要用途是与用户互动,以及操作 DOM。这决定了它只能是单线程 (假定JavaScript 同时有两个线程,一个线程在某个 DOM 节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准)
JS 中数据类型(八种)
基本数据类型(值类型):
String 字符串
Number 数值
Boolean 布尔值
null 空值
undefined 未定义
ES6中新增:
BigInt 大型数值
Symbol 唯一性
引用数据类型(引用类型):Object 对象
内置对象 Function、Array、Date、RegExp、Error 等都是属于 Object 类型
var let const 共同及区别 🔥
var 全局变量 作用于全局 可以重复声明
let const 局部变量 作用于块级作用域 不存在变量提升 暂时性死区 如 {} 不可重复声明
如:暂时性死区
console.log(name) ❌ 若在声明之前使用变量,就会报错。
let name=1
const 声明变量是要初始化值 声明常量 不可更改 声明引用类型时可修改其属性
如:const a; ❌ const a = 1;✅
const a =1; a=2 ❌
const a={n:1} a.n=2 ✅
new 实现 🔥
1.首先创一个新的空对象。
2.根据原型链,设置空对象的 __proto__ 为构造函数的 prototype 。
3.构造函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)。
4.判断函数的返回值类型,如果是引用类型,就返回这个引用类型的对象。
原型和原型链?🔥
每一个实例对象都有一个私有属性__proto__,指向它的构造函数的原型对象(prototype)。
原型链的核心就是依赖对象的_proto_的指向,当自身不存在的属性时,就一层层的扒出创
建对象的构造函数,直至到Object时,就没有_proto_指向了。
浅拷贝和深拷贝🔥
深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的
浅拷贝
Object.assgin() 实现浅拷贝
... 扩展运算符
for in 遍历 添加到新的变量中
concat() slice()
深拷贝
递归实现深拷贝
JSON.parse(JSON.stringify()) JSON对象实现深拷贝 不能处理函数。
同源和跨域🔥
同源策略:
同源策略是浏览器的一种安全策略,所谓同源是指,域名,协议,端口完全相同。
跨域解决方案:
1.JSONP 只能通过 GET script 标签的 src 属性传递数据。(不推荐使用)
本质是利用了 <script src="">标签具有可跨域的特性,由服务端返回一个预先定义好的JS函数的调用,并且将服务器数据以该函数参数的形式传递过来。此方法需要前后端配合完成。
2.后端配置跨域资源共享(CORS)
3.nginx反向代理解决跨域(前端常用)
promise和async await的区别 🔥
首先说说两者的概念
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,简单地说,Promise好比容器,里面存放着一些未来才会执行完毕(异步)的事件的结果,而这些结果一旦生成是无法改变的
实现原理
说到底,Promise 也还是使用回调函数,只不过是把回调封装在了内部,使用上一直通过 then 方法的链式调用,使得多层的回调嵌套看起来变成了同一层的,书写上以及理解上会更直观和简洁一些。
async await也是异步编程的一种解决方案,他遵循的是Generator 函数的语法糖,他拥有内置执行器,不需要额外的调用直接会自动执行并输出结果,它返回的是一个Promise对象。
两者的主要用法、语法就不赘述了,感兴趣的同学可以自行查阅 es6中文文档
两者的区别
1. Promise的出现解决了传统callback函数导致的“地域回调”问题,但它的语法导致了它向纵向发展行成了一个回调链,遇到复杂的业务场景,这样的语法显然也是不美观的。而async await代码看起来会简洁些,使得异步代码看起来像同步代码,await的本质是可以提供等同于”同步效果“的等待异步返回能力的语法糖,只有这一句代码执行完,才会执行下一句。
2. async await与Promise一样,是非阻塞的。
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()不能接受负值作为参数。如果传递了一个**负值**,则默认使用 0。
substring()还会自动调整参数的位置,如果第二个参数小于第一个,则自动交换。比如说, `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之间的**随机浮点数** | 取值范围是 [0,1)
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;
});
find() 【🔥】找出**第一个**满足「指定条件返回 true」的元素;如果没找到,则返回 undefined。
findIndex() 【🔥】找出**第一个**满足「指定条件返回 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,但浏览器不会立即向后端发送请求
10。Vue渲染过程浅析
1.把模板编译为render函数
2.实例进行挂载, 根据根节点render函数的调用,递归的生成虚拟dom
3.对比虚拟dom,渲染到真实dom
4.组件内部data发生变化,组件和子组件引用data作为props重新调用render函数,生成虚拟dom, 返回到步骤3
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的作用主要是为了高效的更新虚拟DOM。
9.什么是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