js 的巧妙优雅使用方法整理

7,071 阅读8分钟

前言:

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

一、!!强制转布尔值boolean

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

假值有:
        0  、  “”  、   nullundefinedfalseNaN

除了这 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 trimSpace(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(trimSpace(strr,1))      //  "1addertasdfsdfASDFDFDFGSDFG"

解析:

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

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

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

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

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

七、给sessionStorage存储对象

// bad:

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

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

// good:

存:
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


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

最后:
        祝各位工作顺利!
                     -小菜鸟Christine