javaScript4

sh f1.js标准内置对象

1)Proxy

详细说明 https://www.jianshu.com/p/81eb68ae5eb1

Proxy 对象用于创建一个对象的代理(在目标对象的外层搭建了一层拦截),从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

const p = new Proxy(target, handler)
target
使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。

2.面向对象替代switch、多分支条件判断

//点击底部按钮组
handelClick(clickType) {
  if ( this .tableData.multipleSelection.length < 1) {
    return this .$message({
      type:  'warning' ,
      message:  '请先勾选需要处理的数据' ,
      showClose:  true ,
    })
  }
  const types = {
    relation:  this .relationBatch,
    move:  this .moveBatch,
    copy:  this .copyBatch,
    unbunding:  this .unbundingBatch,
  }
  return types[clickType]()
},

3.去掉string中的html标签

str..replace(/<[^>]+>/g,  '' )

  

4.优雅删除对象无用key

1.封装函数方法

要删除很多key的时候可用

//要删除的key
const delKeys = ['key1','key2','key3']
delKeysFn(obj)

//封装函数
delKeysFn(obj){
  delKeys.formEach((item)=>{
    delete obj[item]
  })
}

2. Lodash 的 omit 方法

移除不需要的属性

安装lodash 
const object = { 'a': 1, 'b': '2', 'c': 3 };
const result = _.omit(object, ['a', 'c']);

3.  pick 方法

只留下需要的属性

const object = { 'a': 1, 'b': '2', 'c': 3 };
 
const result = _.pick(object, ['a', 'c']);

4.自己实现一个 omit

// 中规中矩式
const omit = (obj, uselessKeys) =>
   Object.keys(obj).reduce((acc, key) =>
      return uselessKeys.includes(key) ?
        acc : 
        {...acc, [key]: acc[key]}
   }, {});


// 投机取巧式
const omit = (obj, uselessKeys) =>
  uselessKeys.reduce((acc, key) => {
    return {...acc, [key]: undefined}
  }, obj)


// 粗暴式
const omit = (obj, uselessKeys) => {
  uselessKeys.forEach(key => {
    delete obj[key]
  })
  return obj
}

5.reduce的n种应用

使用语法:

array.reduce(function(prev, current, currentIndex, arr), initialValue)

参数说明:

prev:函数传进来的初始值或上一次回调的返回值

current:数组中当前处理的元素值

currentIndex:当前元素索引

arr:当前元素所属的数组本身

initialValue:传给函数的初始值

1.累积和累和

let arr = [1, 2, 3, 4, 5]
arr.reduce((prev,cur)=>prev+cur)  //15
arr.reduce((prev,cur)=>prev*cur)  //120

2.求最大和最小值

let arr = [1,2,3,4,5]
arr.reduce((prev,cur)=>Math.max(prev,cur)) //5
arr.reduce((prev,cur)=>Math.min(prev,cur)) //1

3.数组去重,数组对象去重

let arr = [1,2,3,1,1,2,3,3,4,3,5]
let res = arr.reduce((prev,cur)=>{
	!prev.includes(cur)&&prev.push(cur)
  return prev
},[])

//数组对象去重
var arr = [{a:1,b:2},{a:1,b:4},{a:3,b:5}]
const keys = []
const newArr = arr.reduce((pre,next)=>{
  if(!keys.includes(next.a)){
    keys.push(next.a)
    pre.push(next)
  }
  return pre
},[])

4.实现map函数

map函数接收一个函数作为参数,作为参数的函数接收三个参数值,分别是遍历数组的每一项元素,元素的索引和数组本身,这三个参数刚好和reduce函数接收的第一个函数参数的第2,3,4个参数是对应的。

实现思路是,将每次遍历的元素,作为传入函数的参数,并将函数执行的结果放到新的数组中。

let arr = [1,2,3]
Array.prototype._map = function(cb){
	if(typeof cd !== 'function ') return throw new Error(cb + 'is not function')
  let arr = this; //this--调用_map方法的当前数组对象
  return arr.reduce((prev,item,index,array)=>{
  	prev.push(cb(item,index,array))
    return prev
  },[])
}
let res = arr._map(val=>val*2)  //[2.4.6]

5.实现filter函数

Array.prototype._filter = function (cb){
	if(typeof cb === 'function'){
  	let arr = this
    return arr.reduce((prev,item,index,array)=>{
    	cb(item,index,array)?prev.push(item):null
      return prev
    },[])
  }else{
  	throw new Error(cb+'is not function')
  }
}

6.实现compose

compose是函数编程的核心,简单说就是将若干个函数合成一个函数来执行,并且每个函数的执行结果都作为下一个函数的参数(从右到左执行)。

假设目前有两个函数:
function toUpperCase(str){
	return str.toUpperCase()
}
function add(str){
	return str += '!'
}

//一般使用
let str = 'hello world'
let res = toUpperCase(str)
res = add(res) 

//使用compose后,执行fn相当于,依次执行了toUpperCase和add
const fn = compose(add,toUpperCase)
fn(str) 

//使用reduce实现compose
function compose(){
  //将arguments转化为数组
	let args = [].slice.call(arguments)
  return function(x){
  	//因为compose()接收的函数参数,是从右往左走顺次执行
    //所以这里使用reduceRight,用法和reduce一致,只不过是从右到左遍历数组
    return args.reduceRight((prev,cur)=>{
    	return cur(prev)
    },x)
  }
}

//[].slice.call() 原理分析
[].slice.call() 常用来将类数组转化为真正的数组
call 调用函数并改变指向
slice()默认返回所有下标的元素并返回新数组
var array = [].slice.call(arrayLike);
array;  // ['a', 'b', 'c']

7.数组扁平化

let arr = [1, 2, '3js', [4, 5, [6], [7, 8, [9, 10, 11], null, 'abc'], {age: 12}, [13, 14]], '[]'];
function flatten(arr) {
  if (Array.isArray(arr)) {
    return arr.reduce((prev, cur) => {
      // 如果遍历的当前项是数组,再迭代展平
      return Array.isArray(cur) ? prev.concat(flatten(cur)) : prev.concat(cur)
    }, [])
  } else {
    throw new Error(arr + ' is not array')
  }
}

8.求对象数组中指定属性的和

const arr = [{x:1},{x:2},{x:3}]
const arr2 = arr.reduce((prev,cur)=>prev+cur.x)
arr2 // 6

9.将数组中每个元素出现的次数统计,以对象形式输出

const arr = ['A','B','A']
const result = arr.reduce((prev,cur)=>{
  if(cur in prev){
  	prev[cur]++
  }else{
  	prev[cur]=1
  }
	return prev
},{})

result // {A:2,B:1}

10.结合展开运算符使用

const arr = [
  {
  	name:'a',
    fruits:[1,2,3]
  },
  {
  	name:'b',
    fruits:[4,5,6]
  }
]

const result = arr.reduce((prev,cur)=>[...prev,...cur.fruits],[7,8])
result //[1,2,3,4,5,6,7,8]

更多应用:https://blog.csdn.net/ZhaoD6688/article/details/107231249/?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-5&spm=1001.2101.3001.4242

12.获取状态码400的返回值

.catch(error=>{
  console.log(error.response.data); //data是错误信息的全部值
  console.log(error.response.status);
  console.log(error.response.headers); 
  console.log('Error', error.message);
  console.log(error.config);
})

13.对象转数组

const obj = { foo: 'bar', baz: 42 }; console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]

14.对象与mp间的转化

从对象转为 Map :new Map(Object.entries(obj))
从 Map 转为对象:Object.fromEntries(map.entries())

15.清除所有定时器

let end = setInterval(function () { }, 10000);
for (let i = 1; i <= end; i++) {
    clearInterval(i);
}

16.判断对象是否包含某个key

!("key" in obj) //结果为false,表示不包含;否则表示包含
obj.hasOwnProperty("key") //obj表示对象,结果为false表示不包含;否则表示包含

17.身份证信息脱敏

function noPassByIdcard(str) {
  if (null != str && str != undefined) {
    var pat = /^(.{4})(?:\w+)(.{3})$/
    return str.replace(pat, '$1**********$2')
  } else {
    return ''
  }
}

18.vue的防抖 立即执行

  imDebounce(fn, time) {
      this.timer && clearTimeout(this.timer)
      if (this.flag) {
        return fn(), (this.flag = false)
      }
      this.timer = setTimeout(() => {
        this.flag = true
      }, time)
    },

19.多个promise 管理

  async beforeRouteEnter(to, from, next) {
    ;[pre.dept, pre.noType] = await Promise.all([
      deptChooseList({ tree: false }),
      noTypes(),
    ])
    next()
  },

20.判断对象中是否拥有该key

  //hasOwnProperty表示是否有自己的属性。这个方法会查找一个对象是否有某个属性,但是不会去查找它的原型链。

21.脚本命令决定启动模式 获取命令行参数

需求场景:本地开发、测试环境、生产环境可能需要不同的服务地址。测试环境和生产环境打包地址有所区分,每次都需要修改地址后再进行打包稍微有些麻烦。通过npm run build:xxx 以命令行添加参数的方式来决定打包地址刚好可以解决此需求。

实现前先了解几个知识点:

1)process :process对象是一个全局变量,它提供当前 Node.js 进程的有关信息,以及控制当前 Node.js 进程。 因为是全局变量,所以无需使用 require()。

2)process.argv 属性返回一个数组,这个数组包含了启动node.js进程时的命令行参数。

实现分为以下几个步骤

// 1.确定参数名字,package.json中更改启动及打包命令
"dev": "vue-cli-service serve --env dev",
"build:jwtest": "vue-cli-service build --env jwtest",
"build:jwpro": "vue-cli-service build --env jwpro",
  
  
//2.vue.config.js  获取命令行参数,取最后一个。
const env_mode = process.argv.pop() //运行模式
console.log(env_mode, 'mode')


//3.vue.config.js module.exports 中添加配置
configureWebpack: {
  // provide the app's title in webpack's name field, so that
  // it can be accessed in index.html to inject the correct title.
  name: name,
    plugins: [
      new webpack.DefinePlugin({ //定义全局变量
        'process.env': {
          MODE: JSON.stringify(env_mode), //之后任意文件读取process.env.MODE
        },
      }),
    ],
},


//4.创建配置文件xxx.js
const wss_urls = {
  dev: 'wss://xxx',
  jwtest: 'wss://xxx',
  jwpro: 'wss://xxx',
}
const access_urls = {
  dev: 'https://xxx',
  jwtest: 'https://xxx',
  jwpro: 'https://xxx',
}
export const wss_url = wss_urls[process.env.MODE]
export const access_url = access_urls[process.env.MODE]


//5.使用 
import { access_url } from '@/utils/http-url'

22.created与activated的区别

使用<keep-alive>会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在activated阶段获取数据,承担原来created钩子中获取数据的任务。

被包含在 <keep-alive> 中创建的组件,会多出两个生命周期的钩子: activateddeactivated

activated:在组件被激活时调用,在组件第一次渲染时也会被调用,之后每次keep-alive激活时被调用。

deactivated:在组件被停用时调用。

注意:只有组件被 keep-alive 包裹时,这两个生命周期才会被调用,如果作为正常组件使用,是不会被调用,以及在 2.1.0 版本之后,使用 exclude 排除之后,就算被包裹在 keep-alive 中,这两个钩子依然不会被调用!另外在服务端渲染时此钩子也不会被调用的。

什么时候获取数据?

当引入keep-alive 的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated。

我们知道 keep-alive 之后页面模板第一次初始化解析变成HTML片段后,再次进入就不在重新解析而是读取内存中的数据,即,只有当数据变化时,才使用VirtualDOM进行diff更新。有需要的话,页面进入的数据获取应该在activated中也放一份。数据下载完毕手动操作DOM的部分也应该在activated中执行才会生效。

所以,有需要的话,应该activated中留一份数据获取的代码,或者不要created部分,直接将created中的代码转移到activated中。

23.foreach不能保证内部异步按照循环顺序执行,需要更换为for of

24.charAt 截取字符串某一项 传入索引

25..匹配任意字符 str.replace(/./g,1)

replaceAll的兼容性太差,可以用replace和正则相结合来代替replaceAll的使用。(小程序安卓不支持)

//全部替换为1

26.获取页面所有标签数量(全部元素)

方法一:

http://t.zoukankan.com/zjmx-p-11866167.html

[...document.querySelectorAll('*')].map(v=>v.tagName).reduce((res,a)=>{res[a]=(res[a] || 0)+1 ;  return res;},{})

方法二:

function fold(node){
  var map = new Map();
  map.set(node.tagName,1);
  [].reduce.call(node.children,(acc,child)=>{
    deal(acc,fold(child));
    return acc
  },map)
  return map
}

function deal(srcMap,tarMap){
  tarMap.forEach((value,tagName)=>{
    var newV = value + ~~srcMap.get(tagName);
    srcMap.set(tagName,newV);
  })
}  

27.vue生成带logo的二维码

<qrcode-vue
id="qrcodeBox"
:size="qrcodeVue.size"
:value="item.idCard"
:logo="qrcodeVue.logo"
:bgColor="qrcodeVue.bgColor"
:fgColor="qrcodeVue.fgColor"
></qrcode-vue>

import qrcodeVue from "qrcode-vue";

qrcodeVue: {
  size: 50,
    bgColor: "#fff",
      fgColor: "#000",
        // value: "https://www.baidu.com/", //二维码地址
        logo: require("@/static/red-cross.png"), //logo图片
},
  

  //生成二维码
  // getQRcode() {
  //   this.qrcodeVue.value = "www.baidu.com"; // 二维码内容
  // },

28.时分秒补0 补零

str.padStart(2, "0");
ES2017 引入了字符串补全长度的功能。
如果某个字符串不够指定长度,会在头部或尾部补全。
padStart()用于头部补全,padEnd()用于尾部补全。

29.创建window全局变量

public文件创建config.js
html文件引入  <script src="./config.js"></script>

window.config = {
  acticityBaseUrl: 'https://miapp.chuntaoyisheng.com/xz/#/',
  templates: {
    'template_01.jpg': 'pages/recommend/detailTemplateBase',
    'template_02.jpg': 'pages/recommend/detailTemplateOne',
    'template_03.jpg': 'pages/recommend/detailTemplateTwo',
    'template_04.jpg': 'pages/recommend/detailTemplateThree',
    'template_05.jpg': 'pages/recommend/detailTemplateBase',
  },
}

//使用方法
子页面:window.config.acticityBaseUrl

30.闭包缓存,传入同样参数时取缓存。

const getRes = (function () {
  const obj = {}
  return function () {
    const params = [...arguments]
    const key = JSON.stringify(params)
    if (key in obj) {
      console.log('缓存取值')
      return obj[key]
    }
    const result = eval(params.join('+'))
    obj[key] = result
    console.log('计算取值')
    return result
  }
})()

31.class缓存,传入同样参数时取缓存。

class getRes {
  map
  constructor() {
    this.map = new Map()
  }
  getResult() {
    const params = [...arguments]
    const key = JSON.stringify(params)
    if (this.map.has(key)) {
      console.log('缓存取值', this.map.get(key))
      return this.map.get(key)
    }
    const result = eval(params.join('+'))
    this.map.set(key, result)
    console.log('计算取值', result)
    return result
  }
}
const getResClass = new getRes()
const getResult = (...params) => getResClass.getResult(...params)
getResult(1, 2, 3)
getResult(1, 2, 3)
getResult(1, 2)
getResult(1, 2, 3, 4)
getResult(1, 2, 3, 4)


32.常用缓存方式


1.localStorage

2.sessionStorage

3.cookie

4.闭包

5.class

33.全局关闭项目console.log

mainjs里调用

const isDebug = true;  // 控制是否屏蔽全局console.log 日志;isDebug设为false即可屏蔽
console.log = (function (oldLogFunc) {
  return function () {
    if (isDebug) {
      oldLogFunc.apply(this, arguments);
    }
  }
})(console.log);

34.滚动元素到底部

 scrollTop 确定垂直滚动的像素数   scrollHeight 是元素的高度(可见和不可见部分)
el.scrollTop = el.scrollHeight;

35.调用浏览器下载功能

  dowload(fileName, url) {
      let x = new XMLHttpRequest()
      x.open('GET', url, true)
      x.responseType = 'blob'
      x.onload = function (e) {
        let blob = x.response
        if ('msSaveOrOpenBlob' in navigator) {
          //IE导出
          window.navigator.msSaveOrOpenBlob(blob, fileName)
        } else {
          let a = document.createElement('a')
          a.download = fileName
          a.href = URL.createObjectURL(blob)
          document.querySelector('body').appendChild(a)
          a.click()
          document.querySelector('body').removeChild(a)
        }
      }
      x.send()
    },

36.打印单个window元素

1.借用iframe功能 2.生成网页的方式

printCode() {
    const iframe = document.createElement('iframe')
    iframe.style.height = 0
    iframe.style.visibility = 'hidden'
    iframe.style.width = 0
    // 设置 iframe 内容
    iframe.setAttribute('srcdoc', '<html><body></body></html>')
    document.body.appendChild(iframe)
    iframe.addEventListener('load', function () {
      // 克隆页面的图片元素
      const image = document.getElementById('codeRef').cloneNode()
      image.style.maxWidth = '100%'

      // 把克隆的图片元素添加到 iframe 内
      const body = iframe.contentDocument.body
      body.style.textAlign = 'center'
      body.appendChild(image)
      image.addEventListener('load', function () {
        iframe.contentWindow.print()
      })
    })
    iframe.contentWindow.addEventListener('afterprint', function () {
      // 通过父级页面删除 iframe 自己
      iframe.parentNode.removeChild(iframe)
    })
  },

2.生成网页

doPrint() {
      var head_str = '<html><head><title></title></head><body>' //先生成头部
      var foot_str = '</body></html>' //生成尾部
      var older = document.body.innerHTML
      var new_str = document.getElementById('wrapper').innerHTML //获取指定打印区域
      // var new_str = document.getElementsByClassName('blog-content-box')[0].innerHTML;//获取指定打印区域
      var old_str = document.body.innerHTML //获得原本页面的代码
      document.body.innerHTML = head_str + new_str + foot_str //构建新网页
      window.print() //打印刚才新建的网页
      document.body.innerHTML = older //将网页还原
      return false
    },

3.插件

https://blog.csdn.net/weixin_45224906/article/details/127762534

37.在线生成二维码的api

支持 https 的二维码 api 服务并不多,这里是经过精心筛选后剩下的结果。推荐日常使用搜狐视频提供的二维码 api 接口,稳定性很好,站长已使用多年。

使用方法很简单,替换 https://www.abc.com 为想要生成的文字或链接即可。

搜狐视频提供的二维码 api,已稳定五年以上。
https://my.tv.sohu.com/user/a/wvideo/getQRCode.do?text= https://www.abc.com

搜狐快站提供的二维码 api,已稳定两年以上。
https://www.kuaizhan.com/common/encode-png?large=true&data= https://www.abc.com

qrserver 提供的二维码 api,国外服务,已稳定五年以上。
https://api.qrserver.com/v1/create-qr-code/?size=150×150&data= https://www.abc.com

qrcoder 提供的二维码 api,国外服务,已稳定五年以上。
https://www.qrcoder.co.uk/api/v1/?text= https://www.abc.com

p= 二维码尺寸,可选范围 1-40 已稳定有两年左右。
https://api.isoyu.com/qr/?m=0&e=L&p=10&url= https://www.abc.com

38.判断两个范围是否存在交集

a<end&&b>start

39.文件流创建本地url

url = window.URL.createObjectURL(blob)

40.下载文件流

import request from "./request";


export default function(config) {
  return request({
    ...config,
    responseType: "blob",
  }).then(({ data, headers }) => {
    let filename = "";
    if (config.name) {
      //机构端批量导入下载
      filename = config.name;
    } else {
      if (headers["content-disposition"]) {
        filename = headers["content-disposition"].match(
          /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
        )[1];
        filename = decodeURIComponent(filename);
      } else {
        filename = decodeURIComponent(headers.attachment);
      }
    }


    downloadFile(filename, data);
  });
}


function downloadFile(fileName, content) {
  const blob = new Blob([content]);
  if ("msSaveOrOpenBlob" in window.navigator) {
    window.navigator.msSaveOrOpenBlob(blob, fileName);
  } else {
    const a = document.createElement("a");
    a.download = fileName;
    a.href = URL.createObjectURL(blob);
    a.click();
    URL.revokeObjectURL(blob);
  }
}

42.导出数组表格数据为excel 文件

https://github.com/SheetJS/js-xlsx (工具)

https://zhuanlan.zhihu.com/p/215713923

yarn add xlsx

import * as XLSX from 'xlsx';

exportExcel(){
  // 构造数据
  let _data = [
    ['id', 'name', 'value'], //表头

    [1, 'sheetjs', 7262], // 每行数据

    [2, 'js-xlsx', 6969], // 每行数据
  ];

  let ws = XLSX.utils.aoa_to_sheet(_data); // 加到sheet 里面

  ws['!cols'] = [{ wch: 60 }, { wch: 20 }]; // 设置每列宽度


  /* generate workbook and add the worksheet */
  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, 'Sheet1'); // sheet 加到文件里面

  let wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' }); //转换为二进制

  // 定义 应该二进制转 blob 的方法
  const s2ab = (s: any) => {
    let buf = new ArrayBuffer(s.length); //convert s to arrayBuffer
    let view = new Uint8Array(buf); //create uint8array as viewer
    for (let i = 0; i < s.length; i++) view[i] = s.charCodeAt(i) & 0xff; //convert to octet
    return buf;
  };

  // 创建一个a 标签 好下载
  const fileURL = window.URL.createObjectURL(
    new Blob([s2ab(wbout)], { type: 'application/octet-stream' }),
  );
  const fileLink = document.createElement('a');

  fileLink.href = fileURL;
  fileLink.setAttribute('download', `test.xlsx`);
  document.body.appendChild(fileLink);

  fileLink.click();
}
posted @ 2023-08-15 15:42  丶乔  阅读(10)  评论(0编辑  收藏  举报