JavaScript 点滴积累

327 阅读6分钟

1、有图片的页面等所有图片加载完毕再进行判断

    /*等所有图片加载完毕后再判断文本高度以设置置底方式
     *
     */
    $('#main').find('img').load(function() {
        imgs --;
        if (!imgs) {
            setFooterPos();
        };
    });

2、ajax post发送数据

      formData方式会自动把boolean类型的转化为string类型
      如果不让它转化,加上 contentType: "application/json; charset=utf-8" 
      数据序列化 JSON.stringify(link_data); 使之变成json形式传值

3、非常巧妙的数组去重办法

   const arr1 = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
 const arr2 = arr1.filter( (element, index, self) => { return self.indexOf( element ) === index; }); //核心行
 console.log( arr2 ); // [1, 2, 3, 5, 4] 
 console.log( arr1 ); // [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4]

4、js实现剪切板功能

    var Url2 = ENV.INSURANCE_HOST + "/fl/" + row.flowId
    var oInput = document.createElement("input")
    oInput.value = Url2
    document.body.appendChild(oInput)
    oInput.select() // 选择对象
    document.execCommand("Copy") // 执行浏览器复制命令
    

5、0.1 + 0.2 等不等于0.3的正确比较方法

  console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);
  Number.EPSILON  number类型的最小精度
  Math.abs   返回绝对值的方法
  

6、判断数据类型的办法

 var symbolObject = (function(){ return this; }).call(Symbol("a"));
  console.log(typeof symbolObject); //object
  console.log(symbolObject instanceof Symbol); //true
  console.log(symbolObject.constructor == Symbol); //true
  

7、重要的按钮操作(如发送,创建)要给按钮添加去重操作

8、时间戳转换(传入13位)

  time(time = +new Date()) { 
    var date = new Date(time + 8 * 3600 * 1000) // 增加8小时
    return date
      .toJSON()
      .substr(0, 19)
      .replace("T", " ")
  },
  

9、原生js去除字符串空格

      String.prototype.trim=function(){
       return this.replace(/(^\s*)|(\s*$)/g, "");
      }

10、vue路由query问题

vue 路由query取出的参数为字符串类型 所以不要用true/false放到query的参数上

11、获取当天时间的 24:00

方法一:
      a = Date.now() + 1000 * 60 * 60 * 8
      a - (a % (1000 * 60 * 60 * 24)) -  (1000 * 60 * 60*8)    
      a % (1000 * 60 * 60 * 24)  //一整天的秒数
方法二:
      new Date("2019-5-17").getTime() //1558022400000
      用方法拼括号里的字符串

12、http的知识

从 HTTP 请求回来,就产生了流式的数据,后续的 DOM 树构建、CSS 计算、渲染、合成、绘制,都是尽可能地流式处理前一步的产出:即不需要等到上一步骤完全结束,就开始处理上一步的输出,这样我们在浏览网页时,才会看到逐步出现的页面。

304 又是一个每个前端必知必会的状态,产生这个状态的前提是:客户端本地已经有缓存的版本,并且在 Request 中告诉了服务端,当服务端通过时间或者 tag,发现没有更新的时候,就会返回一个不含 body304 状态。

13、meta标签的用法

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<!-- 默认使用最新浏览器 -->
<meta http-equiv="Cache-Control" content="no-siteapp">
<!-- 不被网页(加速)转码 -->
<meta name="robots" content="index,follow">
<!-- 搜索引擎抓取 -->
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
<meta name="apple-mobile-web-app-capable" content="yes">
<!-- 删除苹果默认的工具栏和菜单栏 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- 设置苹果工具栏颜色 -->

<meta name="format-detection" content="telephone=no">
<meta name="format-detection" content="date=no">
<meta name="format-detection" content="address=no">
<meta name="format-detection" content="email=no">
<!--关闭iOS上的内容识别-->

http://www.alenqi.site/2018/03/04/complete-tags/
<!--别人总结好的meta的链接-->

14、随机生成的加密字符串库(crypto-random-string)

$ npm install crypto-random-string //安装命令

const cryptoRandomString = require('crypto-random-string');
 
cryptoRandomString({length: 10});
//=> '2cf05d94db'
 
cryptoRandomString({length: 10, type: 'base64'});
//=> 'YMiMbaQl6I'
 
cryptoRandomString({length: 10, type: 'url-safe'});
//=> 'YN-tqc8pOw'
 
cryptoRandomString({length: 10, characters: '1234567890'});
//=> '1791935639'

15、浏览器的微观任务和宏观任务

    //宏观任务是浏览器宿主api发起的任务 例:setTimeout
    //微观任务 JavaScript引擎发起的任务 例:promise
    //每个宏观任务都有一个微观任务队列
    //promise会加到宏观任务的最后
    
    var r = new Promise(function(resolve, reject){
        console.log("a");
        resolve()
    });
    r.then(() => console.log("c"));
    console.log("b")
    //a,b,c

16、lodash库

  Lodash 通过降低 array、number、objects、string 等等的使用难度从而让 JavaScript 变得更简单。 Lodash 的模块化方法 非常适用于:

  遍历 arrayobjectstring
  对值进行操作和检测
  创建符合功能的函数
  
  // Load the full build.
  var _ = require('lodash');
  // Load the core build.
  var _ = require('lodash/core');
  // Load the FP build for immutable auto-curried iteratee-first data-last methods.
  var fp = require('lodash/fp');
   
  // Load method categories.
  var array = require('lodash/array');
  var object = require('lodash/fp/object');
   
  // Cherry-pick methods for smaller browserify/rollup/webpack bundles.
  var at = require('lodash/at');
  var curryN = require('lodash/fp/curryN');

17、小练习

题目:我们现在要实现一个红绿灯,
把一个圆形 div 按照绿色 3 秒,
黄色 1 秒,红色 2 秒循环改变背景色
fuction sleep(duration){
    return new Promise((resove,reject) =>{
        setTimeout(resove,duration)
    })
}
sleep(2000).then(function(){
    
})

18、上下文的概念

JavaScript 标准把一段代码(包括函数),
执行所需的所有信息定义为:“执行上下文”。

19、上传图片本地预览功能

  uploadChange(file) {
    console.log(file)
    let blobUrl
    try {
      blobUrl = URL.createObjectURL(file.raw)
    } catch (err) {
      console.error("[Element Error][Upload]", err)
    }
    console.log(blobUrl)
  },
  

URL.createObjectURL() 静态方法会创建一个 DOMString,
其中包含一个表示参数中给出的对象的URL。
这个 URL 的生命周期和创建它的窗口中的 document 绑定。
这个新的URL 对象表示指定的 File 对象或 Blob 对象。

用 URL.revokeObjectURL() 方法来释放内存

20、every和some方法

every()是对数组中每一项运行给定函数,
如果该函数对每一项返回true,则返回truesome()是对数组中每一项运行给定函数,
如果该函数对任一项返回true,则返回trueconst tempData = [
  {
    id: 1,
    name: "rocker",
    adress: "US"
  },
  {
    id: 2,
    name: "rocker",
    adress: "US"
  },
  {
    id: 3,
    name: "rocker",
    adress: "US"
  }
];
let everyReturn = tempData.every((item, index) => {
  return item.id > 1;
});
let someReturn = tempData.some((item, index) => {
  return item.id > 2;
});

console.log(everyReturn);
//有一个是错的就返回 false 且的关系

console.log(someReturn);
//有一个是对的就返回 true 或的关系

21、npm

查看可用的npm源
nrm ls

// 用法: nrm use ***
nrm use taobao
// 切换之后可用 nrm ls查看是否已经切换了npm源

22、前端总结(github优质资源整理)

https://juejin.cn/post/6844903902299553806

23、JavaScript定义函数的几种方式

1、普通函数
function foo(){
    //code
}
2、箭头函数
const foo = () => {
    //code
}
3、class中定义的函数
class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
//函数声明   会提升
//类声明     不会提升

24、讲个笑话

佩奇有天放学回家对妈妈抱怨说:同学们都说我长得像吹风机
妈妈平静的看着佩奇:说话就说话,你别拿嘴吹我

25、深拷贝

//方法1
JSON.parse(JSON.stringify())
//方法2 ES6
const arr1=[1,2,3];
const arr2=Array.from(arr1)
//方法3
用lodash的cloneDeep
//方法4  concat 方法会返回一个新数组
var cc = [].concat(data);

26、处理 retina 1px的兼容问题

github.com/jonathantne…

27、src和href的区别

  • href 是指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,用于超链接。
  • src 是指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;
  • 在请求 src 资源时会将其指向的资源下载并应用到文档内,例如 js 脚本,img 图片和 frame 等元素。 当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此,类似于将所指向资源嵌入当前标签内。这也是为什么将 js 脚本放在底部而不是头部。

28、parseInt

parseInt(string, radix)
参数描述
string必需。要被解析的字符串。
radix可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。

如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。

['1', '7', '11'].map(parseInt) 的结果是 [1, NaN, 3] 的原因是因为,map() 方法是向传递给他的函数中传递三个参数,分别为当前值,当前索引以及整个数组

而 parseInt 函数接收两个参数:需要转换的字符串,以及进制基数,所以,整个语句可以写作:['1', '7', '11'].map((value, index, array) => parseInt(value, index, array)),array 被 parseInt 舍弃之后,得到的结果分别是:parseInt('1', 0)、parseInt('7', 1) 以及 parseInt('11', 2),也就是上面看到的 [1, NaN, 3]。

29、cherry-pick

先切一个新的分支
git cherry-pick 某次commit的标识
git cherry-pick continue

30、vscode 保存时自动格式化代码

"editor.formatOnSave": true,  //保存时自动格式化

31、阶段总结

到了什么都懂一点,但是什么都不精通的阶段

32、睡眠函数

/**
 * 睡眠函数
 *
 * @param {number} time 睡眠时间
 * @returns
 */
export const sleep = (time = 0) => {
  return new Promise((reslove) => {
    setTimeout(reslove, time)
  })
}

33、sentry介绍

  • Sentry 是一个实时事件日志记录和汇集的平台。其专注于错误监控以及提取一切事后处理所需信息而不依赖于麻烦的用户反馈。它分为客户端和服务端,客户端(目前客户端有Python, PHP,C#, Ruby等多种语言)就嵌入在你的应用程序中间,程序出现异常就向服务端发送消息,服务端将消息记录到数据库中并提供一个web页方便查看。Sentry由python编写,源码开放,性能卓越,易于扩展,目前著名的用户有Disqus, Path, mozilla, Pinterest等。

34、空格和tab

tab在不同的系统中占位不同,所以不推荐tab

35、PostCSS

PostCSS是一款使用插件去转换CSS的工具

36、多个select框不能选同一个值的问题

每次选择的时候,都去遍历所有的select框的值,

把这些值放到一个数组,把这个数组中有的值设置为disabled

37、查询git历史操作

fc -il 1

38、insertAdjacentElement

句法
targetElement .insertAdjacentElement(position,element);

参数
position
A DOMString表示相对于的位置targetElement; 必须匹配(不区分大小写)以下字符串之一:
'beforebegin':在targetElement自己之前。
'afterbegin':就在targetElement第一个孩子面前。
'beforeend':就在targetElement最后一个孩子之后。
'afterend':targetElement自己之后。

element
要插入树中的元素。

返回值
插入的元素,或者null插入失败的元素。

39、map ( )

//不会改变原数组
//返回一个新数组

The map() method creates a new array 
with the results 
of calling a provided function on every 
element in the calling array

40、数组中返回某个匹配的值

function testMap3(key) {
    let arr = [
      {
        key: 1,
        value: 1
      },
      {
        key: 2,
        value: 2
      },
      {
        key: 3,
        value: 3
      },
      {
        key: 4,
        value: 4
      },
    ]
    let data = arr.filter((item, index) => {
      return item.key === key
    })
    return data
  }
  console.log(testMap3(2));//[{key: 2, value: 2}]

41、移动端调试神器

<script src="https://res.wx.qq.com/mmbizwap/zh_CN/htmledition/js/vconsole/3.0.0/vconsole.min.js"></script>
<script>
   var vConsole = new VConsole();
</script>

移动端调试模拟pc端的控制台
直接在html页面引入 奇迹就会出现

42、try catch finaly语句

catch语句中不能声明变量e,否则会报错
finaly 语句一定会执行 一般用于释放资源

43、赋值表达式结合运算符

a += b 等价于 a = a + b

能这样用的运算符还有
*=、/=、%=、+=、-=、<<=
>>=、>>>=、&=、^=、|=、**=

44、react setState方法立即生效的办法

this.state = {
  count:0
}
this.setState((prevState) => {
  return { count: 0 }
})
this.setState((prevState) => {
  return { count: prevState.count + 1 } // 上一个 setState 的返回是 count 为 0,当前返回 1
})
this.setState((prevState) => {
  return { count: prevState.count + 2 } // 当前返回 3
})

上面我们进行了三次 setState,但是实际上组件只会重新渲染一次,而不是三次;这是因为在 React.js 内部会把 JavaScript 事件循环中的消息队列的同一个消息中的 setState 都进行合并以后再重新渲染组件

45、获取textarea多行文本行数

text.split(/\r?\n|\r/).length

46、查询npm插件使用情况

https://www.npmjs.com/package/package

47、手机号脱敏

phoneHide(phone) {
    var reg = /(\d{3})\d*(\d{4})/
    var hiddenPhone = phone.replace(reg, "$1****$2")
    return hiddenPhone
}

48、forEach跳出循环

Array.forEach(item => {
    if(true){
        throw new error()
    }
)

另外 every 和 some 都可以用return来终止循环

49、增删改url的参数

1、把参数提取成对象格式(qs库、url-parse)

2、改变对象

3、对象再转换为参数格式拼接到url上

50、递归处理树型数据

const selectFormat = items => {
  return items.map(({ title, value, children, id, name }) => {
    const hasChildren = Array.isArray(children)
    const selectKey = UUID()
    return {
      title: title || name,
      value: hasChildren ? selectKey : value || id,
      children: hasChildren ? selectFormat(children) : [],
      key: selectKey,
    }
  })
}

51、 一个样式解决表格信息为空

empty识别空字符串

.ivu-table-cell>span:empty:after{
    content:'暂无数据';
    font-size:12px;
    color:#ccc;
}

52、命令行工具


# ~/.zshrc 结尾处增加以下内容
# 重启命令行或者执行 `source ~/.zshrc` 之后才能生效
 
# 输入 `code` 命令在任意位置使用 VSCode 打开代码,例如输入 `code .` 打开当前目录
alias code="/Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin/code"
 
# 输入 `history` 命令查询历史操作
alias history="fc -il 1"
 
# 代码管理别名命令
# 切换至 qa 分支并更新 qa 至最新代码
alias reset-qa="git fetch --all && git checkout qa && git reset --hard upstream/qa"
# 切换至 production 分支并更新 production 至最新代码
alias reset-production="git fetch --all && git checkout production && git reset --hard upstream/production"
# 推送代码并自动创建 Merge Request 至 qa 分支,Pipeline 成功之后将会自动合并
alias push-qa="git push origin -o merge_request.create -o merge_request.merge_when_pipeline_succeeds -o merge_request.target=qa"

53、复制文本

// 复制文本
export const copyText = (text, cb) => {
  if (window.clipboardData && window.clipboardData.setData) return window.clipboardData.setData('Text', text) // IE 兼容
  function save(e) {
    e.clipboardData.setData('text/plain', text)
    e.preventDefault()
  }
  document.addEventListener('copy', save)
  try {
    if (!document.execCommand('copy')) throw new Error('复制失败')
  } catch (err) {
    window.prompt('Ctrl + C 复制剪切板', text)
  } finally {
    document.removeEventListener('copy', save)
    cb && cb()
  }
}

54、【问题记录】 如何在不阻塞載入或等待載入的情況下載入 iframe

stackoverflow.com/questions/5…

55、互联网常用英文简称

人物类

  • PM-Product Manager-产品经理
  • -Project Manager-项目经理
  • RD-Research and Development- 研发
  • FE-Front-End-前端;web前端研发;
  • OP-Operations-运维
  • UI-User Interface-用户界面
  • UID-User Interface Design-用户界面设计
  • ID-Interaction Design-交互设计
  • UE or UX-User Experience-用户体验
  • UED-User Experience Design-用户体验设计
  • UCD-User Centered Design-以用户为中心的设计
  • DBA-Database Administrator-数据库管理员

文档类

  • PRD-Product Requirements Document-产品需求文档
  • BRD-Business Requirements Document-商业需求文档
  • MRD-Market Requirements Document-市场需求文档
  • FSD-Functional Specifications Document-功能详细说明

56、判断两个区间是否存在交集

dayjs diff 方法可以判断两个时间段时候存在交集
  • 思考过程 判断两个区间是否存在交集,情况太多,容易漏掉情况,曲线救国,判断两个区间不存在交集 先排序,然后比大小

57、 生产环境强制开启Vue Devtools

blog.eh5.me/force-enabl…

58、 前端大文件上传

前端大文件上传网上的大部分文章已经给出了解决方案,核心是利用 Blob.prototype.slice 方法,此方法和数组的 slice 方法相似,调用的 slice 方法可以返回原文件的某个切片。

这样我们就可以根据预先设置好的切片最大数量将文件切分为一个个切片,然后借助 http 的可并发性,同时上传多个切片,这样从原本传一个大文件,变成了同时传多个小的文件切片,可以大大减少上传时间。

另外由于是并发,传输到服务端的顺序可能会发生变化,所以我们还需要给每个切片记录顺序。

59、 前端大文件断点续传

断点续传的原理在于前端/服务端需要记住已上传的切片,这样下次上传就可以跳过之前已上传的部分,有两种方案实现记忆的功能:

1、前端使用 localStorage 记录已上传的切片 hash。 服务端保存已上传的切片

2、hash,前端每次上传前向服务端获取已上传的切片。

第一种是前端的解决方案,第二种是服务端,而前端方案有一个缺陷,如果换了个浏览器就失去了记忆的效果,所以这里选取后者。

60、检测文件类型插件

file-type

npm 链接: file-type

61、?. 和 ?? 操作符

  • ?.操作符 如果对象不存在,刚返回 undefined
// 这样的写法可以使代码更健壮

// 对象
console.log(user.homeaddress?.country); 

// 数组 如果hobbies[3] 不存在name属性,就会报错
user.hobbies[3].name  
// 改写为
user.hobbies?.[3].name  
  • ?? 操作符 不返回 undefined 而是返回一个默认值
const country = user.officeaddress?.country;
console.log(country);
// undefined

需要返回默认值:

const country = user.officeaddress?.country ?? "中国";
console.log(country);
// 中国

62、浏览器重发请求

火狐浏览器

找到请求,右键编辑并重发,编辑请求数据后点击发送就可以重发请求

谷歌浏览器

右键 -> copy -> copy as fetch 然后复制粘贴到控制台,修改,回车执行代码

63、数据兜底

即使在对好接口后,也不要信任后端的任何返回

所有页面 所有操作都要做好兜底操作

64、 waitOneSecond

waitOneSecond() {
    return new Promise(resolve => {
        setTimeout(resolve, 1000);
    });
}

65、Intersection Observer

IntersectionObserver接口 (从属于Intersection Observer API) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。祖先元素与视窗(viewport)被称为根(root)。