提高工作效率之原生JS的方法

如今框架横行,但原生JS学习反而变少了,框架虽然方便了,但掌握原生JS才是最基础的,本文分享了一些提供工作效率的原生JS方法,希望对你有所帮助。

作者:玖月晴空
链接:https://juejin.im/post/5a16a1fb6fb9a045284627d3

前言:

随着前端市场日新月异的发展,现如今的市场要的不只是会切切图的小仔、小妹了,而是需要真正懂原生js闭包,继承,原型链,node,以及熟读源码的大神,那么我们也不能太落后各位大神,撸起袖子,重新拾起原生js吧! 以下是个人总结,也有一些是copy大神的,现在放到一起,方便以后查阅(有不对的地方,还望大家能够提出,我会尽快加以改正)。

一、!!强制转布尔值boolean

根据当前需要判断的值是真值还是假值来判断,真值返回true,假值返回false,那么这样的话,除了假值,剩下的也都是真值了。

假值有:
        0  、  “”  、   null  、 undefined  、  false  、NaN、
      

除了这 6 个外,其它均为“真” ,包括对象、数组、正则、函数等。 注意: '0'、'null'、'false'、{}、[]也都是真值 。 那么下面我们来看看!!是如何转布尔值的。 例如: 首先我们声明3个变量,xnull,y为空字符串,str为字符串,下面看看他们添加了"!!"后会有什么结果。

var x=null;
var y="";
var str="abcd";

console.log(!!x)      // false;
console.log(!!y)      // false;
console.log(!!str)    // true;

如上所说,假值返回false,真值返回true

二、数字字符串str强制转Number

这里的强转是对于数字字符串,例如:"22","6",可直接使用如下方法直接使用运算的方式来转换,null能参与计算,时在计算时null会先转成0,然后再进行运算。

  1. 将字符串前加+,可以强制转number,下面我们就一起来试试吧!
var str="88";
console.log(+str)   // 88

//但是如果是混合类型的字符串,则会转为NaN
+"1606e" ;  // NaN
+ null  ;   // 0
  1. 将字符串减去一个数字
"11" - 1 ; // 10
 null - 1  ; // -1
  1. 将字符串乘以一个数字
"111" * 1 ; // 111
 null * 1 ;  // 0
  1. 将字符串除以一个数字
"111" / 1 ;  // 111
 null / 1 ;  // 0

也可以用来判断:


if(toString.call(str*1)==[object Number]){
    dosomething..
}

三、不可靠的undefined 可靠的void 0

JavaScript中,假设我们想判断一个是否是 undefined,那么我们通常会这样写:

if(a === undefined){
 dosomething.....
}

但是在javascript中,undefined是不可靠的 例如: 当undefined被放在在function函数内,我们把它当成一个局部变量,它是可以赋上值,下面我们来试试。

function foo2(){
    var undefined=1;
    console.log(undefined)
}
foo2();     // 1;

但是当在函数内定义一个全局变量,并不能给赋上值

var undefined;
function foo2(){
    undefined=1;
    console.log(undefined)
}
foo2()    // undefined

那么我们试试用void 0或者 void (0)来代替: 先声明一个变量a,赋值为undefined,接下来我们用void 0来判断一下。

var a=undefined;

//用void 0来判断一下
if(a===void 0){
    console.log('true')
}       // true

//再用void (0)来判断一下
if(a===void (0)){
    console.log('true')
}       // true
//最后我们打印一下这两个的返回值
console.log(void 0,void (0))    // undefined undefined

我们现在可以通过void 0 运算来获得 undefined;那在以后需要判断值为undefined的时候,可以直接用void 0或者void (0),而且这两个值的直接返回值就是undefined,所以说非常可靠哦!

四、字符串也是有length属性的!

我们知道所有的Array都是有length属性的,就算是空数组,那么length 为0,那么字符串有没有呢?接下来我们来验证一下。

var str="sdfsd5565s6dfsd65sd6+d5fd5";
console.log(str.length)      // 26

结果是有的,所以我们在判断类型时,不能单纯拿有没有length属性来判断是不是数组了,我们可以用下面的方法来判断是否是数组:

var obj=[1,2] ;
console.log(toString.call(obj) === '[object Array]');

五、如何创建一个随机数组,或者将已有的数组打乱?

在项目中有时候我们需要一个随机打乱的数组,那么下面我们来实现以下: 先来创建一个数组:

var arr=[];
for(var i=0;i<10;i++){
    arr.push(i)
}
console.log(arr)    // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

接下来我们来打乱它:

arr.sort(()=>{
    return Math.random() - 0.5
})                 // [1, 0, 2, 3, 4, 6, 8, 5, 7, 9]

第二种打乱方法:

arr.sort((a,b)=>{
    return a>Math.random()*10;
})                // [1, 2, 0, 6, 4, 3, 8, 9, 7, 5]

我们以前的正常排序是这样的

arr.sort(function(a,b){
    return b-a
});

解析:

先说正常的排序: a,b表示数组中的任意两个元素,若return > 0 ,ba后;若reutrn < 0ab后;当a=b时,则存在浏览器兼容 ; a-b输出从小到大排序,b-a输出从大到小排序。 然后再说我们打乱的方法: 创建数组不用说,接下来就是用jssort方法 来实现,Math.random()实现一个随机0-1之间的小数 然后再减去0.5,这时就会根据return比较后得到的值排序,所以说就会生成不是正常从大到小或者从小到大的排序。

第二个打乱的方法同样是遵循sort的方法,将a,b传进去 然后和随机数做比较,关于比较的方法不太清楚。

六、去除前后、前、后所有空格

这是专门为去除空格写的一套方法,适用于各种情况,所有空格,前后空格,前空格,后空格。

var strr="    1 ad dertasdf sdfASDFDF DFG SDFG    "
    //  type 1-所有空格,2-前后空格,3-前空格,4-后空格
function trim(str,type){
    switch (type){
        case 1:return str.replace(/\s+/g,"");
        case 2:return str.replace(/(^\s*)|(\s*$)/g, "");
        case 3:return str.replace(/(^\s*)/g, "");
        case 4:return str.replace(/(\s*$)/g, "");
        default:return str;
    }
}
console.log( trim(strr,1))      //  "1addertasdfsdfASDFDFDFGSDFG"

解析:

\s : 空格符,Tab,换页符,换行符
\S : 非\s的所有内容
/g :  全局匹配
^  :  匹配在行首
$  :  匹配在行尾
+  : 重复次数>0
*  : 重复次数>=0
|  :  或者 

replace(a,b): 方法用于在字符创中用一些字符替换另一些字符, 会传入两个值,将逗号前面的值a替换成逗号后面的值b

如只需要去除前后空格,可直接使用js的trim()方法:

let str = "  abcd  ";
str.trim()  // "abcd"

关于正则匹配,我有一篇文章专门来介绍,传送门

七、字母大小写切换(正则匹配,replace

这个方法主要是给一些需要大小写转换提供的方法,主要有首字母大写,首字母小写,大小写转换,全部转大写和全部转小写。

type:
&emsp;&emsp;1:首字母大写
&emsp;&emsp;2:首页母小写
&emsp;&emsp;3:大小写转换
&emsp;&emsp;4:全部大写
&emsp;&emsp;5:全部小写
&emsp;&emsp;

原始字符串:

var str="sdfwwerasfddffddeerAasdgFegqer";

function changeCase(str,type) {

   //这个函数是第三个大小写转换的方法
    function ToggleCase(str) {
        var itemText = ""
        str.split("").forEach(
                function (item) {
                 // 判断循环字符串中每个字符是否以a-z之间开头的并且重复大于0次
                    if (/^([a-z]+)/.test(item)) {
                    //  如果是小写,转换成大写
                        itemText += item.toUpperCase();
                    }
                //  判断循环字符串中每个字符是否以A-Z之间开头的并且重复大于0次
                    else if (/^([A-Z]+)/.test(item)) {
                   //   如果是大写,转换成小写
                        itemText += item.toLowerCase();
                    }
                    else{
                  //  如果都不符合,返回其本身
                        itemText += item;
                    }
                });
        return itemText;
    }
  //下面主要根据传入的type值来匹配各个场景
    switch (type) {
         //当匹配
        case 1:
            return str.replace(/^(\w)(\w+)/, function (v, v1, v2) {
                 //v=验证本身  v1=s ; v2=dfwwerasfddffddeerAasdgFegqer
                return v1.toUpperCase() + v2.toLowerCase();
            });
        case 2:
            return str.replace(/^(\w)(\w+)/, function (v, v1, v2) {
                //v=验证本身  v1=s ; v2=dfwwerasfddffddeerAasdgFegqer
                return v1.toLowerCase() + v2.toUpperCase();
            });
        case 3:
            return ToggleCase(str);
        case 4:
            return str.toUpperCase();
        case 5:
            return str.toLowerCase();
        default:
            return str;
    }

}

 console.log(changeCase(str,1))   //SdfwwerasfddffddeerAasdgFegqer

解析:

split:用于把一个字符串分割成字符串数组
\w: 数字0-9或字母a-z及A-Z,或下划线
\W: 非\w,除以上的特殊符号等   
toUpperCase:转大写
toLowerCase:转小写
replace第二个参数可以是函数,函数的参数中,第一个是本身,第二个是正则匹配内容,第三个匹配剩下的内容

replace第二个参数可以是函数,函数的参数中,第一个是本身,第二个是正则匹配内容,第三个匹配剩下的内容 下面我们就通过小实验来验证一下:

提高工作效率之原生JS的方法" data-src="https://user-gold-cdn.xitu.io/2017/11/27/15ffde656e0fc565?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="932" data-height="284" />

八、循环n次传入的字符串

str为传入随意字符串,count为循环的次数

 var str="abc";
 var number=555;

function repeatStr(str, count) {
    //声明一个空字符串,用来保存生成后的新字符串
    var text = '';
    //循环传入的count值,即循环的次数
    for (var i = 0; i < count; i++) {
       //循环一次就把字符串+到我们事先准备好的空字符串上
        text += str;
    }
    return text;
}
  console.log(repeatStr(str, 3))         // "abcabcabc"
  console.log(repeatStr(number, 3))      // "555555555"

解析:根据count循环的次数,在循环体内复制,return 返回+=后的值

九、常用校验验证:邮箱,手机号,名字,大写,小写

function checkType (str, type) {
    switch (type) {
        case 'email':
            return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
        case 'phone':
            return /^1[3|4|5|7|8][0-9]{9}$/.test(str);
        case 'tel':
            return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
        case 'number':
            return /^[0-9]$/.test(str);
        case 'english':
            return /^[a-zA-Z]+$/.test(str);
        case 'chinese':
            return /^[\u4E00-\u9FA5]+$/.test(str);
        case 'lower':
            return /^[a-z]+$/.test(str);
        case 'upper':
            return /^[A-Z]+$/.test(str);
        default :
            return true;
    }
}
console.log(checkType ('hjkhjhT','lower'))   //false

解析:

checkType ('hjkhjhT','lower')'需要验证的字符串''匹配的格式'
email:验证邮箱
phone:验证手机号
tel:验证座机号
number:验证数字
english:验证英文字母
chinese:验证中文字
lower:验证小写
upper:验证大写

十、给sessionStorage存储对象

// 需要存入的对象:

let obj={
   hellow:world
};
let str=JSON.Stringify(obj);
----------------

//简单使用:

存:
sessionStorage.setItem("Param",str);
取:
let get_data=JSON.parse(sessionStorage.getItem("Param")).hellow  // world
-------------------   

//进一步整理:

存:
sessionStorage.setItem("Param",JSON.stringify({Hellow:world}));
取:
JSON.parse(sessionStorage.getItem("Param")).Hellow   // world

十一、控制台打印执行时间

有时我们需要对比两个方法的执行效率,或者查看某方法的执行时间,那么我们就可以使用下面的方法作为监听的的方法。

console.time("开始时间:")

// 中间放你想执行的方法

console.timeEnd("结束时间:")

参考

十二、探究双等号 “==” 和恒等 “===”

=====运算符用于比较两个值是否相等,当然,它们对相等的定义不尽相同。两个运算符允许任意类型的操作数,如果操作数相等则返回true,否则返回false。那么关于=====有什么区别呢?让我们一起来探究。

参照:《权威指南》

'==='恒等

===严格相等运算符,首先计算其操作数的值,然后比较这两个值,比较过程没有任何类型转换:

  • 如果两个类型不相同,则它们不相等。
    例如:`1 === 'true'  // false`
  • 如果两个值都是null或者都是undefined,则它们相等。
    例如:
        null === undefined        // false
        null === null             // true
        undefined === undefined   // true
  • 如果两个值都是布尔值true或者都是false,则它们相等。
    例如:true === true   // true 
  • 如果其中一个值是NaN,或者两个值都是NaN,则它们不相等。(NaN和其他任何值都是不相等的,包括它本身。通过x!==x来判断x是否为NaN,只有在xNaN的时候,这个表达式的值才为true
    例如:NaN === NaN   // false
         NaN !== NaN    // true
  • 如果两个引用值指向同一对象,数组或函数,则它们是相等的。如果指向不同的对象,则它们是不相等的,尽管两个对象具有完全一样的属性。
例如:var obj = {};
         obj === obj ; // true 
    
    var obj1 = {a:1};
    var obj2 = {a:1};
        obj1 === obj2; // false
  • 如果两个值类型相等,值不相等,那么它们不相等。
例如:true === false;  //  false
      "1" === "8"     //  false
      
        ...
  • 如果两个值相等,类型相等,那么它们相等。
例如: "1"==="1";  //  true
      8 === 8;  // true
      "true" === "true";  //  true
      false === false;
      undefined === undefined;  //  true 
      null === null;  // true
      ...

'=='相等

相等运算符“==”和恒等运算符相似,但相等运算符但比较并不严格。如果两个操作数不是同一类型,那么相等运算符会尝试进行一些类型转换,然后进行比较。

  • 如果两个值类型相同,但值不同,那么它们不相等。
例如:"1" == "3";  //  false
     "true" == "false";  //  false
     false == true //  false
     ...
  • 如果一个值是null,一个值是undefined,则它们相等。
例如: null == undefined  //  true
  • 如果其中一个是布尔值,则将其转换为数字,true 转换为 1,false 转换为 0,然后再进比较。
例如:1 == true;  //  true
     false == 0  //  true
     true == false  //  false
  • 如果其中一个是数字,一个是字符串,先将字符串转为数字,然后再使用转换后的值进行比较。
例如:1 == "1"  //  true
     "500" == 800  //  false

  • 如果一个值是对象,另一个值是数字或字符串,则需将对象转换为原始值(通过toString()或valueOf().js中的内置类首先尝试使用valueOf(),再进行toString(),日期类除外,日期只使用toString() ),然后再进行比较。
var obj ={a:"b"};
    obj.toString();   //  "[object Object]"
    1 == obj;    //  false
  • 如果两个对象的类型相同,但引用地址不同,那么它们不相等。
例如:[] == []  //  false
     {} == {}  //  false

下面分享一个有意思的面试题:

例如: [] == ![]  //  true  这个为什么是true呢?
    
是因为 “!”的优先级大于 “ == ” ,所以先算右边,![] 结果为 false,

[] == ![] 等同于=> [] == false ;

如果一个值是对象,另一个值是数字或字符串,则需将对象转换为原始值,再比较:

[].toString()  => ''

[] == false 等同于=>   "" == false 

再进行类型转换,转为数字:

"" == false  等同于=>  0 == 0 

此时类型相同,比较值:

0 == 0   //  true

值相等,所以结果为true

几点注意事项:

1.首先会先进行类型判断,相同的类型直接比较值

2.特别注意undefinednull 相等

3.判断值的类型,如非object,全部转为number,再进行对比值,

注意:所有的假值,都转为 0,true转为 1


十三、把字符串作为 URI 组件进行编码、解码

  1. encodeURIComponent()函数可把字符串作为 URI 组件进行编码。
encodeURIComponent("中文")

//   "%E4%B8%AD%E6%96%87"
  1. decodeURIComponent()函数可把encodeURIComponent编码完的数据进行编码
decodeURIComponent("%E4%B8%AD%E6%96%87")

//  "中文"

十四、uuid生成随机字符串(比随机数高级的随机字符串)

平常我们用到随机数可能会想到的是如下:

Math.random() ⇨  0.3920174387754096

今天就推荐一个高逼格的生成随机字符串的方法:UUID

UUID 是通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部分其目的,是让分布式系统中的所有元素,都能有唯一的辨识信息,而不需要通过中央控制端来做辨识信息的指定。如此一来,每个人都可以创建不与其它人冲突的UUID。在这样的情况下,就不需考虑数据库创建时的名称重复问题。

UUID是由一组32位数的16进制数字所构成,所以UUID理论上的总数为16^32=2^128,约等于3.4 x 10^38。也就是说若每纳秒产生1兆个UUID要花100亿年才会将所有UUID用完。

UUID的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的32个字符。

示例:

550e8400-e29b-41d4-a716-446655440000

uuid 的 npm 地址

线上引入方式:

推荐使用版本4:

<script src="http://wzrd.in/standalone/uuid%2Fv4@latest"></script>

<script>

    uuidv4(); // ⇨ v4 UUID
    
</script>

推荐使用版本5:

<script src="http://wzrd.in/standalone/uuid%2Fv5@latest"></script>

<script>

    uuidv5('http://example.com/hello', uuidv5.URL); // ⇨ v5 UUID

</script> 

npm 下载方式:

npm install uuid

根据版本号按需引入:

<!--版本4-->

const uuidv4 = require('uuid/v4');

uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'

十五、clipboard.js:复制文字功能

今天再推荐一个使用的功能,就是我们的复制,不依赖flash, 不依赖其他框架,gzip压缩后只有3kb大小

ClipboardJS官网地址

1. 复制

复制:一个很常见的用例是从另一个元素复制内容。你可以给目标元素添加一个 data-clipboard-target 属性来实现这个功能。这个属性的值就是能匹配到另一个元素的选择器。

  1. 第三方CDN引入方式:地址

下面就写了个简版的原生html场景使用方式

<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
  </head>

  <body>
    <script>
      new ClipboardJS('.btn');
    </script>

    <input id="foo"    value="我是内容5555"  style='width:300px'>

    <button class="btn" data-clipboard-target="#foo">按钮按钮</button>
    
  </body>

</html>

  1. npm 下载方式:
npm install clipboard --save

下面是在react组件的使用方式:

import React, { useEffect } from 'react';
import ClipboardJS from 'clipboard'

const App = () => {

  useEffect(() => {
    const clipboard = new ClipboardJS('.btn')
    
    // 这里是在组件销毁的时候把 clipboard 销毁
    return () => clipboard.destroy()
  }, [])

  return (
    <>
      <input id="copy-text" value={'内容'} />

      <button className="btn" data-clipboard-target="#copy-text">复制</button>

    </>
  )
}

export default App;

2. 剪切

剪切:你可以定义一个 data-clipboard-action='cut' 属性来指明你想要复制还是剪切内容,使用方式如下:

<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
  </head>

  <body>
    <script>
      new ClipboardJS('.btn');
    </script>

    <input id="foo"    value="我是内容5555"  style='width:300px'>

    <button class="btn" data-clipboard-action="cut"  data-clipboard-target="#foo">按钮按钮</button>

  </body>

</html>

3. 从属性复制文本

从属性复制文本,简单说就是说不用必须从另一个元素来复制,你仅需要给目标元素设置一个data-clipboard-text 属性即可

<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
  </head>

  <body>
    <script>
      new ClipboardJS('.btn');
    </script>
    
    // 这里点击按钮,复制到粘贴板的内容就是data-clipboard-text上的值
    <button class="btn" data-clipboard-text="这里是我要的内容">按钮按钮</button>

  </body>

</html>

4. 复制/剪切 后的回调:success / error

有时我们复制 / 剪切后,需要给用户一些反馈,这里我们就用到事件的回调,如下

<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
  </head>

  <body>
    <script>

      var clipboard = new ClipboardJS('.btn');

       // 成功后的回调
      clipboard.on('success', function(e) {
          console.info('Action:', e.action);
          console.info('Text:', e.text);
          console.info('Trigger:', e.trigger);

          e.clearSelection();
      });
      // 失败后的回调
      clipboard.on('error', function(e) {
          console.error('Action:', e.action);
          console.error('Trigger:', e.trigger);
      });

    </script>

    <button class="btn" data-clipboard-text="这里是我要的内容">按钮按钮</button>

  </body>

</html>

(以上部分,有借鉴守候!大神的文章 github.com/chenhuiYj/e…

如果你对我对文章感兴趣或者有些建议想说给我听?,也可以添加一下微信哦!

如果亲感觉我的文章还不错的话,可以一下添加关注哦!