基本数据类型
ES5-------Number/Boolean/String/Undefined/Null
ES6新增—symbol
引用数据类型
Object
检测方法4种
1、Object.prototype.toString.call()
**作用: 可以检测所有数据类型**
**所有数据类型都可以检测,而且非常正确**
语法: Object.prototype.toString.call( 'xxx'/11/[ ] )
返回值: [object Xxx], Xxx 就是对象的类型
2、constructor
**作用: 可以检测基本数据类型和引用数据类型**
**弊端: 把类的原型进行重写, 很有可能把之前的constructor覆盖 检测出来的结果就会不准确**
语法: ("xx")/([ ])/(function(){ }).constructor === String/Array/Function
返回值: true/false
3、instanceOf
**原理: 判断对象类型,基于原型链去判断(obj instanceof Object)**
**左边对象的原型链proto上是否有右边构造函数的proptotype属性**
**作用: 判断左边的对象是否是右边构造函数的实例**
**弊端: 用于引用类型的检测, 对于基本数据类型不生效**
语法: " "/[ ]/true instanceOf String/Array/Boolean
返回值: true/false
4、typeOf
**作用: 用于检测基本数据类型和函数**
**弊端: 引用数据类型(Arrary/function/object)只会返回Object, 不起作用**
语法: typeOf " "/[ ]/xx
返回值: "string"/"boolean"/"object" (无法区分)
每个对象都可以有一个原型_proto_,这个原型还可以有它自己的原型,以此类推,形成一 个原型链。查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对 象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找… 这个操作被委托在整个原型链上
1、prototype:每一个函数都有一个prototype这个属性,而这个属性指向一个对象,这个对象我们叫做原型对象
作用: 节约内存扩展属性和方法可以实现类之间的继承
2 、 proto :每一个对象都有一个_proto_属性_proto_ 指向创建自己的那个构造函数的原型对象对象 可以直接访问 proto 里面的属性和方法
3、constructor:指向创建自己的那个构造函数 ,是原型上的方法
总结: 当我们创建一个构造函数的时候这个构造函数自带了一个prototype属性,而这个属性指向一个 对象,也就是原型对象。 这个原型对象里面有一个constructor构造器,它的作用是指向创建自己的构造函数。除此之外 prototype还可以存放公共的属性和方法。 当我们实例化一个对象的时候(被new调用的时候),这个对象自带了一个 proto 属性,这 个proto 指向创建自己的构造函数的原型对象。可以使用这个原型对象里面的属性和方法
传统的javascript中只有对象,没有类的概念。它是基于原型的面向对象语言。原型对象特点就是将自身的属性共享给新对象。
ES6引入了Class(类)这个概念,通过class关键字可以 定义类。该关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言
constructor: constructor()方法是类的默认方法,通过new命令生成对象实例 时,自动调用该方法。一个类必须有constructor()方法,如果没有显式定义,一个空的 constructor()方法会被默认添加。
[https://www.jianshu.com/p/86267fab4878
原因:由于浏览器的同源策略,即属于不同域的⻚面之间不能相互访问各自的⻚面内容。
哪些情况下产生跨域
1、域名不同,2、 端口号不同,3、协议不同(http/https),4、域名和域名对应ip,5、主域名相同(127.0.01 和 localhost) 多域名匹配一个ip地址 6、子域名不同(一级和二级域名)
解决方法
1、后端代理 - 后端不存在跨域(后端代码脱离浏览器,后端是服务器端)
利用后端(自己公司的后端)去获取接口数据,将数据传给前端
2、jsonp原理** (json with padding) 数据填充的方式
利用浏览器的"漏洞" src不受同源策略的影响,可以请求任何链接 。动态创建script标签,将事先写好的函数名传给服务器,供服务器使用
(1)script标签src属性不存在跨域
(2)get方式–传递函数名 --弊端
(3)callback回调函数(传递函数名)
3、反向代理 proxy webpack配置
“proxy”: {
“/index.php”: {
“target”: “http://qinqin.net”,
“changeOrigin”: true
}
}
4.CORS解决跨域(xhr2) nginx
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源(协议 + 域名 + 端口)服务器,发出 XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
需要服务器(提供接口的源码里面)添加下面两句话。
header(‘Access-Control-Allow-Origin:*’);
header(‘Access-Control-Allow-Method:POST,GET’);
jsonp是一种非正式传输协议,用于解决跨域问 题流程: 1、创建一个全局函数 2、创建一个script标签 3、给script添加src 4、给src添加回调函数test(callback=test) callback是传给后端的一个参数 5、将script放到⻚面上 6、script请求完成,将自己从⻚面上删除
https://www.cnblogs.com/sdcs/p/8484905.html
闭包原理:定义在一个函数内部的函数(函数嵌套函数),闭包就是将函数内部和函数外部连接起来的一座桥梁。
打破了作用域链的规则 闭包就是能够读取其他函数内部变量的函数
用途**:a:可以读取函数内部的局部变量 b:让这些变量始终保持在内存当中 **
3注意:由于闭包会使得函数中的变量都被保存在内存当中,内存会消耗很大,所以不能够滥用闭包,否则会造成网⻚性能的问题 闭包
**优点:**1、使用闭包是不会污染全局环境,2、方便进行模块化开发,3、减少形参个数,延长了形参的生命周期,
坏处 1、就是不恰当使用会造成内存泄漏
闭包的不适用于返回闭包的 函数是个特别大的函数,很多高级应用都要依靠闭包实现.
使用场景:1、通过循环给页面上多个dom节点绑定事件 。2、封装私有变量(计数器) 3、:延续局部变量的寿命,4、高阶组件 5、函数防抖
模块化的就是以闭包为基础构建的;
/*
* fn [function] 需要防抖的函数
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
let timer = null
//借助闭包
return function() {
if(timer){
clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
timer = setTimeOut(fn,delay)
}else{
timer = setTimeOut(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时
}
}
}
1、意外的全局变量
2、被遗忘的定时器
3、没有清除的dom应用 ,故要及时清除,
4、滥用闭包
清除内存泄漏方法有两种,一是标记清除,二便是引用计数清除。
JS的垃圾回收机制是为了以防内存泄漏:标记清除(mark and sweep)、引用计数(reference counting)。
标记清除:垃圾收集器给内存中的所有变量都加上标记,然后去掉环境中的变量以及被环境中的变量引用的变量的标记。在此之后再被加上的标记的变量即为需要回收的变量,因为环境中的变量已经无法访问到这些变量。
引用计数:这种方式常常会引起内存泄漏,低版本的IE使用这种方式。机制就是跟踪一个值的引用次数,当声明一个变量并将一个引用类型赋值给该变量时该值引用次数加1,当这个变量指向其他一个时该值的引用次数便减一。当该值引用次数为0时就会被回收。
Promise 是es6新增的,异步编程的一种解决方案,用来取代回调函数和事件,比传统的解决方案——回调函数和事件——更合理和更强大。
有三种状态:pending(进行中)、fulfilled(resolve已成功)和rejected(已失败)。
promise的特点 :
(1)对象的状态不受外界影响。Promise对象代表一个异步操作。
(2)一旦状态设定,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为resolve和从pending变为rejected。只要这两种情况发生,状态就凝固了
promise的的方法
promise实例方法:Promise.prototype.then Promise.prototype.catch*
一:resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
二:reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
三:Promise.prototype.finally
finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
promise的 静态方法 Promise.all():用于将多个 Promise 实例,包装成一个新的 Promise 实例,接受一个数组作为参数,只有数组里面的每个状态都变成resolve,则新的 Promise 实例状态才会变成resolve.
Promise.race():将Promise对象数组中最先执行完成的内容通过后面then传出
promise的基本使用
1、通过new promise创建一个promise对象,里面有一个参数,参数是一个回调函数,回调函数中 有2个参数,resolve,reject resolve()当异步执行成功的时候调用的方法,reject()当异步失败的 时候调用的方法。
2、除此之外promise有一个then方法,当成功的时候执行第一个回调函数,当失败 的时候执行第二 个回调函数。第二个回调函数也可以通过promise对象.catch调用
3、Promise.all():当所有的异步代码都执行完毕以后才会执行.then中的操作
4、Promise.race():只要有一个promise执行完毕后就会执行.then操作
https://www.cnblogs.com/moveup/p/9746748.html
promise的三种状态与链式调用: pending - 进行中 fulfilled - 成功 rejected - 失败
https://www.jianshu.com/p/dc61ea153874
async异步能干什么?就是用来修饰函数,使该函数异步执行,不阻碍后续函数的执行 同时我们注意到,async修饰的函数也带有then catch方法,因此,经async修饰的函数也 是一个promise await只能放在async中,且只能修饰promise对象 1. promise的诞生是为了简化函数嵌套调用流程,也便于后续维护 2. async/await定义了异步函数,并在其内部可通过await等待promise对象,阻塞后 续的执行
**await关键字必须在async函数里面 await会阻塞当前直到完成 async返回reject的方法,当抛出异常等同于reject async / await与 Promise的主要区别是 Promise代码完全都是Promise的API(then、catch等等),操作本身的语义反 而不容易看出来, async / await函数的实现最简洁,最符合语义,几乎没有语义不相关的代码 async / await 函数就是 Generator 函数的语法糖
async/await函数的优势
1. 使用async函数可以让代码简洁很多,不需要像Promise一样需要些then,不需要 写匿名函数处理Promise的resolve值,也不需要定义多余的data变量,还避免了嵌 套代码
2. 使用aync/await的话,catch能处理JSON.parse错误 promise中不能处理
3. 条件语句也和错误捕获是一样的,在 Async 中也可以像平时一般使用条件语句
[promise的状态处理的原理] :https://www.jianshu.com/p/44a971659696
generator:https://www.jianshu.com/p/83da0901166f
await后面有个接口 接口要2S才能完成 接口2S才会执行
await是同步还是异步:await同步 async异步
async和await有两个关键字,一个写在函数外面,一个写在函数里面,函数外面是异步的 函数里面是同步的 调用函数的那一行其实是异步的,下一行
函数里面转成阻塞的
async函数中
let a=await promise 的a函数
let b=await promise 的b函数
promise.all改写 Promise.allSettled Promise.any
promise实现promise.all的方法
var test3 = async function () {
try {
await p1();
await p2();
p3();
} catch (e) {
console.log('p1失败了', e)
}
}
没区别
1、**堆**--引用类型地址传递
堆:动态分配的内存,大小不定,不会自动释放。
存放引用类型的值 先进后出FILO
引用类型: Object(Arrary, Date, Math,Function, Object)
访问方法: JS不能直接访问内存中的值, 只能操作对象的地址, 所以产生深/浅拷贝问题**
2、**栈**--基本类型值传递
自动分配内存空间,系统自动释放,
存放基本类型的值和引用类型的地址 先进先出FIFO
基本类型: Undefined、Null、Boolean、Number 和 String, Symbol(ES6新增)
访问方法: 按值访问, 直接操作内存中的值
为什么在react中要使用浅拷贝
redux中要求:状态是只读的,唯一且不可修改的,reducer必须是一个纯函数
-因为redux中数据不可更改,所以redux中的数据应该要拷贝 返回一个新值
浅拷贝–新旧互相影响,改变的是地址
新值===原值, 只能拷贝一层
数组方法 ` slice截取`, `concat拼接`, `filter过滤` , `map`,
对象方法 ` Object.assign({ },obj)`, `Object.create(obj)`
展开运算符`{…obj}` [...arr]
深拷贝–新旧互不影响,改变的是值
新值=/=原值 , 可以拷贝多层
1、JSON序列化** **JSON.parse( JSON.stringify(obj) )** 对象-->字符串-->对象
这个方式的弊端:
1.如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是对象的形式
2.如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象;
3、如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
5、JSON.stringify()只能序列化对象的可枚举的自有属性,不可枚举的不能被复制
可枚举 :可枚举性(enumerable)用来控制所描述的属性,是否将被包括在for...in循环之中。具体来说,如果一个属性的enumerable为false,下面三个操作不会取到该属性。
- for..in循环
- Object.keys方法
- JSON.stringify方法
2、**原生实现**
递归+浅拷贝
3、 **工具实现**【 第三方封装库 】
loadsh _.cloneDeep(obj)
缺点
4、Immutable
Object.create()
let let声明的变量有块作用域 不能重复声明变量,
const 常量声明,一旦声明,常量的值不能改
const定义一个对象,可以修改里面的属性,因为对象是引用类型 改变的是引用地址
解构赋值
扩展运算符 ...
模板字符串
箭头函数 简洁,同时函数体内this对象,就是定义时所在的对象,而不是使用时所在的对象。This不会改变了 一定是匿名函数 不要在最外层定义箭头函数
Symbol类型 独一无二的值
Generators生成器函数 * 函数体内部使用yield表达式将进程分片暂停 next获得结果
class extends 类和继承
promise 异步编程的一种解决方法 三个状态pending-resolve-reject
状态从pending-resolve 成功返回一个promise对象,通过then传递
状态从pending-reject 失败走reject
promise.all 并发 promise.race速发
不说set 数据结构Set new set()存储数据 set.size得到存储的数据长度
has()判断某个值是否存在set中 foreach遍历set
不说map : new map map.set map.get map.delete
都是用来存储数据用的,但是存储的数据格式不同
set 直接存储 任意类型数据
map 存储数据的时候,必须以key,value的形式,
set 使用forEach 遍历的时候,key和value值是一样的
而map 遍历的时候,key就是存进去的对象的key,value就是存在的值
for循环这种写法比较麻烦,因此数组提供内置的forEach方法。
forEach没有返回值,无法中途跳出forEach循环,break命令或return命令都不能奏效。
for...in循环主要是为遍历对象而设计的,不适用于遍历数组**
for...of循环相比上面几种做法,有一些显著的优点。
有着同for...in一样的简洁语法,但是没有for...in那些缺点。
不同于forEach方法,它可以与break、continue和return配合使用。
提供了遍历所有数据结构的统一操作接口。
同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
当指定的事情完成时,Event Table会将这个函数移入Event Queue。
主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
上述过程会不断重复,也就是常说的Event Loop(事件循环)。
先执行同步代码 微任务放在微任务队列中 宏任务放在宏任务队列中
宏任务和微任务是任务队列是两个任务队列中
同步执行完,执行微任务,再执行宏任务
宏任务 setTimout setInterval
微任务 promise process.nextTick
回调函数 异步回调 函数作为参数传递给另外有一个函数 将函数内部的值通过回调函数传出来 解决同步的一种方式 多层嵌套 造成回调地狱
事件监听
发布/订阅 系统中有一个信号中心,当某个任务执行完成后向信号中心发布一个消息,其他任务就可以通过这个信号中心去订阅这个信号,从而知道什么时候直接可以开始执行 发布订阅模式和事件监听类似,可以查看消息中心有多少信号,每个信号有多少订阅者
promise
generator(ES6) 异步任务 通过yield关键字可以让任务在需要的地方暂停,每一步的值可以通过next获取
async/await(ES7) await得到的就是async异步返回值,底层原理还是promise中的resolve方法
首先总的来说,三者都是用于持久化数据存储的手段,都是存储在浏览器端,且同源.
localStorage和sessionStorage都是Web存储,大小5M左右,完全存储在客户端,它们是因为本地存储数据而存在.
cookies也是存储在浏览器端的,大小不超过4k,由服务器端存储在客户端。
localStorage属于永久性存储,数据存储量大,,而sessionStorage属于当会话结束的时候,存储的值会被清空,而cookie是通过设置过期时间expires来存储的。
正则 type number
https://zhuanlan.zhihu.com/p/133658121