整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

常用的JavaScript代码技巧 (一)字符串、数

常用的JavaScript代码技巧 (一)字符串、数字

为一名前端程序员需要了解一些常用的JavaScript代码技巧,这样可以提高代码效率,我们就来看看具体的内容吧。


字符串类

1.比较时间

const time1="2022-03-05 10:00:00";
const time2="2022-03-05 10:00:01";
const overtime=time1 < time2;
// overtime=> true

2.货币格式

const ThousandNum=num=> num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
const cash=ThousandNum(100000000);
// cash=> 100,000,000

3.随机密码

const Randompass=len=> Math.random().toString(36).substr(3, len);
const pass=RandomId(8);
// pass=> "7nf6tgru"

4.随机HEX颜色值

const RandomColor=()=> "#" + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0");
const color=RandomColor();
// color=> "##26330b"

5.评价星星

const StartScore=rate=> "★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate);
const start=StartScore(4);
// start=> ★★★★☆

6.获得URL参数

const url=new URL('https://example.com?name=tom&sex=male');
const params=new URLSearchParams(url.search.replace(/\?/ig, ""));
params.has('sex'); // true
params.get("sex"); // "male"


数字类

  1. 数字处理,替代Math.floor() 和 Math.ceil()
const n1=~~ 1.19;
const n2=2.29 | 0;
const n3=3.39 >> 0;
// n1 n2 n3=> 1 2 3

2.补零

const FillZero=(num, len)=> num.toString().padStart(len, "0");
const num=FillZero(123, 5);
// num=> "00123"

3.转换成数值

const num1=+null;
const num2=+"";
const num3=+false;
const num4=+"59";
// num1 num2 num3 num4=> 0 0 0 59

4.时间戳

const timestamp=+new Date("2022-03-07");
// timestamp=> 1646611200000

5.小数

const RoundNum=(num, decimal)=> Math.round(num * 10 ** decimal) / 10 ** decimal;
const num=RoundNum(1.2345, 2);
// num=> 1.23

6.奇偶校验

const YEven=num=> !!(num & 1) ? "no" : "yes";
const num=YEven(1);
// num=> "no"
const num=YEven(2);
// num=> "yes"

7.获得最小值最大值

const arr=[0, 1, 2, 3];
const min=Math.min(...arr);
const max=Math.max(...arr);
// min max=> 0 3

8.生成范围随机数

const RandomNum=(min, max)=> Math.floor(Math.random() * (max - min + 1)) + min;
const num=RandomNum(1, 10); // 6 每次运行可能不一样


待续................

avaScript中的Number对象是一个用于处理数字值的对象,它可以通过构造函数new Number()创建,或通过字面量的形式创建。Number是一个全局对象,Number对象内部的一些属性和方法,即可以通过Number对象访问,也可以全局访问,如:parseInt()parseFloat等都来自于Number对象。

  1. Number对象

  2. Number对象属性/方法

  3. Number实例方法

1. Number对象

Number是一个未经封装的用于处理数字值的对象,我们可以用它的构造函数来创建一个数字对象,也可以用于将非数字对象转换为数字。

构造函数

new Number(value);

如上所示,为value创建了一个Number对象实例。如果value不可转换为数字,则返回NaN

非数字对象转换为数字

Number还可不做为构造函数使用,即:没有new操作符,不做为构造数时其主要用于类型的转换。

Number("123") // 123

Number("12.3") // 12.3

Number("") // 0

Number("0x11") // 17

Number("0b11") // 3

Number("0o11") // 9

Number("itbilu.com") // NaN

Number("100a") // NaN

在使用Number()函数进行数据类型转换时,其转换规则如下:

  • Boolean类型 - true转换为1false转换为0

  • 数字类型 - 原样输出

  • null - 返回0

  • undefined - 返回NaN

  • 字符串

    • 空字符串 - 转换为0

    • 字符串中只包含数字 - 转换成十进制数字

    • 包含小数点 - 转换成浮点数

    • 其它 - 返回NaN

  • Object类型 - 调用对象的valueOf()方法,再按上述规则进行转换

使用Number()与使用parseInt()parseFloat()进行数据类型转换的区别在于:

  • Number()可以将任何类型转换为数字,而parseInt()parseFloat()只能用于字符串的转换

  • Number()会对传入字符串进行整体转换,而parseInt()parseFloat()也会尝试对字符串中的部分数字进行转换。

  • 更多区别请参考:JavaScript数字类型转换

2. Number对象属性/方法

Number对象属性/方法是指通过Number调用的方法,可以它们理解为静态属性/方法。Number对象中的一些属性和方法被添加到了全局对象,这些属性和方法可以不通过Number对而直接调用。

属性

2.1 Number.EPSILON - 两个Number的最小差

Number.EPSILON属性用于表示两个Number的之间的最小差,该属性值接近于 2.2204460492503130808472633361816E-162-52

2.2 Number.MAX_SAFE_INTEGER - 最大安全整数

Number.MAX_SAFE_INTEGER属性表示JavaScript中最大的安全整数,其值为2-53-1

2.3 Number.MAX_VALUE - 最大值

Number.MAX_VALUE属性表示JavaScript中所能表示的最大正数值,其值接近于1.79E+308,超出后会表示为Infinity,最小负数值为-MAX_VALUE

2.4 Number.MIN_VALUE - 最小值

Number.MIN_VALUE属性表示JavaScript中所能表示的最小正数值,其址接近于0,最小负数值为-MIN_VALUE

2.5 Number.NaN - 非数字

Number.NaN表示“非数字”(Not-A-Number),和全局对象NaN相同。

2.6 Number.NEGATIVE_INFINITY - 负无穷大

Number.NEGATIVE_INFINITY属性表示负无穷大,会在溢出时返回该值。

2.7 Number.POSITIVE_INFINITY - 正无穷大

Number.POSITIVE_INFINITY属性表示负无穷大,与全局对象Infinity相同,会在溢出时返回该值。

2.7 Number.prototype - 原型属性

Number.prototype表示构造函数的原型,添加到原型上的属性或方法都可以被Number实例使用。

方法

2.8 Number.isNaN() - 判断值是否是NaN

Number.isNaN(value)

Number.isNaN()方法用于判断被检测的值是否是NaN,该方法是在ECMAScript 6中定义的方法与全局方法isNaN()并不是同一个方法。与全局方法isNaN()相比,该方法更安全,因为它不会强制进行类型转换。

2.9 Number.isFinite() - 是否是有穷数

Number.isFinite(value)

Number.isFinite()用于判断传入值是否是有穷数,该方法是在ECMAScript 6中定义的方法。

2.10 Number.isInteger() - 是否是整数

Number.isInteger(value)

Number.isInteger()用于关断传入的值是否是个整数。

2.11 Number.isSafeInteger() - 是否是安全整数

Number.isSafeInteger(value)

Number.isSafeInteger()用于关断传入的值是否是个整数,即:值是否位于-253-1253-1之间。

2.12 Number.parseFloat() - 字符串转换为浮点数

Number.parseFloat(string)

Number.parseFloat()用于把一个字符串转换为浮点数,该方法与全局方法parseFloat()一样,在ECMAScript 6被添加到Number对象中。

2.13 Number.parseInt() - 字符串转换为整数

Number.parseInt(string)

Number.parseInt()用于把一个字符串转换为整数,该方法与全局方法parseInt()一样,在ECMAScript 6被添加到Number对象中。

3. Number实例方法

Number实例继承自Number.prototype,所有Number实例都有以下方法:

3.1 Number.prototype.toExponential() - 数字的指数表示形式

numObj.toExponential(fractionDigits)

以指数形式(科学计数法)的字符串来表示Number对象,fractionDigits参数用于指定小数位。

var numObj=77.1234;

console.log(toExponential()); //输出 7.71234e+1

console.log(numObj.toExponential(4)); //输出 7.7123e+1

console.log(numObj.toExponential(2)); //输出 7.71e+1

3.2 Number.prototype.toFixed() - 转换为指定小数位的字符串

numObj.toFixed([digits])

toFixed()可以把Number四舍五入为指定小数位数的数字字符串。

3.3 Number.prototype.toLocaleString() - 转换为本地形式的字符串

numObj.toLocaleString([locales [, options]])

该方法继承自Object.prototype.toLocaleString()用于把一个数字转换为字符串的本地表示形式。

3.4 Number.prototype.toPrecision() - 转换为指定精度的字符串

numObj.toPrecision(precision)

将数字转为一个具有指定精度的字符串

3.5 Number.prototype.toString() - 转换为字符串

numObj.toString([radix])

该方法继承自Object.prototype.toString(),用于返回Number的字符串表示形式,radix表示转换基数,可选值为2~36,默认为10

3.6 Number.prototype.valueOf() - 返回原始值

numObj.valueOf()

该方法继承自Object.prototype.valueOf(),用于返回Number对象的原始值,该方法通常会在JavaScript内部隐式调用。

var numObj=new Number(10);

console.log(typeof numObj); // object

var num=numObj.valueOf();

console.log(num); // 10

console.log(typeof num); // number

题一览

  1. 如何判断一个值是否为NaN?运行环境内建的方法isNaN()有坑
  2. 如何判断两个浮点数相等?如fn(0.1+0.2 , 0.3)=> { /*返回true*/}
  3. 如何检测一个值是否整数?
  4. 对于一个数字进行取整,你能说出多少种方法?
  5. 当一个变量显式类型转换时(利用Number()方法),遵循的规则是什么?
  6. Number([])和Number([1,2,3])的值分别是什么?说明其原理?
  7. 讲一讲parseInt()方法遵循的运算规则?

问题解答

1.如何判断一个变量是否为NaN?

相信大多数人应该都会想到这个不就是用运行环境提供的内建方法 isNaN()来判断吗?

如下代码:

isNaN(1); //false 
isNaN("666"); //false, 恩,字符串666确实不是NaN
isNaN(5*"abc"); //true,恩,5*字符串abc得到的结果确实是NaN

isNaN('what?'); //true, 啊?!! 这不并不是我想要的

事实上,isNaN的逻辑是“输入参数是否不是NaN,也不是数字”。这句话我忘记在哪看过啦,我理解isNaN()的逻辑可以理解为“输入参数是否可以转化为数字”更加贴切和容易理解。所以字符串“666”的返回值为false,因为它可以转化为数字,而字符串“what?”不能转换为数字,故返回值为false。

那既然无法用isNaN来检测一个值是否为NaN,那么该如何做?

有两种办法

第一种,根据上面的实验,我们可以先判断输入参数的类型是否为number,再调用isNaN方法,这样就避免了对于非数字类型的判断错误。

代码如下:

if(!Number.isNaN){
  Number.isNaN=function(n){
    return (
    	typeof n==='number' && window.isNaN(n)
    )
	}
}

Number.isNaN(5*'abc'); //true
Number.isNaN('what?'); //false

第二种,利用NaN的一个特性,它是JS语言中唯一一个不等于它本身的值,所以我们也可以这么写

if(!Number.isNaN){
  Number.isNaN=function(n){
  	return n !==n;
	}
}

Number.isNaN(5*'abc'); //true
Number.isNaN('what?'); //false

还有一种,可以利用ES6中提供的Object.is()方法来进行验证

Object.is(5*'abc', NaN); //true
Object.is('what?', NaN); //false

如果你的代码中仍然使用isNaN(),那么你的程序迟早会出现BUG

2.如何判断两个浮点数相等?

在JavaScript中,0.1+0.2 不等于0.3是一个经典问题,他时刻提醒你,对于浮点数来说,他并不能像普通数学题那样简单比较。究其原因,是因为在JS中,0.1+0.2的值是一个比较接近0.30000000000000004的数字,所以他并不等于0.3。

不要小看这个问题,浮点数的运算经常会出现,比如计算商品的折扣、计算税费等情况下都需要对浮点数进行运算。

通常的做法是设置一个误差范围值,通常称为“机器密度”,对于JavaScript来说,这个值是2的-52次幂,即Math.pow(2, -52)。

所以,可以对于浮点数进行比较时可以用下面的方法(在ES6中,Number.EPSILON是自带的),以下代码示例来源于网络

if(!Number.EPSILON){
Number.EPSILON=Math.pow(2, -52);}

function numbersCloseEnoughToEqual(n1, n2){
return Math.abs(n1 - n2) < Number.EPSILON;}

numbersCloseEnoughToEqual(0.1+0.2, 0.3); //true

此外,需要说明的是JavaScript中最大的浮点数是Number.MAX_VALUENumber.MIN_VALUE。

3.如何检测一个值是否整数

如果允许使用ES6的话,可以用Number.isInterger();这个方法干净利落。

Number.isInterger(1.000); //true
Number.isInterger(1); //true
Number.isInterger('1'); //false

如果不允许使用ES6的话,可以自行写一个pollyFill方法。

if(!Number.isInterger){
	Number.isInterger=function(num){
		return (typeof num==='number') && num%1===0;
	}
}

4.对于一个数字进行取整,你能说出多少种方法?

parseInt()这个方法你肯定能想到。但你可能想不到他的坑还真不少,未必是无懈可击的方法。

这里先卖个关子在最后一个问题中,我在详细解答。

其实还有很多很简单有效的方法来对数字进行取整。

比如下面的方法:

8.84|0; //8
~~8.84; //8
8.84>>0; //8

这三种方法都是可以的,分别说一下:

8.84|0 或者 写成 0|8.84 都是一样的,从语法上看,它是让0与指定值进行按位“或”运算,在JavaScript中,它先对指定值执行了ToInt32的转换,在按位进行或运算,所以最终结果就是把指定值转换为32位的整数。

而~~8.84也是对变量进行ToInt32的转换;再进行一步按位“取非”运算,即对每个字节进行反转;然后,再对结果再次“取非”。

那么8.84>>0的操作就同理可证了……

但是,上面的三种方法也是有其局限性的,因为他们是遵循ToInt32的转化规范,所以他们也只能对于32位的数字进行转换,所以再加上一个符号位,那么他们所能处理的数字范围在2的正负31次幂之间,即-2147483648 ≤ x ≤ 2147483647。

5.当一个变量显式类型转换时(利用Number()方法),遵循的规则是什么?

这个问题应该会有很多种问法,比如,把一个字符串转换为数字时,都经历了哪些操作?

这道题还是很考验基础的,一般工程师是不会记住这个细节点的。

言归正传,ES5规范中规定了这个抽象操作ToNumber。

对于布尔型:true的结果为1,false的结果为0;

对于undefined: 结果为NaN

对于null:结果为0

对于字符串类型:遵循数字常量的相关规则和语法。处理失败时会返回NaN。

对于复杂类型:会先调用该值的valueOf()方法,如果有并且返回基本类型值,就是用该值进行强制类型转换。如果没有就是使用toString()的返回来进行强制类型转换。

举个栗子来加强一下记忆:

var test1={
	valueOf: function(){
		return 10; //valueOf方法的将被调用;
	},
test2={
	toString: function(){
		return 666;
	}
}

Number(test1) ; //10
2*test1; //20
Number(test2); //666
Number(test2)/2; //333

6.Number([])和Number([1,2,3])的值分别是什么?说明其原理?

这道题应该也算是上一道题的加强记忆了。

大家已经知道了是先调用valueOf(),再调用toString()方法,那么空数组和[1,2,3]有什么区别呢?

因为数字的valueOf()方法返回的是数组本身,不是一个基本类型,所以还会调用toString()方法;而数组的toString()方法返回的是数组各项通过逗号拼接一起的字符串(可以理解调用了Array.prototype.join(",")方法),所以空数组返回空字符串,转换为数组自然就是0;而数组[1,2,3]则只能转换为NaN了.

那么,大家觉得下面的代码应该输出什么呢?为什么?

Number([100]); //???

7.聊一聊parseInt()方法遵循的运算规则?

之前已经提到了,parseInt()方法含有太多坑。也许面试者会问你下面的代码为什么可以输出52

parseInt('52px'); //52

如果想回答上面的问题,你必须知道下面的知识点。

parseInt(string, radix);方法的接受两个参数:

  • string:

要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用toString 抽象操作)。字符串开头的空白符将会被忽略。

  • radix:

一个介于2和36之间的整数(数学系统的基础),表示上述字符串的基数。比如参数"10"表示使用我们通常使用的十进制数值系统。始终指定此参数可以消除阅读该代码时的困惑并且保证转换结果可预测。当未指定基数时,不同的实现会产生不同的结果,通常将值默认为10

返回值:

返回解析后的整数值。 如果被解析参数的第一个字符无法被转化成数值类型,则返回 NaN

如果 parseInt 遇到了不属于radix参数所指定的基数中的字符那么该字符和其后的字符都将被忽略。接着返回已经解析的整数部分。

所以,这里就明白为什么字符串'52px'会被parseInt()解析为52,因为没有传递第二个参数radix,所以默认按照10进制进行解析,而字符'p'不在10进制内,所以字符'p'和后面的字符全部被忽略,直接返回数字52.

下面是parseInt()最经典的一个

parseInt(1/0, 19); //18

如果不亲自一试,你绝不会相信上面代码的输出是18。

这里需要知道的是,1/0运算结果是“无穷”,在JavaScript中为Infinity,而这个Infinity转换为字符串则为'Infinity',第一个字符是'I',在以19为基数时他的值为18。第二个字符‘n’不是一个有效的数字字符,所以除第一个字符外,后面的字符全部被忽略,所以最后就返回了18。