http协议和https协议
http:
超文本传输协议,基于TCP/IP协议传输数据,应用最广泛的一种网络数据,所有的www文件都必须遵守这个标准。
https:
由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http安全。主要可以分为两种:一种是建立一个信息安全通道,保证数据传输的安全,另一种是确认网站的真实性。
区别:
http是超文本传输协议,信息是明文传输,https是具有安全性的ssl/tls加密传输协议。
https需要到CA申请证书
http和https使用的是完全不同的连接方式,http的端口是80,https的端口是443
http的连接很简单是无状态的,https是由ssl/tls+http协议构建的可进行加密传输、身份认证的网络协议,比http安全。
https的缺点:
https协议握手比较费时,会使页面的加载时间延长近50%,增加10%~20%的耗电。
https连接缓存不如http高效,会增加数据开销和功耗,
SSL证书需要钱,SSL证书通常需要绑定IP,不能在同一个IP上绑定多个域名
https协议的加密范围有限,在黑客攻击、拒绝服务攻击、服务器劫持方面起不到什么作用
实践建议
建议保留http,在切换的时候可以做http和https兼容,方式:去掉页面链接中的http头部,这样可以自动匹配http头和https头
参考链接: blog.csdn.net/qq_35745940…
mobx等、setstate 等
var、let、const理解
let声明和const声明,两个都是块级作用域,且var有变量提升,在let中,使用的变量一定要进行声明。
var可以重复声明,let不可以
var不受限于块级,let受限于块级
var可以在声明的上面访问变量,let有暂存死区,在声明上面访问会报错。
const声明后必须赋值,且不可变量否则会报错
react性能优化
react和vue的生命周期
vue的生命周期:1. beforeCreate(){}--->2.Create--->3.beforeMount---->4.mounted --->5.beforeUpdate--->6updated---->7.beforeDestroy ---->8.destoryed
beforeCreate(){
//this.say()//这里会报错 this没有
},
created(){ //这里可以使用this 数据请求
this.username="leson";
},
beforeMount(){//页面结构加载完成以前
},
mounted(){//页面结构完成
//写dom操作 定时器
//事件 window.onscroll
},
updated(){
console.log(this.userage);
},
react报错的时候如何看的
vue data为什么是个函数而不是对象
vue组件是可复用的vue实例,一个组件被创建好之后,可能被用在各个地方,组件被用了多少次,组件中的data数据都应该是互相隔离,互不影响的,基于这一理念,组件每复用一次,data数据就会被复制一次,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响。
如果data是对象的话,当被复用时,复用对象和源对象都会指向同一个内存地址,互相之间会互相影响,所以要是函数。
vue 渲染时 key 起到什么作用
key是虚拟dom对象的标识,当数据发生变化时,vue会根据新数据生成新的虚拟dom,随后vue进行新虚拟dom与旧虚拟dom的差异比较:
旧虚拟DOM中找到新虚拟DOM相同的key:若虚拟DOM中内容没变,直接使用之前的真实DOM,若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
旧虚拟DOM中未找到与新虚拟DOM相同的key:创建新的真实DOM随后渲染到页面
用index做key会引发的问题:
若对数据进行:逆序添加、逆序删除等破环顺序操作会产生没有必要的真实DOM更新
盒模型是什么
盒模型主要定义为:content、padding、margin、border
盒模型分为标准盒模型和IE盒模型
标准盒模型:windth = content; box-sizing:content-box;
IE盒模型:width = padding+border+content; box-sizing:border-box;
css两个隐藏属性的区别
display:none;使元素不显示,不在占据空间; viability:hidden;元素隐藏的同时占据空间;
redux的执行流程
浏览器的缓存机制
浏览器的缓存机制就是把一个请求过的web资源拷贝一份副本存储存在浏览器中;
缓存会根据进来的请求保存输出内容的副本,当一下个请求到来的时候,如果是相同的url,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向服务器再次发送请求
比较常见的就是浏览器会缓存访问过的页面,当再次访问这个URL地址的时候,如果网页没有更新就不会再次下载网页,而是直接使用本地缓存的网页
只有当网站明确标识已更新,浏览器才会再次下载网页
跨域的解决方案
请求url的协议、域名、端口三者之间任意一个与当前页面url不同的即为跨域
1.通过设置Access-Control-Allow-Origin为*
2.jsonp进行跨域[jsonp只支持get方法]
3.使用proxy代理解决跨域
git工具应的操作流程
git init 初始化项目
git status 查看当前目录下文件的状态
git add (文件名 | .)添加到暂存盘,文件名代表某文件,"."代表所有文件
git commit -m "备注" 提交到git本地仓库,产生新版本,引号中的备注必须写
git log 查看所有提交的记录
git clone 链接 克隆远程仓库,进行连接
git checkout -b [branch] 新建一个分支,并切换到该分支
git checkout [branch] 切换到某分支
git branch -d [branch-name] 删除分支
git merge [branch] 合并指定分支到当前分支
git push 将本地仓库push到远程仓库\
事件循环[先执行同步任务,在执行异步任务,执行一次同步任务,异步任务执行一轮,就是这种机制无限循环]
先执行同步再执行异步
所有同步任务在主线程上执行,形成一个执行栈
主线程之外,存在一个任务队列,异步任务有了运行结果,就在任务队列中放置一个事件
一旦主线程的栈中所有同步执行完,系统就会读取任务队列
主线程要做的就是从任务队列中去实践,执行事件,执行完毕,再取事件,再执行事件,这样不断读取事件,执行事件的循环机制叫事件循环机制
先promise ---> .then ---> settimeout
先执行微任务再执行宏任务
css定位
position:static静态定位用于取消定位
position:relative相对定位,没有脱离标准流,在页面中占位置
position:absolute绝对定位,脱离了标准流,在页面中不占位
position:fixed固定定位,脱离了标准流,在页面中不占位
promise的理解
参考: www.jianshu.com/p/f6d4371dd…
js数组的常用方法
1. Array.push(),向数组的末尾添加一个或多个元素,并返回新的数组长度。原数组改变。
var arr = [1,2,3,4];
arr.push(5,6,7);
arr = [1,2,3,4,5,6,7];
2. Array.pop(),删除并返回数组的最后一个元素,若该数组为空,则返回undefined。原数组改变。
var arr = [1,2,3,4,5];
var del = arr.pop(); //6
arr = [1,2,3,4,5]
3. Array.unshift(),向数组的开头添加一个或多个元素,并返回新的数组长度。原数组改变。
var arr = [1,2,3,4,5,6,7];
var res = arr.unshift(0); //8
arr = [0,1,2,3,4,5,6,7]
4. Array.shift(),删除数组的第一项,并返回第一个元素的值。若该数组为空,则返回undefined。原数组改变。
var arr = [1,2,3,4,5,6];
var res = arr.shift();//1
arr = [2,3,4,5,6,7];
5. Array.concat(arr1,arr2…),合并两个或多个数组,生成一个新的数组。原数组不变。
var arr = [1,2,3,4,5,6,7];
var arr1 = ['a','b','c'];
var arr2 = ['x','y','z'];
var res = arr.concat(arr1,arr2);//[1,2,3,4,5,6,7,'a','b','c','x','y','z'];
arr = [1,2,3,4,5,6,7];
6. Array.join(),将数组的每一项用指定字符连接形成一个字符串。默认连接字符为 “,” 逗号。
var arr = [1,2,3,4];
var str = arr.join();//1,2,3,4
var str1 = arr.join('-');//1-2-3-4
7. Array.reverse(),将数组倒序。原数组改变。
var arr = [1,2,3,4];
arr.reverse()//[4,3,2,1];
8. Array.sort(),对数组元素进行排序。按照字符串UniCode码排序,原数组改变。
①从小到大
var sortNum = function(a,b){
return a - b;
}
arr.sort(sortNum)
②从大到小
var sortNum = function(a,b){
return b - a;
}
arr.sort(sortNum)
③按照数组对象中的某个值进行排序
var arr = [{name:"a",age:12},{name:"b",age:14},{name:"c",age:10}];
function fn(params){
return function sortAge(a,b){
return a[params] - b[params]
}
}
arr.sort(fn('age'));// [{name:"c",age:10},{name:"a",age:12},{name:"b",age:14}]
9.Array.map(function),原数组的每一项执行函数后,返回一个新的数组。原数组不变。(注意该方法和forEach的区别)。 map 会返回一个新的数组,不会改变原来的数组,foreach不会反悔新数组,允许对原数组进行修改
10.Array.slice() 按照条件查找出其中的部分内容
参数:
array.slice(n, m),从索引n开始查找到m处(不包含m)
array.slice(n) 第二个参数省略,则一直查找到末尾
array.slice(0)原样输出内容,可以实现数组克隆
array.slice(-n,-m) slice支持负参数,从最后一项开始算起,-1为最后一项,-2为倒数第二项
返回值:返回一个新数组
是否改变原数组:不改变
11.Array.splice(index,howmany,arr1,arr2…) ,用于添加或删除数组中的元素。从index位置开始删除howmany个元素,并将arr1、arr2…数据从index位置依次插入。howmany为0时,则不删除元素。 原数组改变。
12.Array.forEach(function),用于调用数组的每个元素,并将元素传递给回调函数。原数组不变。(注意该方法和map的区别,若直接打印Array.forEach,结果为undefined)。
13.Array.filter(function),过滤数组中,符合条件的元素并返回一个新的数组。
14.Array.every(function),对数组中的每一项进行判断,若都符合则返回true,否则返回false。
15.Array.some(function),对数组中的每一项进行判断,若都不符合则返回false,否则返回true。
16.Array.reduce(function),reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
17.indexOf() 检测当前值在数组中第一次出现的位置索引
参数:array.indexOf(item,start) item:查找的元素 start:字符串中开始检索的位置。
返回值:第一次查到的索引,未找到返回-1。
是否改变原数组:不改变。
11、includes()
判断一个数组是否包含一个指定的值
参数:指定的内容
返回值:布尔值
是否改变原数组:不改变。
接着面试官可能还会问你: 原数组改变的方法有:push pop shift unshift reverse sort splice 不改变原数组的方法有:concat map filter join every some indexOf slice forEach
ts的理解和作用
同源的理解
怎么判断数据类型
var arr = [1,2,3]
1. typeof arr
2. arr instanceof Array
3. (arr).constructor
4. Object.prototype.toString.call(arr)
浏览器输入url的过程
- 浏览器输入url
- 根据域名解析出IP地址
1.检查浏览器缓存,有缓存:返回,没有缓存:下一步
2.检查系统缓存hosts文件
3.检查网络中路由器的dns缓存
4.递归查询,优先查找其他域名服务器,看有没有,没有在查找本地域名服务器,本地域名服务器用迭代查询查找
5.迭代查询不断向上访问查找 - 根据找到饿IP建立tcp连接进行三次握手
- 发送http请求
- 如果发生重定向,状态码是3开头,就返回第一步,继续匹配重定向的服务器
- 向重定向的服务器发送http请求
- 服务器处理请求,发送html响应
- tcp断开连接
- 根据响应,得到html渲染出界面
- 其他内容比如图片URL,返回第一步重新请求,如果请求过,就从浏览器缓存中得到
手写:
封装组件、重复渲染
输出8个console.log
console.log
console.table
console.error
console.info
console.debug
console.time
console.timeEnd
console.count
使用vue点击改变字体颜色,刷新页面颜色也不会丢失
this.$router.replace({
name: 'Home',
query: {
color: 'red'
}
})
/** 刷新当前界面 */
this.$router.go(0)
判断数组,至少两个
//方法一:
var arr = [];
arr instanceof Array
//方法二:
console.log([].constructor == Array); //true
console.log({}.constructor == Object); //true
console.log("string".constructor == String); //true
console.log((123).constructor == Number); //true
console.log(true.constructor == Boolean); //true
//方法三:
function isArray(o) {
return Object.prototype.toString.call(o);
}
var arr=[2,5,6,8];
var obj={name:'zhangsan',age:25};
var fn = function () {}
console.log(isArray(arr)); //[object Array]
console.log(isArray(obj)); //[object Object]
console.log(isArray(fn)); //[object function]
防抖、节流
// 防抖
function debounce (callback,delay) {
var t = null;
return function () {
clearTimeout(t);
t = setTimeout(callback,delay);
}
}
window.onscroll = debounce(function(){
console.log("调用了一次");
},500)
// 节流;
function throttle (callback,duration){
var lastTime = new Date().getTime();
return function () {
var now = new Date().getTime();
if(now - lastTime > 500){
callback();
lastTime = now;
}
}
}
window.onscroll = throttle(function(){
console.log("调用了一次");
},500)
邮箱的正则表达式
var emal = new RegExp(/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/);
//邮箱
emal.test('aaa@qq.com')
var url = new RegExp(/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/)
//url
var phone = new RegExp(/^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/)
//手机号
参考: www.cnblogs.com/fozero/p/78…
回调函数的链式调用(用promise)
let checkLogin=()=> {
return new Promise((resolve,reject)=>{
let flag=document.cookie.indexOf("userId")!=-1?true:false;
if(flag=true){
resolve({
status:0,
result:true
});
}else{
reject("error");
}
});
}
let getuseInfo=()=>{
return new Promise((resolve,reject)=>{
let useInfo={
status:0,
userId:101
}
resolve(useInfo);
})
}
checkLogin().then((res)=>{
console.log("Login Success");
return getuseInfo();
},(error)=>{
console.log(`error:${error}`);
}).then(res=>{
console.log(`userId:${res.userId}`);
});
//Promise.all()的使用
Promise.all([checkLogin(),getuseInfo()]).then(([res1,res2])=>{
console.log("Login Success");
console.log(`userId:${res2.userId}`);
})
var arr = [1,2,3,4,5,6]的随机排序
方法一:
var arr =[1,2,3,4,3];
function fn(arr){
var arr1 = arr.concat();
arr1.sort(function(n1,n2){
return Math.random() - 0.5;
})
return arr1
}
fn(arr)
方法二:
var arr = [1,2,3,4,3];
function fn2(arr){
var result = [];
var arr2 = arr.concat();
(function(){
if(!arr2.length){return}
var index = Math.floor(Math.random()*arr2.length);
result = result.concat(arr2.splice(index,1));
arguments.callee();
})();
return result;
}
fn2(arr)
实现数组去重
方法一:
var arr =[1,1,2,3,4];
let res = []
for (let i = 0; i < arr.length; i ) {
if (res.indexOf(arr[i]) == -1) {
res.push(arr[i])
}
}
方法二:
var arr = [1,1,2,3,4]
[...new Set(arr)]
方法三:
var arr = [1,1,2,3,4]
Array.from(new Set(arr))
css手写三角形
div{
width:0;
height:0;
border:3px solid transparent;
border-top-color:red;
}
使用vue做一个弹窗组件,点击叉号关闭弹窗
<template>
<transition name="move" appear>
<div class="message" v-if="visible">
<span>{{message}}</span>
<span class="close" @click="closeMessage">X</span>
</div>
</transition>
</template>
<script>
export default {
name: 'message',
props: {
message: {
type: String,
default: '内容'
},
visible: {
type: Boolean,
default: false
},
duration: {
type: Number,
default: 0
}
},
data () {
return {
timer: null
}
},
watch: {
visible (val) {
if (val) {
this.autoClose()
}
}
},
mounted () {
this.autoClose()
},
methods: {
autoClose () {
let _this = this
if (this.duration !== 0) {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
_this.closeMessage()
}, _this.duration + 500)
}
},
closeMessage () {
this.$emit('close', false)
}
}
}
</script>
<style scoped lang="scss">
.message{
min-width: 200px;
border: 1px solid #ccc;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
transition: opacity .3s,transform .4s,top .4s;
padding: 15px;
display: flex;
align-items: center;
justify-content: space-between;
.close{
color: #666;
cursor:pointer;
}
&.move-enter,&.move-leave-to{
opacity: 0;
top: 0;
}
&.move-enter-active,&.move-leave-active{
transition: 0.3s linear;
}
}
</style>
// Main.js
import message from './message.vue'
import Vue from 'vue'
let vm
const createMessage = (propsData) => {
if (Vue.prototype.$isServer) return
propsData = propsData || {}
if (typeof propsData === 'string') {
propsData = {
message: propsData
}
}
const Ctor = Vue.extend(message)
vm = new Ctor({ propsData }).$mount()
vm.$on('close', flag => {
vm.visible = flag
})
document.body.appendChild(vm.$el)
return vm
}
export default {
install (vue) {
vue.component(message.name, message)
vue.prototype.$BMessage = createMessage
}
}
//调用页面
this.$BMessage({
visible: true,
message: 'hello world',
duration: 3000
})
执行结果
async function async1(){
console.log('1');
await async2();
console.log('2')
}
async function async2(){
console.log('3')
}
console.log('4');
setTimeout(function(){
console.log('5');
},0)
async1();
new Promise(resolve=>{
console.log('6');
reslove();
}).then(function(){
console.log('7')
})
console.log('8')
//4、1、3、6、8、2、7、5
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
return new Promise(function(){
console.log('a')
}).then(function(){
console.log('b')
})
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
//script start---> async1 start--->async2--->a--->promise1--->script end--->async1 end--->promise2--->setTimeout
查找字符串中出现最多次数的字母
var str="ddasdasdasdasdasf";
function text(str){
var num=0;
var value='';
var json={}
for(var i=0;i<str.length;i++){
if(!json[str[i]]){
json[str[i]]=[];
}
json[str[i]].push(str[i]);
}
for(var i in json){
if(num<json[i].length){
num=json[i].length;
value=i;
}
}
console.log('出现最多次数的是:'+value+'总共出现:'+num+'次');
}
text(str)