JS基础知识1
基础点:
- es5 原型链、
2. 继承、
3. this指向、
4. new操作符、
5. 隐式转换、
6. 事件循环机制macro micro、
7. 基础类型、
8. 数据去重/交集/并集、
9. 判断是否为数组、
10. 变量声明提升、
11. 函数作用域、
12. 节流/防抖、
13. apply/call、
14. jsonp跨域、
15. cors
es6
- let/const、
- 箭头函数、
- promise、
- async/await
Vue
- 双向绑定实现、
- 组件通信方式
算法相关:
- 冒泡、
- 快排、
- 二叉树遍历、
- 大数相乘(适当刷下剑指offer)
网络相关:
- http2.0、1.1区别,
- tcp/udp,
- cookie/session等等
- es5 原型链
原型链是什么?
JavaScript万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条。
1> 每一个构造函数都是 由 FUNCTION 构造函数创建的
2> 每一个构造函数都有一个 prototype 的属性,指向原型对象,原型的对象的作用是共享方法
3> 每一个对象都有自己的 _proto_属性,用来指向构造函数prototype的原型对象
4> 每一个原型对象都有constructor 的属性,来指向构造函数的对象
5> _ _proto_ _对象原型和原型对象prototype是等价的
- 继承
Es6之前:通过构造函数+原型对象模拟实现继承,被称为组合继承。
//Call()作用:调用这个函数并且修改函数运行时的this指向。
1> 借助构造函数继承父类型属性,核心原理是通过call()把父类型的this指向子类型的this,这样可实现子类型继承父类型属性;
2.利用子构造函数的原型对象指向父构造函数的实例对象,可实现继承父的方法;
注:记得用子构造函数的原型对象的constructor指向子构造函数
Es6之后extends()方法
父类Class Father{ constructor{} };和它平级定义方法;
子类Class son extends Father{ constructor{super()} }
- this指向
1> 调用方式的不同决定了this的指向不同:
普通函数调用 this指向window
构造函数调用 this指向实例对象,原型对象里的方法也指向实例对象
对象方法调用 this指向该方法所属对象
事件绑定方法 this指向绑定事件对象
定时器函数 this指向window
立即执行函数 this指向window
2> 函数内部的this指向可通过bind(),call(),apply()来处理
call()方法: fun.call(thisArg,arg1,arg2,...);作用调用函数,并改变函数内部this指向,可以实现继承。
apply()方法:fun.call(thisArg,[argsArray])作用调用函数,并改变函数内部this指向,方便用于数组操作。
bind()方法:fun.bind(thisArg,arg1,arg2,...)不会调用函数,但是能改变函数内部的this指向,返回的是改 变this之后的新函数。可用于改变定时器内部的this指向。
3> 使用箭头函数;
4> 在函数内部使用`_this=this;`
- new操作符
new操作符新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象
1、创建一个空的对象
2、链接到原型
3、绑定this指向,执行构造函数
4、确保返回的是对象
function _new(func, ...args) {
let obj = Object.create(func.prototype);
let res = obj.apply(func, args);
return res instanceof Object ? res : obj;
}
- 隐式转换
1.一元加运算符:+ 强制转化为数字类型
2.数字和其他类型相加,和布尔、null、undefined都是转为数字,和字符串相加数字转为字符串
3.字符串和其他类型相加,结果为字符串
4.null+undefined == NaN 两者都转数字, null转数字为0, undefined转数字为NaN
5.obj与其他类型运算的时候, 会调用valueOf方法在调用String(obj)的时候, 会调用toString()方法对象的比较简单来说就是转化成字符串之后再进行比较
- 事件循环机制macro micro
Macro Task (宏任务)和 Micro Task(微任务)
宏任务主要包含:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
微任务主要包含:Promise、MutaionObserver、process.nextTick(Node.js 环境)
微任务跟在当前宏任务之后,代码执行到一个微任务就跟上,一个接一个
执行顺序:
1>当前脚本所有同步任务执行,遇到宏任务添加到宏任务,遇到微任务添加到微任务
2>执行当前脚本后的微任务
3>执行宏任务
如何区分宏任务和微任务呢?划分的标准是什么
宏任务本质:参与了事件循环的异步任务。
微任务本质:直接在 Javascript 引擎中的执行的,没有参与事件循环的异步任务。
宏任务,微任务的优先级
promise 是在当前脚本代码执行完后,立刻执行的,它并没有参与事件循环,所以它的优先级是高于 setTimeout。
- 基础类型
简单数据类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol(ES6新增)。Bigint(新增)
Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值
复杂数据类型(引用数据类型):对象(Object)、数组(Array)、函数(Function)。日期(Date)
基本类型存储的是值,复杂类型存储的是地址(指针)。
当你创建了一个复杂类型的时候,计算机会在内存中帮我们开辟一个空间来存放值,但是我们需要找到这个空间,这个空间会拥有一个地址(指针)。
当我们将变量赋值给另外一个变量时,复制的是原本变量的地址(指针),当我们进行数据修改的时候,就会修改存放在地址(指针) 上的值。
- 数据去重/交集/并集
const a = {fn: 1};
const set = new Set([1,1,2,2,3,4,5,5,5,a,'a']);
const b = new Set([6,7,8,9,5,4,3,'a','v']);
const only = [...new Set([])];//去重
const union = new Set([...set, ...b]);// 并集
const intersect = new Set([...set].filter(x => b.has(x)));// 交集
- 判断是否为数组
- Array.isArray()
- [] instanceof Array
- Object.prototype.toString.call([]) //输出的是[object,Array];
- 3.Object.prototype.toString.apply([])
- 变量声明提升
JS代码的执行过程分为两个阶段:
1.预解析阶段:进入某作用域时,js解析器会受限找到当前作用域中所有的变量和函数进行声明(提前在内存中为变量开辟好空间)
2.执行阶段: 执行当前作用域中的代码(遇到变量赋值则赋值)
1> 发现var 和function关键字进行声明
2> 当变量和function 同名时 函数名优先原则
Es6声明变量的六种方法:
Var命令、function命令、let命令、const命令、import命令、class命令
在es5中,var和function 声明的全局变量是顶层对象的属性
在es6中,let、const、class声明的全局变量不属于顶层对象的属性
//window.screenLeft是全局对象的属性,窗口距离屏幕左端的距离 var screenLeft=88; console.log(window.screenLeft) //88 不会在改变,var声明的变量与window中变量同名 影响了全局对象的属性 let screenRight=88; console.log(window.screenRight)//会改变,不影响顶层对象的属性
let const变量声明提升过程:
1、预解析阶段:JS解析器找到该作用域中所用变量,进行变量声明(即在内存中开辟存储位置,但并不初始化)
2、执行阶段:对变量进行赋值等等。。。。
特点
1、let、const声明变量同样存在变量声明提升问题,但其有一个特性:暂时性死区(tdc),变量声明之前,不可调用该变量,否则会报错
2、let、const声明变量绑定声明时的作用域,这个特性其实为JS新增了块级作用域
3、作用域中不能重复声明,否则会报错,解决了变量名称冲突问题
4、const用以声明一个只读的变量,一旦声明,则该变量在内存(栈)中位置不可变。
5、const当前作用域中不可变,其他作用域可以重新赋值)
const a="kxz"; { const a="康心志"; console.log(a) //"康心志" 不会报错 } console.log(a) //"kxz" 不会报错
6、const声明为基本类型的值不可变,const声明为引用类型,如对象,数组,等可以进行属性的改变。
例如:
const a={}; a.path="kxz.com"; console.log(a) //{path:"kxz.com"} 不会报错
7.Object.freeze() 对象冻结
/* const a={ path:"https://www.baidu.com" port:3000 } a.port=80; console.log(a.port) //80 */ const a={ path:"https://www.baidu.com" port:3000 } Object.freeze(a); a.port=80; console.log(a.port) //3000
js作为编程语言,最基本的功能是存储,只有把这个数据保存在内存中,才能参与计算和其他操作。而把数据保存到内存中并可顺利的取出来,需要规定一套机制或者说规则,在计算机中把对数据存储的规则叫作用域,而js的作用域是函数作用域,作用域是可以相互嵌套的但是不能重叠,外部无法访问内部作用域,内部可访问外部作用域。
(with、trycatch中的catch也是块级作用域,但是性能差,不推荐使用)
作用域的存在可以避免名称的污染,但是创建函数的过程中污染到了作用域,所以创建了立即执行函数
立即执行函数 iife
开头加字符会将函数声明语句转为函数表达式
匿名函数运行的几种方式
方式一 开头()后边跟()运行
方式二 new
方式三 !
方式四 true&&
方式五 false||
方式六 +
iife作用
1.避免作用域下命名污染
2.对整个性能有提升,不需要到大作用域中查找
3.有利于压缩
4.避免全局命名的冲突和填坑
5.保存闭包状态
6.颠倒代码运行顺序
Es5中只有函数作用域和全局作用域,导致很多地方不合理例如1.内层变量可能会覆盖外层变量2.for循环中的i会泄露成全局变量
Es6中出现了块级作用域
Es6允许作用域的任意嵌套、但外层作用域无法读取内层作用域、内层作用域可以定义外层作用域的同名变量、
Es5规定不能再块级作用域中声明
es6中允许在块级作用域中声明函数,函数声明类似于var,即会提升到全局作用域或作用域头部,同时函数声明还会提升到所在的块级作用域的头部。
考虑到环境差异太大,应避免在块级作用域中声明函数,如果确实需要,应写成函数表达式的形式,而非函数声明语句
12.节流/防抖
防抖(debounce)
原理:事件响应函数在一段时间之后才执行。如果在这段时间内再次调用,则重新计算时间
实现注意:1.this 2.event对象
应用场景:1> scroll事件滚动触发 2>搜索框输入查询 3>表单验证 4> 按钮提交事件
5>浏览器窗口缩放,resize事件
<div id="div1"></div>
<script>
var div1=document.getElementById("div1");
var count=0;
function doSome(e){
console.log(e);
count++;
console.log(count);
}
div1.onmousemove=debounce(doSome,200);
function debounce(func,wait){
let timeout;
return function(){
//1.修复函数内部指向问题
let that=this;
//2.修复了event指向问题
let arg=arguments;
clearTimeout(timeout);
timeout=setTimeout(function(){
func.apply(that,arg)
},wait);
}
}
</script>
节流(throttle)
原理:如果你持续触发事件,每隔一段时间,只执行一次事件
实现方式:1.使用时间戳 2使用定时器
应用场景:1> Dom元素的拖拽功能实现 2> 射击游戏 3> 计算鼠标移动距离
4>监听scrool滚动事件
<div id="div1"></div>
<script>
//dingshiqi
var div1=document.getElementById("div1");
var count=0;
function doSome(){
count++;
console.log(count);
}
div1.onmousemove=throttle(doSome,2000);
function throttle(func,wait){
let that,args,timeout;
return function(){
that=this;
args=arguments;
if(!timeout){
timeout= setTimeout(() => {
timeout=null;
func.apply(that,args);
}, wait);
}
}
}
</script>
<div id="div1"></div>
<script>
var div1=document.getElementById("div1");
var count=0;
function doSome(){
count++;
console.log(count);
}
div1.onmousemove=throttle(doSome,2000);
function throttle(func,wait){
let that,args;
let old=0;
return function(){
that=this;
args=arguments;
let now=new Date().valueOf();
if(now-old>wait){
func.apply(that,args);
old=now;
}
}
}
</script>
<div id="div1"></div>
<script>
//时间戳
var div1=document.getElementById("div1");
var count=0;
function doSome(){
count++;
console.log(count);
}
div1.onmousemove=throttle(doSome,2000);
function throttle(func,wait){
let that,args;
let old=0;
return function(){
that=this;
args=arguments;
let now=new Date().valueOf();
if(now-old>wait){
func.apply(that,args);
old=now;
}
}
}
</script>
13. apply/call
call()方法: fun.call(thisArg,arg1,arg2,...);作用调用函数,并改变函数内部this指向,可以实现继承。
apply()方法:fun.call(thisArg,[argsArray])作用调用函数,并改变函数内部this指向,方便用于数组操作。
14. jsonp跨域
跨域,指的是浏览器不能执行其他网站的脚本。浏览器执行`javascript`脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。
解决办法:
①JSONP:注意JSONP只支持GET请求,不支持POST请求。
原理:ajax请求受同源策略影响,不允许进行跨域请求,而script标签src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。
②代理:写后端接口,在后端调用页面拿到返回值返回给html文件。相当于绕过了浏览器,就不会存在跨域问题。
③CORS(axios中使用的就是cors)
设置header('Access-Control-Allow-Origin:*');//允许所有来源访问
设置header('Access-Control-Allow-Method:POST,GET');//允许访问的方式
15. Cors
跨域资源共享"(Cross-originresourcesharin
- let/const、
- let和const声明的变量,只在块级作用域中有效,
- Let和const声明的变量不存在变量提升,只要在声明之前使用变量就会报错
- Let和const声明变量形成暂时性死区,暂时性死区的本质是只要进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用改变量。
- 不允许重复声明。Let不允许在相同的作用域内重复声明一个变量。
- Const声明的变量,只在块级作用域中有效,
- Const声明一个只读的常量
- Const本质不是变量的值不得改动,而是变量指向的内存地址不得改动。对于简单数据类型,变量就保存在内存地址中,所以等同于常量,而对于复杂数据类型来说,变量指向的内存地址保存的只是一个指针,只能保证这个指针是固定的,不能控制其数据结构。(可以为对象添加属性但是不能对其重新赋值)
- Const和let本质区别是编译器内部处理不同
- Const优于let: 1>const可以提醒阅读程序的人,这个变量不应该改变。2>const比较符合函数式编程思想,运算不改变值只是建立新值。3>js编译器会对const进行优化,有利于提升性能 4>js可能会有多线程的实现,这时let表示的变量只应出现在单线程运行的代码中,不能多线程共享,有利于保证线程安全。
- 箭头函数、
- 箭头函数一条语句若返回对象字面量,则需要加括号
- 箭头函数在参数和箭头之间不能换行
- 立即执行函数可以写成箭头函数的形式
- 箭头函数不能用于构造函数
- 箭头函数没有prototype属性
- 箭头函数不绑定arguments,,取而代之用rest参数…解决
- 箭头函数不绑定this箭头函数没有自己的this
- 箭头函数无法使用 call()或 apply()来改变其运行的作用域
- 使用new调用箭头函数会报错,因为箭头函数没有constructor
- promise、
- promise是异步编程的一种解决方案,可以解决回调地狱问题,promise是一个对象,从它可以获取异步操作的信息。
- 优点:Promise其实就是做了一件事情,它是对异步操纵进行了封装,然后可以将异步操纵以同步的流 程表达出来,避免了层层嵌套的回调函数,同时提供了同一的接口,使得控制异步操纵更加容易。
缺点:
(1) 无法取消Promise,一旦被创建它就会立刻去执行,无法中途取消
(2) 如果不设置回调函数,Promise内部的错误无法反应到外部
(3) 当处于未完成状态时,无法得知目前进行到那个状态。
- Promise特点:
1) 对象状态不受外界影响。三种状态Pending(进行中)、Fulfilled(已成功) Rejected(已失败)
2) 状态一旦改变就不会再变称为resolved(已定型)。两种状态:成功(Pengding到fulfulled) 、失败(pengding到rejected)
- 基本用法:创建promise对象的实例,then方法指定Resolved状态和Rejected状态的回调函数。
var promise=new promise(function(resolve,reject){
if(/*异步操作成功*/){
resolve(value);
}else{
reject(error);
}
});
promise.then(function(value){
//success
},function(error){
//failure
})
- 其他:
(1) Promise.prototype.then()方法返回的是一个新的promise实例,可以再then方法的后面再次调用另一个then方法
(2) Promise.prototype.catch()方法用于指定发生错误的回调函数,错误总是会被下一个catch捕获。多个promise对象后也可跟一个catch进行错误捕获。
(3) Promise.all()和promise.race()用于将多个promise实例包装成一个新的promise实例。
(4) Promise.resolve()用于将现有对象转化成promise对象
- async/await
1.async是generator和promise的语法糖,利用迭代器的状态机和promise来进行自更新!
2.Async对Generator函数进行了改进。
(1) 内置执行器
(2) 更好的语义async代替*,await代替yield
(3) 更广的适用性
(4) 返回值是promise
3.async函数返回一个promise对象,async函数内部return语句返回的值,会成为then方法回调函数
4.await命令后面是一个promise对象,若不是则会被转成一个立即resolve的Promise对象
5.Async - 定义异步函数(async function someName(){...})
自动把函数转换为 Promise
当调用异步函数时,函数返回值会被 resolve 处理
异步函数内部可以使用 await
6.Await - 暂停异步函数的执行 (var result = await someAsyncCall();)
当使用在 Promise 前面时,await 等待 Promise 完成,并返回 Promise 的结果
await 只能和 Promise 一起使用,不能和 callback 一起使用
await 只能用在 async 函数中
20.Vue双向绑定实现
双向绑定怎么实现
数据劫持 发布订阅模式
vue中实现双向数据绑定的原理是:采用数据劫持结合发布者-订阅者的方式,
通过Object.defineProperty()来劫持各个属性的setter,getter,
在数据变动时,发布消息给订阅者,触发相应的监听回调。
实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。
通俗的讲,就是利用observe监听Model层的数据变化;
21.组件通信方式
通信种类:父子,子父,隔代,兄弟
- Props
- vue自定事件
- 消息订阅与发布
- Vuex
- Slot
- 冒泡、
function bubbleSort(arr){
let len=arr.length;
for(let i=0;i<len;i++){
for(let j=i+1;j<len;j++){
if(arr[i]>arr[j]){
[arr[i],arr[j]]=[arr[j],arr[i]]
}
}
}
return arr;
}
- 快排、
function quickSort(arr){
//找基准数
let firstnum=arr[0];
let left_arr=[];
let right_arr=[];
//大于基准数放左边数组,小于基准数放右边数组
for(let i =1;i<arr.length;i++){
if(arr[i]>firstnum){
right_arr.push(arr[i]);
}else{
left_arr.push(arr[i]);
}
}
//对左右数组进行快排 返回排序好的左右数组
if(left_arr.length>=2) left_arr=quickSort(left_arr);//递归
if(right_arr.length>=2) right_arr=quickSort(right_arr);//递归
//连接到一起
return left_arr.concat(firstnum,right_arr);
}
- 二叉树遍历
- 大数相乘
- 思路一:用Bigint 在数的末尾加n或者用BigInt()
- 模仿小学数学
var multiply = function(num1, num2) {
if(num1==0 || num2==0) return "0"
const res=[];// 结果集
for(let i=0;i<num1.length;i++){
let tmp1=num1[num1.length-1-i]; // num1尾元素
for(let j=0;j<num2.length;j++){
let tmp2 = num2[num2.length-1-j]; // num2尾元素
let pos = res[i+j] ? res[i+j]+tmp1*tmp2 : tmp1*tmp2;// 目标值 ==》三元表达式,判断结果集索引位置是否有值
res[i+j]=pos%10; // 赋值给当前索引位置
// 目标值是否大于10 ==》是否进位 这样简化res去除不必要的"0"
pos >=10 && (res[i+j+1]=res[i+j+1] ? res[i+j+1]+Math.floor(pos/10) : Math.floor(pos/10));
}
}
return res.reverse().join("");
};
- http2.0、1.1区别
HTTP/2采用二进制格式而非文本格式
HTTP/2是完全多路复用的,而非有序并阻塞的——只需一个连接即可实现并行
使用报头压缩,HTTP/2降低了开销
HTTP/2让服务器可以将响应主动“推送”到客户端缓存中
- tcp/udp
TCP(Transmission Control Protocol,传输控制协议)
UDP(User Data Protocol,用户数据报协议)
(1)TCP是面向连接的(需要三次握手建立连接),udp是无连接的即发送数据前不需要先建立链接。
(2)对系统资源的要求(TCP较多,UDP少)
(3)流模式与数据报模式 ;(TCP是面向字节流,UDP面向报文,并且网络出现拥塞不会使得发送速率降低因此会出现丢包,对实时的应用比如IP电话和视频会议等)。
(4)UDP程序结构较简单;
(5)TCP是面向连接的可靠性传输,而UDP是不可靠的TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。。
- cookie/session
cookie`和`sessiom`是两种保持会话状态的方法。
cookie就是指客户端在向服务端发起请求的时候,服务端会在进行response的时候给当前客户端的一小段文本信息,并保存在当前的客户端的浏览器中,这一小段cookie文本信息也就是这个客户端去访问服务端的通行证,有了这个通行证,以后当这个客户端再去访问服务端的时候,服务端便知道是谁拿着通行证去进行访问了。
session和cookie的功能类似,也是一种保持会话状态的方式,在用户使用浏览器发起会话时,服务器会为每一个用户浏览器提供一个单独的session对象来保存用户的数据,并将它保存在服务端,而当用户访问其他web资源的时候,则可以从保存用户数据的session对象中把用户数据抽取出来并进行访问。
区别:
1. cookie的用户数据是保存在用户浏览器的cookie中的;
session的用户数据是保存在服务器为用户浏览器单独创建的session对象中的。
2. 数据的读取和调用,cookie可以采用request.getCookies这种方法;
session则可以用request.Session的方法。
3. 安全性,cookie是存储在用户浏览器中的;
而session是存储在服务器上的,所以session比cookoe要相对安全;
22.讲讲你知道的状态码
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。所请求的资源必须通过代理访问
306 Unused 已经被废弃的HTTP状态码
307 Temporary Redirect 临时重定向。与302类似。使用GET请求重定向
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理
怎么判断空对象
- 使用for in循环可以遍历所有属性以次判断对象是否为空对象:
function isEmptyObject(obj){
for(var key in obj){
return false
};
return true;
};
2.Object.keys(obj)返回不包括原型上的可枚举属性,即自身的可枚举属性
var data = {};
var b = Object.keys(data).length === 0;
3.转成 json 格式的字符串、判断是否等于"{}"var data = {};
var b = JSON.stringify(data) == "{}";
alert(b); //true
vue组件传值
方式一:父子组件 props $emit
父传子 子组件里面定义props来做接收
子传父 用vue中的$emit将想要传递的值通过函数的形式传出,在父组件接收
this.$emit(arg1,arg2) arg1:方法名字,arg2:要传出的值
方式二:兄弟组件$emit $on
兄弟组件之间就需要一个中间值,我在这里称为bus。在vue文件main.js中,我们利用 Vue.prototype.bus=new Vue() 来定义,此时我们就有了一个中间量。
组件一
toBrother() {
this.bus.$emit("toBrother", this.msg1);
}
组件二:
beforeCreate() {
this.bus.$on("toBrother", msg => {
this.get = msg;
});
在第二个子组件里面通过beforeCreate生命周期来获得传过来的值,这时候需要用this.bus.$on来接收,第一个参数是this.bus.$emit定义的第一个方法名,第二个参数是一个方法,此方法带一个返回参数。在这里我使用箭头函数。
方式三:Vuex传值
Vuex 应用的状态 state 都应当存放在 store.js 里面,Vue 组件可以从 store.js 里面获取状态,可以把 store 通俗的理解为一个全局变量的仓库。但是和单纯的全局变量又有一些区别,主要体现在当 store 中的状态发生改变时,相应的 vue 组件也会得到高效更新。
在 src 目录下创建一个 vuex 目录,将 store.js 放到 vuex 目录下
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
// 定义状态
state: {
author: 'Wise Wrong'
}
})
export default store
组件中1中
computed: {
author () {
return this.$store.state.author
}
}
组件2中
methods: {
setAuthor: function () {
this.$store.state.author = this.inpuTxt
}
}
总结:
父子通信:
父向子传递数据是通过 props,子向父是通过 events($emit);通过父链 / 子链也可以通信($parent / $children);ref 也可以访问组件实例;provide / inject API;$attrs/$listeners
兄弟通信:
Bus;Vuex
跨级通信:
Bus;Vuex;provide / inject API、$attrs/$listeners
来源:https://segmentfault.com/a/1190000019208626
浅拷贝和深拷贝
浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用,如果拷贝后的对象发生变化,原对象也会发生变化。只有深拷贝才是真正地对对象的拷贝。
浅拷贝的意思就是只复制引用,而未复制真正的值。
深拷贝就是对目标的完全拷贝,不像浅拷贝那样只是复制了一层引用,就连值也都复制了。
只要进行了深拷贝,它们老死不相往来,谁也不会影响谁。
目前实现深拷贝的方法不多,主要是两种:
利用 JSON 对象中的 parse 和 stringify
利用递归来实现每一层都重新创建对象并赋值
Css复习
- 圣杯布局
方法一:float -margin position:relative
方法二:float -margin 和margin
方法三:position:absolute 和 position:relative 配合使用
方法四:flex
- 清除浮动
由于浮动元素不再占用原文档的位置,不清除浮动的花就会对后面的元素排版造成影响,即清除浮动主要为了解决父元素因为子级浮动而引起内部高度变为0,引起高度坍塌。
方法一:clear:both
在包裹浮动元素的父元素中末尾加上<div style="clear:both"></div>其中 .clear:both(left|right),解释一个left好了,清除左侧浮动影响也可以是不允许左侧有浮动元素。
方法二:overflow:hidden
缺点:内容增多造成不自动换行,导致内容被溢出、隐藏
方法三:给父级CSS也加上对应的floatfloat:xxx
方法四:父级增加一个CSS为clearfix(最常用)
.clearfix:after{
content:".";
display:block;
height:0;
clear:both;
visibility:hidden;
}
方法五:确定所需高度直接给父盒子设定高度
Vue中的生命周期
盒模型
1) 盒模型有两种,W3C 和IE 盒子模型
1、W3C定义的盒模型包括margin、border、padding、content,元素的宽度width=content的宽度
2、IE盒模型与W3C盒模型的唯一区别就是元素的宽度,元素的width=border + padding + content
2) 对盒模型的理解
IE定义的盒模型较为合理,所以在css3中新增了box-sizing,包含两个属性content-box和border-box。
(1) content-box 元素的width = content
(2)border-box 元素的width = border + padding + content
3)更多理解
对于行内元素 margin-top/margin-bottom对于上下元素无效,margin-left/margin-right有效
对于相邻的块级元素margin-top和margin-bottom两者叠加按照一定的规则
(1) 都是整数 margin值取两者的最大值
(2) 都是负数 margin值取最小值
(3)两者正负相反,margin值取两者之和
再往深的说就是bfc的理解了。
BFC
一、BFC 的概念
1.规范解释
块格式化上下文(Block Formatting Context,BFC)是Web页面的可视化CSS渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。
2.通俗理解
BFC 是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品。
如果一个元素符合触发 BFC 的条件,则 BFC 中的元素布局不受外部影响。
浮动元素会创建 BFC,则浮动元素内部子元素主要受该浮动元素影响,所以两个浮动元素之间是互不影响的。
二、创建 BFC
根元素或包含根元素的元素
浮动元素 float = left | right 或 inherit(≠ none)
绝对定位元素 position = absolute 或 fixed
display = inline-block | flex | inline-flex | table-cell 或 table-caption
overflow = hidden | auto 或 scroll (≠ visible)
三、BFC 的特性
BFC 是一个独立的容器,容器内子元素不会影响容器外的元素。反之亦如此。
盒子从顶端开始垂直地一个接一个地排列,盒子之间垂直的间距是由 margin 决定的。
在同一个 BFC 中,两个相邻的块级盒子的垂直外边距会发生重叠。
BFC 区域不会和 float box 发生重叠。
BFC 能够识别并包含浮动元素,当计算其区域的高度时,浮动元素也可以参与计算了。
四、BFC 的作用
1.包含浮动元素(清除浮动)
2.导致外边距折叠
3.避免外边距折叠
D
1.延迟加载'defer 属性。这个属性的用途是表明脚本在执行时不会影响页面的构造。也就是说,脚本会被延迟到整个页面都解析完毕后再运行。因此,在 <script> 元素中设置defer 属性,相当于告诉浏览器立即下载,但延迟执行
2.异步加载 async 只适用于外部脚本文件,并告诉浏览器立即下载文件,下载完成后立即执行。但与 defer不同的是,标记为 async 的脚本并不保证按照指定它们的先后顺序执行
3.使用 defer 属性可以让脚本在文档完全呈现之后再执行,延迟脚本总是按照指定它们的顺序执行。
使用 async 属性可以表示当前脚本不必等待其他脚本,也不必阻塞文档呈现。不能保证异步脚本按照它们在页面中出现的顺序执行。