前端面试题--高频率

一.git&gitHub

1.什么是git

git是版本管理工具
主要分为四个不同区域:工作区,存储区,本地仓库,远程仓库
在工作区有一个隐藏目录.git,这个是本地版本库

2.git指令

保存
git init 初始化仓库
git add 。 工作区的内容提交到暂存区
git commit -m ‘提交信息’ 从暂存区提交到本地仓库
git status 查看状态
git log 查看提交信息

撤销
git checkout 文件名 暂存区覆盖工作区的内容
git rest  --hand commitId 根据id名重置工作区的内容
git rm --cached 文件名 删除暂存区的内容

分支
git branch 查看分支
git branch 分支名称 创建分支
git checkout 来源分支 切换分支
git merge 分支名称 合并分支
注意:必须在主分支master上才能合并
git branch -d 分支名称 删除分支(-D)强制删除
注意:合并分支后才能删除

保留
git stash 存储临时改动
git stash pop 恢复改动

3.git项目流程

我在做项目的时候,一般会使用git远程仓库进行项目,再多人开发项目的时候,项目组长会创建一个远程仓库,然后,我要把远程仓库克隆下来,git clone 命令,来进行项目的操作,首先,我要安装依赖库,配置好所需要的组件,完成之后,我要先创建一个子分支,子分支一般以自己的名字命名,在子分支上进行项目操作,git branch 分支名称  命令创建子分支,然后,用git branch来查看是否在自己的分支上,如若在主分支上,则要切换到子分支上用git checkout命令进行,现在在子分支上,按着项目的需求,把自己分支的工作完成,完成之后,我要提交到远程仓库,我第一步要做的就是pull一下,git pull命令,然后用git add 。和git commit -m命令来进行提交一下,然后,把本地仓库的内容提交到远程仓库,git push命令,等项目结束后,组长会进行合并分支,git merge命令进行

4.为什么先拉取在推送

不先拉取,会提示报错,报错的原因是因为,在提交的过程,本地仓库与远程仓库的版本不同,所以要先拉取一下,更新本地仓库,然后,查看是否有冲突,如果有手动解决冲突,没有,直接推送
二.var、let、const的区别
var:1.不受限于块级作用域
	2.可以重复声明变量
	3.声明的变量存在声明提升,变量可以在声明之前调用,值:underfind
声明提升:就是将变量提升到当前作用域的最顶部
let和const:1.受限于块级作用域
		   2.有暂时性死区
		   3.不能重复声明变量
		   4.变量不存在声明提升,一定在声明后使用,否则会报错
const:是常量,不可改变的量,一旦改变会报错,声明之后进行赋值,否则或报错
暂时性死区:使用let命令声明变量前,该变量是不存在的
三.箭头函数与普通函数的区别
箭头函数:1.是匿名函数,不能作用于构造函数,不能new
		2.不具有arguments对象,可以用展开运算符...解决
		3.没有原型prototype属性
		4.的this指向是父级的上下文
		5.不能使用apply(),call(),bind(),不能直接修改this指向
普通函数:1.可以有匿名函数,也有具名函数,可以用于构造函数,以此创建实例对象
		2.具有arguments对象
		3.有原型prototype属性
		4.的this指向调用它的对象
四.什么是arguments?
是伪数组,参数集合,原型上没有数组的方法,比如push,pop等方法,但是可以转换成数组
es5里可以,借用数组原型
function fun(){
 // 伪数组 不能使用数组方法
 console.log(arguments)
 // 伪数组转换为数组
 let arr = [...arguments]
 console.log(arr)
 let arr = [6,7,8]
 // 伪数组使用数组方式
 // apply 改变指向 传递的参数是一个数组
 Array.prototype.push.apply(arguments,arr)
 console.log(arguments)
 }
 fun(1,2,3,4,5)
es6里可以,利用展开运算符...参数的方法
let fn=(...arguments)=>{
	consloe.log(arguments)
}
五.es6解构赋值
定义:解构赋值就是从目标对象或数组中提取变量
应用场景:element-ui vant-ui的按需引入 请求接口返回数据,提取想要的数据
1.数组结构赋值:左右值是一一对应的
var a,b;
[a,b]=[10,20]
console.log(a)//10
console.log(b)//20
2.对象结构赋值:值是根据属性名来赋值
({a,b}={a:10,b:20})
console.log(a)//10
console.log(b)//20
3.解构赋值:交换a,b的值
var a = 1,b = 2;
[a,b] = [b,a];
console.log(a); // 2
console.log(b); // 1
4.// 剩余运算符 数组:根据数组的形式,左右值是一一对应的,a,b的值,剩下的就是...rest的啦
var a,b,rest;
[a,b,...rest] = [22,33,44,55,66]
console.log(a); // 22
console.log(b); // 33
console.log(rest); // [44,55,66]
5.// 剩余运算符 对象:值是根据属性名来赋值,位置发生变动,值也不变
var a,b,rest;
({a,b,...rest}={a:22,b:33,c:44,d:55,f:66})
console.log(a); // 22
console.log(b); // 33
console.log(rest); // [44,55,66]
六.es6 class继承和es5继承
es5中的类:
es5中生成实例对象需要定义构造函数,通过new操作符来生成实例对象。
定义了构造函数并且new构造函数,后台会隐式执行new Object()创建对象。并将构造函数的作用域给到新对象,即实例对象的this直接指向构造函数,
es5继承:
1.原型链继承:父类的实例作为子类的原型
优点:简单易于实现,父类的新增实例与属性子类都能访问
缺点:可以在子类中增加实例属性,如果要新增原型属性和方法需要在new父类构造函数的后面无法实现多继承
创建子类实例时,不能向父类构造函数中传参数

2.借用构造函数继承:复制父类的实例属性给子类
优点:解决子类构造函数向父类构造函数传递参数,可以实现多继承
缺点:方法在构造函数中定义,无法复用
不能继承原型属性/方法,只能继承父类的实例属性和方法

3.组合继承:既能调用父类实例属性,又能调用父类原型属性
优点:函数可复用,不存在引用属性问题,可以继承属性和方法,也可以继承原型的属性和方法
缺点:由于调用两次父类,所以产生了两份实例
es6中的类:
es6中引入了class类的概念,通过class关键字定义类。
定义方法不能使用function关键字
方法之间不能用逗号隔开,不然会发生报错
class定义的类实质上是一个函数,指向自身相关联的构造函数,可以理解为class类是构造函数的另一种写法
在通过class定义的类中存在prototype属性的。class定义的类中的方法都被保存在prototype中。
可以通过Object.assign方法动态给对象增加方法。
constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法
constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例
在constructor内部定义的属性可以称为实例属性,constructor外声明的属性都是定义在原型上的,可以称为原型属性。然后通过hasOwnProperty()函数用于判断属性是否是实例属性,返回值为布尔值。然后通过in操作符可以判断属性是否在类中。结合这两个方法可以判断该属性时在类的实例上还是原型上。
class不存在变量提升,所以需要先定义再使用。因为ES6不会把类的声明提升到代码头部,但是ES5就不一样,ES5存在变量提升,可以先使用,然后再定义。
es6继承:
代码量少,简单易懂
通过class关键字定义一个类,子类通过extends关键字来继承父类的属性和方法
子类的constructor方法中通过super关键字继承父类的属性
在子类的原型上通过super关键字来继承父类的方法
七.for/in和for/of的区别
1.for..in遍历数组会得到下标
2.for...in遍历对象得到是对象的key值
1.for...of遍历数组得到的是value
2.for...of直接遍历对象会报错
3.for...of遍历对象需要配合Object.keys()
var obj = {a:100,b:200,c:300}
for(var a of Object.keys(obj)){
 console.log(a) // 得到的也是对象的key值 a b c
 console.log(a+':'+obj[a]) // a:100 b:200 c:300
}
八.深拷贝和浅拷贝
深拷贝:创建一个新的对象和数组,将原对象的各项属性的值(数组的所有元素)拷贝过来,是值而不
是'引用'
浅拷贝:将原对象或数组的引用直接赋给新对象或新数组,新数组/新对象只是原对象的一个引
用
手动深拷贝(递归代码)
function deepClone(obj){
// 判断传入的参数是不是对象或数组,如果传入的是null或者不是对象或数组return 返回
 // 用typeof来检测 数组的检测结果也是object
 
 if(typeof obj !=='object'||obj==null){
 	return obj
 }
 
 // 初始化返回结果
 let result
 
 // 判断传入的是数组还是对象
 // 用instanceof 来判断obj 是否在Array的原型链上 如果在就是数组
 if(obj instanceof Array){
 	result=[]
 }else{
 	result={}
 }
 
  //for ... in 遍历obj
 	for(var key in obj){
 	// 保证key不是原型上的属性
 		if(obj.hasOwnProperty(key)){
 		result[key]=deepclone(obj[key])
 		}
 		return result
 	}
}

var add={
	name:'小高',
	age:18,
	sex:{sex:'女'},
	arr:['a','b','c']
}
const obj1=deepclone(add)
consloe.log(obj1.arr)//a,b,c
obj1.arr[0]='d'
consloe.log(obj1.arr[0])//d
九.es5和es6的继承有啥区别
es5继承:在子类中创建自己的this指向,最后将方法添加到this中
es6继承:使用关键字先创建父类实例对象this,最后在子类class中修改this
十.什么是promise?
1.promise是一个容器,异步操作的结果
2.在语法上,Promise是一个对象,获取异步操作的最终状态
3.Promise还是一个构造函数,对外有统一的Api,自身上有all,resolve,reject等方法,原型上有then,catch方法
4.promise有三种状态,初始状态,成功状态,失败状态
状态不可逆,只能由初始状态到成功状态或者是初始状态到失败状态
5.new创建了一个promise对象,有两个参数,resolve,reject
6.应用场景:promise对axios二次封装、promise封装ajax、promise封装wx.request、promise封装uniapp.reqest
7.promise小写是‘promise实例’,promise首字母大写‘promise构造函数’,promise首字母大写且复数‘promise规范’
8.promise的Api
- then
  - 把原来的回调分离出来,用链式调用的方式回调,then有两个回调函数,第一个成功,第二个失败
- catch
  - 和then的参数一样,用来指定错误的reject的回调,在执行then方法时,如果报错会执行catch方法
- all
  - 并行执行异步操作,在所有异步操作成功后回调,all会把异步操作的结果放入数组里传递给then
- race
  - 用法和all一样,只要有一个异步操作执行完毕,就立刻执行then回调
  应用场景:获取接口数据,超时的时候,用race方法
  9.promise的链式调用,解决了地狱回调的问题
异步加载图片(手写)
// Promise异步加载图片 race()
function imgOnlad(){
	let p = new Promise((resolve,reject)=>{
		// 创建img
		let img = new Image()
		img.src = '图片路径'
		img.onload= function(){
			resolve(img)
		}
	})
	return p
}

// 超时加载
function timeOut(){
	var p = new Promise((resolve,reject)=>{
		setTimeout(()=>{
			let span = document.createElement('span')
			span.innerText = '加载失败'
			resolve(span)
		},50)
	})
	return p
}


//Promise race()
Promise.race([imgOnlad(),timeOut()]).then(res=>{
	document.body.appendChild(res)
})
promise封装ajax(手写)
// Promise 封装Ajax
function Fun(method,url){
// 创建Promise
let p = new Promise((resolve,reject)=>{
	
	// 创建Ajax核心对象
	var xhr = new XMLHttpRequest()
	
	//开启请求
	xhr.open(method,url,true)// 请求方式  请求地址 是否为异步
	
	// 发送请求
	xhr.send(null)
	
	// 监听异步回调
	xhr.onreadystatechange = function(){
		if(xhr.readyState == 4 && xhr.status == 200){
			resolve(xhr.responseText)
		}else if(xhr.status == 400){
			reject('请求失败')
		}
	}
})
	return p
}

let url='http://wthrcdn.etouch.cn/weather_mini?city=%E5%8C%97%E4%BA%AC'
	Fun('get',url).then(res=>{
	console.log(res)
})
 promise all方法(手写)
// Promis all() 模拟验证用户名和手机号
// 模拟用户名验证通过
var p = new Promise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok')
	}, 1000)
})


// 模拟手机号通过
var p1 = new Promise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok')
	}, 2000)
})

p.then(res => {
	console.log(res)
})

p.then(res => {
	console.log(res)
})

// 两个验证必须都通过才能进行下一步操作哟
// Promise all() 所有异步都执行完 才会执行回调
Promise.all([p,p1]).then(res=>{
	
	let data = res.every(item=>{
		return item === 'ok'
	})
	console.log(data)
	if(data){
		document.querySelector('button').disabled = false
	}
})
// every 不会改变原数组,会返回一个新数组
// every 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)
// 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
// 如果所有元素都满足条件,则返回 true。
十一.小程序的目录结构
1.app.js是公共js样式
2.app.json是公共配置文件
3.pages定义页面级路由 谁想在前,写前面就行
4.写完定义的路由名字后,会自动生成4件套 .js .json .wxml .wxss
5.app.wxss是公共css样式
6.utils文件
7.project。config。json 项目配置文件
8.sitemap。json
十二.小程序组件封装
1.首先,创建一个 子组件 components文件夹
2.在components下定义一个w-swipe目录,然后,自动生成组件的(js,json,wxml,wxss)四个部分
3.然后,手动配置一下,文件
w-swipe下的wxml

  
    
      
    
  


w-swipe下的wxss
.swiper {
  height: 360rpx;
}

.swiper-image {
  width: 100%;
  /* height: 100%; */
}

w-swipe下的js
// components/w-swiper/w-swiper.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    images:{
      type:Array,
      value:[]
    }
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {

  }
})

w-swipe下的json
{
  "component": true,
  "usingComponents": {}
}
4.在pages创建一个父组件 demo
5.也会自动生成4个文件 demo.js demo.json demo.wxml demo.wxss 
demo.js
在data里定义一个数组 imgList:[]
生命周期函数得第一个onLoad里
var that=this
wx.request({
url:'http://123.207.32.32:8000/api/h8/home/multidata',
data:{},
method:'get',
success(res){
	let {data:{data:{list:{list}}}}=res
	that.setData({
	imgList:list
	})
	}
})
demo.json
{
'w-swipe':'/compoonents/w-swipe/w-swipe'
}
demo.wxml

十三.小程序如何设置data数据
setData

this.setData({
 	//定义数据
})
#.小程序得碎知识点
组件name:component
页面name:pages
全局name:app
小程序如何获取value值:item
小程序如何设置data数据:this.setBata
图片请求得时候,要在onload这个生命周期函数定义,越早越好
十四.promise对wx.request封装
1.在根目录下创建一个evn目录,在目录里创建一个index.js文件,是多环境开发,分别是开发环境,测试环境,生产环境三部分
2.在根目录下在创建一个http目录,在目录里创建三个js文件,分别是api.js文件,是放接口数据的地址
  fetch.js文件,用new Promise来封装了wx.request()网络模块
  http.js文件是根据当前环境,设置相应的baseUrl, 引入fetch中封装好的promise请求,封装基础的get\post\put\upload等请求方法,设置请求体,带上token和异常处理等,设置对应的方法并导出;
3.定义好后,在app.js文件导入http文件,在组件下面定义http
4.在页面使用的时候 let app=getApp(),在onload生命周期函数里使用 app.http.then()方法
十五.小程序常用的组件有哪些
item组件、swpier组件(轮播组件)、返回顶部组件、from表单组件,view组件,text组件,image组件、button组件,navigator(导航组件),icon组件,tab标签栏组件,checkbox组件,底部组件 

你可能感兴趣的:(javascript,vue.js,es6)