工作中JS补充

1.js事件轮询机制

事件轮询

JS是单线程的所以执行任务需要排队,但这样会影响页面加载,
所以JS选择使用异步。添加了一个消息队列,将一些需要等待的事件放到消息队列里,先执行那些可以直接进行的操作,之后不停的去去问消息队列,有没有任务可以执行呀,有没有任务可以执行呀。如果有的话,就把需要执行的操作取出来放到主线程里执行,如果没有的话则继续之前的操作,这也就是js的事件轮询

console.log('start')

setTimeout(function() {
    console.log('setTimeout')
}, 0)

console.log('end')

输出结果为:“start” , “end” , “setTimeout”

执行过程

1.所有任务都在主线程上执行,形成一个执行栈。
2.所有任务都在主线程上执行,形成一个执行栈。
3.如果执行栈中的所有同步任务执行完毕,js就会读取消息队列中的异步任务,如果有可以执行的任务就把他放入执行栈中并开始执行。
4.主线程不断重复上面的第三步,这样的一个循环称为事件循环。

宏任务:

  • setTimeout,setInterval,setImmediate,
  • I/O
  • UI rendering

微任务:

  • promise
  • process.nextTick
  • MutationObserver(html5新特性)

实例:

console.log('script start')

setTimeout(function(){
    console.log('setTimeOut')
}, 0)

new Promise(function(resolve){
    console.log('promise1') 
    resolve()
}).then(function(){
    console.log('promise2') 
})

console.log('script end')

输出结果:script start’, ‘promise1’, ‘script end’ , ‘promise2’ ,‘setTimeOut’

注:(promise里的是同步代码,.then里的才是异步的)

执行过程

(些文章,也把同步任务视为宏任务,这时的执行就是宏任务 => 微任务 => 宏任务 => 微任务……的循环(其实对执行顺序而言并没有差异))
1、所有任务都在主线程上执行,形成一个执行栈。
2、主线程发现有异步任务,如果是微任务就把他放到微任务的消息队列里,如果是宏任务就把他放到宏任务的消息队列里。
3、执行栈所有同步任务执行完毕。
4、执行微任务队列,之后再执行宏任务队列。
5、轮询第4步。

2.vue中this.nextTick

将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法Vue.nextTick一样,不同的是回调的 this 自动绑定到调用它的实例上.
(简单的说就是js是单线程的 他的执行有执行的队列,有些时候数据更新后 并不一定会发生dom更新 这时候你对更新数据的dom进行操作是不会有用的 因为他还未更新当你更新完数据立刻使this.nextTick就会将该操作延迟 等到发生更改的dom更新完成在执行。此时才有效。)

Object.keys() 方法

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。

// simple array
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']

// array like object with random key ordering
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']

// getFoo is a property which isn't enumerable
var myObj = Object.create({}, {
  getFoo: {
    value: function () { return this.foo; }
  }
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']

3.toFixed() 方法

toFixed() 方法可把 Number 四舍五入为指定小数位数的数字

NumberObject.toFixed(num)

//例如

var percent = 74.444555
console.log(percent.toFiexd(2))
输出为:74.44

num:规定小数的位数,是 0 ~ 20 之间的值,包括 0 和 20,有些实现可以支持更大的数值范围。如果省略了该参数,将用 0 代替。

17种正则表达式

7.17种正则表达式 

复制代码代码如下:

"^//d+$"//非负整数(正整数 + 0) 
"^[0-9]*[1-9][0-9]*$"//正整数 
"^((-//d+)|(0+))$"//非正整数(负整数 + 0) 
"^-[0-9]*[1-9][0-9]*$"//负整数 
"^-?//d+$"//整数 
"^//d+(//.//d+)?$"//非负浮点数(正浮点数 + 0) 
"^(([0-9]+//.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*//.[0-9]+)|([0-9]*[1-9][0-9]*))$"//正浮点数 
"^((-//d+(//.//d+)?)|(0+(//.0+)?))$"//非正浮点数(负浮点数 + 0) 
"^(-(([0-9]+//.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*//.[0-9]+)|([0-9]*[1-9][0-9]*)))$"//负浮点数 
"^(-?//d+)(//.//d+)?$"//浮点数 
"^[A-Za-z]+$"//由26个英文字母组成的字符串 
"^[A-Z]+$"//由26个英文字母的大写组成的字符串 
"^[a-z]+$"//由26个英文字母的小写组成的字符串 
"^[A-Za-z0-9]+$"//由数字和26个英文字母组成的字符串 
"^//w+$"//由数字、26个英文字母或者下划线组成的字符串 
"^[//w-]+(//.[//w-]+)*@[//w-]+(//.[//w-]+)+$"//email地址 
"^[a-zA-z]+://(//w+(-//w+)*)(//.(//w+(-//w+)*))*(//?//S*)?$"//url 

正则表达式详情
// 1.利用RegExp构建正则表达式
//  var regexp = new Regexp (/表达式/)

var regexp = new Regexp (/123/)
//2.利用字面量创建
 var reg = /123/;
//  3.检测正则表达式规范test
  regExpObj.test(str)

  // 1.regExpObj正则表达式
  // 2.str 我们要测试的文本
  // 3. 就是检测str文本是否符合我们写的正则表达式规范
  reg.test(123) // true
  reg.test(abc) // false


  //5.正则表达式里得特殊字符
    // 5.1边界符号 ^, $
      // ^表示匹配行首得文本以谁开始
      // $表示匹配行尾得文本以谁结束

      //  若^ 和 $ 同时出现哎i你则表示 必须 必须是精确匹配 重复出现也不可以

      var rg = /abc/  //正则表达式不需要加引号

      // 只要包含abc这个字符串返回的都是true
      rg.test('abc') //true
      rg.test('abcd')  //true
      rg.test('aabcd') // true  

      console.log('-----------------')

      var reg1 = /^abc/ //表示 必须以a开头
      reg1.test('abc') //true
      reg1.test('abcd')  //true
      reg1.test('aabcd') // true 
      
      var var reg2 = /^abc$/ //表示 必须是abc字符串才符合规定
      reg2.test('abc') //true
      reg2.test('abcd')  //false
      reg2.test('aabcd') // false 
      reg2.test('abcabc') // false 

      //  5.2 [] 表示有一系列的字符可以供选择,只要匹配其中的一个就可以了
      var reg3 = /[abc]/
        reg3.test('aqqq') // true
        reg3.test('baby') // true
        reg3.test('ecop') // true
        reg3.test('red') // false

      var reg4 = /^[abc]$/ // 表示三选一, 只有a, 或者b 或者c z这三个字母才能返回true
      reg4.test('a') //ture
      reg4.test('b') //ture
      reg4.test('c') //ture
      reg4.test('aa') //false
      reg4.test('abc') //false
      reg4.test('dcb') //false
    // 5.3 [-] 表示在这个范围内有任何一个都可以
    var reg5 = /^[a-z]$/ // a-z 26个字母范围内任何一个字符都可以
    reg5.test('a') //ture
    reg5.test('b') //ture
    reg5.test('c') //ture
    reg5.test('A') //false
    reg5.test('1') //false
    // 字符组合
    var reg6 = /^[a-zA-Z0-9_-]$/; //26个英文字母(大写和小写都可以)或者事 _ 或者是- 任何一个字母 返回 true 只能多选一 

    reg6.test('a') //ture
    reg6.test('2') //ture
    reg6.test('_') //ture
    reg6.test('A') //ture
    reg6.test('!') //false
    reg6.test('aa') //false


   var reg7 = /^[^a-zA-Z0-9_-]$/; //如果中括号[]里面有^表示取反的的意思,不能和边界符^混淆,和上边正好是相反 有任何一个都是false
   reg7.test('a') //false
   reg7.test('2') //false
   reg7.test('_') //false
   reg7.test('A') //false
   reg7.test('!') //true


  //  5.4 量词符: 用来设定某个模式出现得次数
  // 简单理解: 或是让下面这个a 这个字符重复出现多少次
  // 量词符 * :相当于 >=0 可以出现0次或者很多次
   var reg8 = /^a*$/
   reg8.test('a') //true
   reg8.test('') //ture
 // 量词符 + :相当于 >=0 可以出现1次或者很多次
   var reg9 = /^a+$/
   reg9.test('a') //true
   reg9.test('') //fasle

  // 量词符 ? :相当于 出现 1次或者 0次
  var reg10 = /^a?$/
   reg10.test('a') //true
   reg10.test('') //ture
   reg10.test('aaaaa') //false

  //  量词符 {3}: 重复出现3次
    var reg11 = /^a{3}$/
    reg10.test('aaaaa') //false
    reg10.test('aaa') //ture


  //  量词符 {3,}: 重复出现大于等于3次
  var reg11 = /^a{3,}$/
  reg10.test('aaaaa') //true

  //  量词符 {3,16}: 重复出现大于等于3次小于等于16次
  var reg11 = /^a{3,16}$/


  // 6.用户名限制
  // 只能输入英文字母数字下划线 短横线 , 量词中间不要有空格{6,16}
    var reg12 = /^[a-zA-Z0-9_-]{6,16}$/

    reg12.test('a') //false
    reg12.test('0') //false
    reg12.test('andy_001') //true
    reg12.test('Andy-99') //true
    reg12.test('andy!19') // false

// 7.[] : 字符集 匹配方括号中的任意字符
// {} : 量词符里面表示得重复次数
var reg13 = /^abc{3}$/  //表示 只让c重复三次
reg13.test('abc') //false
reg132.test('abcabcabc') //false
reg13.test('abccc') // true
// (): 表示优先级

var reg13 = /^(abc){3}$/ 
reg13.test('abcabcabc') //true

// 8. 座机号码验证 : 两种模式 010-12345678  0426-9999328
//  正则里面得 或者 符号 |
var reg14 = /^\d{3}-\d{8}| \d{4}-\d{7}$/
// 或者
var reg15 = /^\d{3,4}-\d{7,8}$/

// 9.正则表达式参数 
// g:全局匹配
// i:忽略大小写
// gi:全局匹配+忽略大小写
/表达式/g



    

构造函数 原型对象(prototype) 和 对象的原型( __ proto __)

每一个对象都有 __ proto __ 属性 它指向的是构造函数中的原型对象 prototype 所以 构造函数的原型对象中的方法 实例对象也能使用

  1. { } -》propto -》 构造函数的prototype (prototype 是个对象 内部装着 可以共同使用的 方法)

对象的原型 等价于 构造函数的原型对象
在这里插入图片描述
在这里插入图片描述

JSON.parse 与 JSON.stringfy得用处

1。可以实现对象深拷贝

//深拷贝
function deepClone(data) {
    let _data = JSON.stringify(data),
        dataClone = JSON.parse(_data);
    return dataClone;
};
//测试
let arr = [1,2,3],
    _arr = deepClone(arr);
arr[0] = 2;
console.log(arr,_arr)//[2,2,3]  [1,2,3]

2.判断数组是否包含某对象,或者判断对象是否相等

//判断数组是否包含某对象
let data = [
    {name:'echo'},
    {name:'听风是风'},
    {name:'天子笑'},
    ],
    val = {name:'天子笑'};
JSON.stringify(data).indexOf(JSON.stringify(val)) !== -1;//true

//判断两数组/对象是否相等
let a = [1,2,3],
    b = [1,2,3];
JSON.stringify(a) === JSON.stringify(b);//true

3.让localStorage/sessionStorage可以存储对象。

//存
function setLocalStorage(key,val){
    window.localStorage.setItem(key,JSON.stringify(val));
};
//取
function getLocalStorage(key){
    let val = JSON.parse(window.localStorage.getItem(key));
    return val;
};
//测试
setLocalStorage('demo',[1,2,3]);
let  a = getLocalStorage('demo');//[1,2,3]

Object.assign() 是浅拷贝还是深拷贝?

1.如果对象的属性值为简单类型(如string, number),通过Object.assign({},srcObj);得到的新对象为深拷贝;如果属性值为对象或其它引用类型,那对于这个对象而言其实是浅拷贝的。

实现深拷贝的几种方法

1.JSON.stringify 和 JSON.parse如上
2.Object.assign()深拷贝简单数据类型(number, string)
3.lodash.cloneDeep()实现深拷贝

let _ = require('lodash');
let obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
let obj2 = _.cloneDeep(obj1);

4.使用递归的方式实现深拷贝

function isDeepClone (source){
	let target 
	if(source.typeof === 'object'){ //如果是对象的话
		 target = Array.isArray(source)? []: {}  //因为数组也是对象 所以 判断是对象后还要继续判断  是不是数组
		 for(let key in source){
		 	if(source.hasOwnProperty(key){ //用来检测 source 是否存在 key 这个属性 返回值是 布尔值 如果有key  则继续向下判断
				if(source[key].typeof === 'object'){  判断内部是否还有 引用数据类型 有的话 继续重复进行 深拷贝的方法
					isDeepClone(source[key])
					}else{
					target[key] = source[key]
				}
		 	}
		 }
	} else{
		target = source
	}
	return target 
}

箭头函数没有 this 指针 如果调用箭头函数 出现this 则该this 为该箭头函数定义位置上下文的this

async await

async函数会返回一个promise,并且Promise对象的状态值是resolved(成功的)
1.如果你没有在async函数中写return,那么Promise对象resolve的值就是是undefined

function log(time){
    setTimeout(function(){
        console.log(time);
        return 1;
    },time)
}
async function fun(){
    let a = await log(1000);
    let b = await log(3000);
    let c = log(2000);
    console.log(a);
    console.log(1)
}
fun(); 
// 立即输出 undefined 1   
// 1秒后输出 1000
// 2秒后输出 2000
// 3秒后输出 3000

会立即输出得原因就是 log()函数没有return
2.如果你写了return,那么return的值就会作为你成功的时候传入的值

// 使用async/await获取成功的结果

// 定义一个异步函数,3秒后才能获取到值(类似操作数据库)
function getSomeThing(){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('获取成功')
        },3000)
    })
}

async function test(){
    let a = await getSomeThing();
    console.log(a)
}
test(); // 3秒后输出:获取成功

3.如果asycn里的代码都是同步的,那么这个函数被调用就会同步执行

async function fn(){
  console.log('a')
}
fn()
console.log('b')
//a
//b

地址:async await 详细讲解

promise.all()

可以并发执行多条异步请求,节约时间
promise.all()该方法用于将多个Promise实例,包装成一个新的Promise实例。

var p = Promise.all([p1,p2,p3]);
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

判断数据类型

typeof只能判断基本数据类型 ’string’,number, boolean, object,undefined,对于复杂的数据类型都只返回 object
此时我们可以使用Object.prototype.toString.call() 方法判断具体得数据类型 返回值是一个数组形式

Object.prototype.toString()本身是允许被修改的,而我们目前所讨论的关于Object.prototype.toString()这个方法的应用都是假设toString()方法未被修改为前提的。

1.基本数据类型
     Object.prototype.toString.call(null);// ”[object Null]”
	 Object.prototype.toString.call(undefined);// ”[object Undefined]”
	 Object.prototype.toString.call(“abc”);// ”[object String]”
	 Object.prototype.toString.call(123);// ”[object Number]”
	 Object.prototype.toString.call(true);// ”[object Boolean]”
2.原生引用类型
2.1 函数数据类型
function fn(){
console.log('nihao')
}

Object.prototype.toString.call(fn) //[object, 'Function']
2.2 数组数据类型
var arr = [1,2,3];
Object.prototype.toString.call(arr);//”[object Array]”
2.3 日期类型
var date = new Date();
Object.prototype.toString.call(date);//”[object Date]”
2.4正则表达式
var reg = /[hbc]at/gi;
Object.prototype.toString.call(arr);//”[object Array]”
2.5 自定义类型
function Person(name, age) {
    this.name = name;
    this.age = age;
}
var person = new Person("Rose", 18);
Object.prototype.toString.call(arr); //”[object Object]”
3. 判断原生JSON 对象
var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);
console.log(isNativeJSON);//输出结果为”[object JSON]”说明JSON是原生的,否则不是;

web会话跟踪的几种方式(cookie)

1.token
2.cookie
3.session
4.URL重写
5.隐藏表单项

1.token 无状态的,是多用户下处理认证的最佳方式

当第一次客户端向服务器发起请求时,服务器端生成一串字符串,并将这个字符串作为一个令牌发放给客户端,当客户端再次发起请求时只需带上token 即可不需要再次带上用户名和密码

最简单的 token 组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,使用 hash/encrypt 压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。

2.cookie

是服务器生成的,以键值对的形式 存放在某个目录下的文件中,发放给浏览器,当浏览器再次向服务器发起请求时被携带并发送给服务器。由于cookie是存在客户端的 所以为防止恶意使用,每个域的cookie 数量有限

缺点:
1.每个特定域名下cookie数量有限
2.大小有限制只能是4kB
3.每次http都需要发送到服务器端,影响获取资源的效率

session :有状态的

存储于服务器或者硬盘中,可以理解为一个状态列表,拥有一个唯一识别符号 sessionID ,客户端通常存放于 cookie 中。服务器收到 cookie 后解析出 sessionID ,再去session列表中查找,找到相应的session,如果cookie被禁 也可以放在url中,
用户认证流程
1.第一次客户端请求服务器,服务器根据用户信息创建session并返回对应的sessionID给浏览器
2.浏览器接收sessionID并把它存到cookie中,并同时记录session属于哪个域名
3.客户端再次向服务器端发起请求时 ,请求会自动判断此域名下是否有cookie信息,如果存在会把cookie信息发给服务端,然后服务端会在Cookie中获取sessionID,在根据sessionID在状态列表中找到对应的session信息,没找到就说明该用户没有登录或者登录失效,找到了则证明当前用户已登录可执行后面的操作。
4.如果web服务器做了负载均衡,那么下一个操作请求到了另外的一个域名 则session 会丢失

URL重写

在url的尾部添加一些额外的数据,这些数据标识当前的会话,服务器将这些数据与它存储的相关数据关联起来。即使在浏览器不支持Cookie的情况下,这种方案也能正常工作

1、必须对所有指向本 Web 站点的 URL 进行编码。
2、所有页面都必须动态生成。
3、不能使用预先记录下来的URL进行访问,或者从其他的网站链接进行访问。
4、用户 ID 及登录密码等重要信息可能以参数的形式暴露在URL上,造成安全隐患。
5、大部分的 URL 的长度有限制,不能传送大量的数据。

session 与cookie的区别

存储位置: session存储在服务器端,cookie 存储在客户端
安全性: session 比cookie更安全,别人可以分析存放在本地的cookie进行cookie欺骗
存储大小:cookie的数据不能超过4kB,浏览器对同一个站点有cookie数量限制,session 中存储的数据远高于cookie
存储类型不同:cookie支持字符串类型,想要设置其他类型 需要进行转换,session 可以存储任意类型
session会在一定时间内保存在服务器上当访问增多时 会比较占用服务器的性能 ,所以可以把登陆的信息存放在session上,其他信息如果需要保存可以存放在cookie里

节流和防抖得区别

防抖:当事件被触发后 延迟n秒后在执行 如果在这n秒中又被触发,则重新计时,等同于 游戏中的回城

1.使用场景–输入框是按键触发请求时

用户连续输入一串字符时,可以通过防抖策略,只有在输入完后, 在执行请求 ,减少请求次数,节约请求资源

var time = null   
  //定义一个要发生的数据
  getdata(data){
  //data是发送的数据
    //发送请求
}
//防抖的timer

//定义防抖的函数,调用这个函数后,会设置一个定时器
//request是发送请求的函数。
function fn(keword,request){
//keword是你要传递的参数
//request是你发送请求的函数名
//开启定时器后,会返回一个定时器的id,可以接受这个id,清除的时候也是根据这个id来清除的。
   time = setTimeout({
   //发送请求
    request(keword)
},500)
}

input.keyup = function(){
     clearTimeout(timer)
     fn(keywords,getdata)
     //keywords是用户输入的值
}
//给输入框绑定事件
//按键抬起后触发, 先清除定时器,

节流:就是 减少一段时间内事件的触发频率,当按键触发后 一段时间内 输入或触发都不会在执行, 即只触发第一次得事件,只有等这个事件执行完后才能执行下一次事件

1.使用场景—鼠标连续点击触发事件
2.懒加载时要监听计算滚动条得位置
//vue中的场景,time是data里的变量
cleartime(){
      //第一步是清除定时器,
       clearTimeout(this.time)
      //第二部要把存定时器的值清空,不然还存着定时器的那个id
      this.time = null
    },
     //请求函数
    getdata(){
     //如果定时器存在,则退出函数
    if(this.time){
      return
    }
    //不存在就创建一个定时器
      this.time = setTimeout(()=>{
       //用箭头函数this是vue
       //不用箭头函数,this是window
       //执行你的逻辑。

       //之后执行清空定时器函数在上面
        this.cleartime()
      },3000)
   
        }

节流和防抖得区别

防抖相当于游戏中得回城 点击后延迟一段事件在触发请求 如果多次触发取最后一次触发开始延迟一定时间后在发起请求
节流相当于游戏中的释放技能,触发后立刻发起请求,然后间隔一段时间内不在发起 就算点击也不再发起请求,单位i时间过去后在次点击才触发第二次请求

本地存储 localStorage 与 sessionStorage

区别:

  1. 生命周期不同
    localstorage:生命周期为永久生效,可以多个窗口共享
    sessionstorage: 生命周期为关闭浏览器窗口,在同一窗口下数据可以共享,
    2.存储容量上:
    localStorage约为20M
    sessionStorage: 约为5M
    3.在数据共享上
    localStorage:同一个浏览器多个窗口(页面)数据可共享
    sessionStorage:同一浏览器 同一窗口(页面)数据可共享,窗口关闭 sessionStorage 生命周期结束
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值