249建站之家:JavaScript 有用的代码片段和 trick

浮点数取整


const

 x = 

123.4545

;

x >> 

0

// 123

~~x; 

// 123

x | 

0

// 123

Math

.floor(x); 

// 123

注意:前三种方法只适用于32个位整数,对于负数的处理上和 Math.floor是不同的。

Math

.floor(-

12.53

); 

// -13

-

12.53

 | 

0

// -12

生成6位数字验证码


// 方法一

(

'000000'

 + 

Math

.floor(

Math

.random() *  

999999

)).slice(-

6

);

// 方法二

Math

.random().toString().slice(-

6

);

// 方法三

Math

.random().toFixed(

6

).slice(-

6

);

// 方法四

''

 + 

Math

.floor(

Math

.random() * 

999999

);

16进制颜色代码生成


(

function

() {

  

return

 

'#'

+(

'00000'

+

    (

Math

.random()*

0x1000000

<<

0

).toString(

16

)).slice(-

6

);

})();

驼峰命名转下划线


'componentMapModelRegistry'

.match(

/^[a-z][a-z0-9]+|[A-Z][a-z0-9]*/

g).join(

'_'

).toLowerCase(); 

// component_map_model_registry

url查询参数转json格式


// ES6

const

 query = (search = 

''

) => ((querystring = 

''

) => (q => (querystring.split(

'&'

).forEach(item => (kv => kv[

0

] && (q[kv[

0

]] = kv[

1

]))(item.split(

'='

))), q))({}))(search.split(

'?'

)[

1

]);

// 对应ES5实现

var

 query = 

function

(search) {

  

if

 (search === 

void

 

0

) { search = 

''

; }

  

return

 (

function

(querystring) {

    

if

 (querystring === 

void

 

0

) { querystring = 

''

; }

    

return

 (

function

(q) {

      

return

 (querystring.split(

'&'

).forEach(

function

(item) {

        

return

 (

function

(kv) {

          

return

 kv[

0

] && (q[kv[

0

]] = kv[

1

]);

        })(item.split(

'='

));

      }), q);

    })({});

  })(search.split(

'?'

)[

1

]);

};

query(

'?key1=value1&key2=value2'

); 

// es6.html:14 {key1: "value1", key2: "value2"}

获取URL参数


function

 getQueryString(key){

  

var

 reg = 

new

 

RegExp

(

"(^|&)"

+ key +

"=([^&]*)(&|$)"

);

  

var

 r = window.location.search.substr(

1

).match(reg);

  

if

(r!=

null

){

      

return

  unescape(r[

2

]);

  }

  

return

 

null

;

}

n维数组展开成一维数组


var

 foo = [

1

, [

2

3

], [

'4'

5

, [

'6'

,

7

,[

8

]]], [

9

], 

10

];

// 方法一

// 限制:数组项不能出现`,`,同时数组项全部变成了字符数字

foo.toString().split(

','

); 

// ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]

// 方法二

// 转换后数组项全部变成数字了

eval

(

'['

 + foo + 

']'

); 

// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// 方法三,使用ES6展开操作符

// 写法太过麻烦,太过死板

[

1

, ...[

2

3

], ...[

'4'

5

, ...[

'6'

,

7

,...[

8

]]], ...[

9

], 

10

]; 

// [1, 2, 3, "4", 5, "6", 7, 8, 9, 10]

// 方法四

JSON.parse(`[${JSON.stringify(foo).replace(

/\[|]/

g, 

''

)}]`); 

// [1, 2, 3, "4", 5, "6", 7, 8, 9, 10]

// 方法五

const

 flatten = (ary) => ary.reduce((a, b) => a.concat(

Array

.isArray(b) ? flatten(b) : b), []);

flatten(foo); 

// [1, 2, 3, "4", 5, "6", 7, 8, 9, 10]

// 方法六

function

 flatten(a) {

  

return

 

Array

.isArray(a) ? [].concat(...a.map(flatten)) : a;

}

flatten(foo); 

// [1, 2, 3, "4", 5, "6", 7, 8, 9, 10]

注:更多方法请参考《How to flatten nested array in JavaScript?》

日期格式化


// 方法一

function

 format1(x, y) {

  

var

 z = {

    y: x.getFullYear(),

    M: x.getMonth() + 

1

,

    d: x.getDate(),

    h: x.getHours(),

    m: x.getMinutes(),

    s: x.getSeconds()

  };

  

return

 y.replace(

/(y+|M+|d+|h+|m+|s+)/

g, 

function

(v) {

    

return

 ((v.length > 

1

 ? 

"0"

 : 

""

) + 

eval

(

'z.'

 + v.slice(-

1

))).slice(-(v.length > 

2

 ? v.length : 

2

))

  });

}

format1(

new

 

Date

(), 

'yy-M-d h:m:s'

); 

// 17-10-14 22:14:41

// 方法二

Date

.prototype.format = 

function

 (fmt) { 

  

var

 o = {

    

"M+"

this

.getMonth() + 

1

//月份 

    

"d+"

this

.getDate(), 

//日 

    

"h+"

this

.getHours(), 

//小时 

    

"m+"

this

.getMinutes(), 

//分 

    

"s+"

this

.getSeconds(), 

//秒 

    

"q+"

Math

.floor((

this

.getMonth() + 

3

) / 

3

), 

//季度 

    

"S"

this

.getMilliseconds() 

//毫秒 

  };

  

if

 (

/(y+)/

.test(fmt)){

    fmt = fmt.replace(

RegExp

.$1, (

this

.getFullYear() + 

""

).substr(

4

 - 

RegExp

.$1.length));

  } 

  

for

 (

var

 k in o){

    

if

 (

new

 

RegExp

(

"("

 + k + 

")"

).test(fmt)){

      fmt = fmt.replace(

RegExp

.$1, (

RegExp

.$1.length == 

1

) ? (o[k]) : ((

"00"

 + o[k]).substr((

""

 + o[k]).length)));

    }

  }     

  

return

 fmt;

}

new

 

Date

().format(

'yy-M-d h:m:s'

); 

// 17-10-14 22:18:17

统计文字个数


function

 wordCount(data) {

  

var

 pattern = 

/[a-zA-Z0-9_\u0392-\u03c9]+|[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af]+/

g;

  

var

 m = data.match(pattern);

  

var

 count = 

0

;

  

if

( m === 

null

 ) 

return

 count;

  

for

 (

var

 i = 

0

; i < m.length; i++) {

    

if

 (m[i].charCodeAt(

0

) >= 

0x4E00

) {

      count += m[i].length;

    } 

else

 {

      count += 

1

;

    }

  }

  

return

 count;

}

var

 text = 

'贷款买房,也意味着你能给自己的资产加杠杆,能够撬动更多的钱,来孳生更多的财务性收入。'

;

wordCount(text); 

// 38

特殊字符转义


function

 htmlspecialchars (str) {

  

var

 str = str.toString().replace(

/&/

g, 

"&amp;"

).replace(

/</

g, 

"&lt;"

).replace(

/>/

g, 

"&gt;"

).replace(

/"/

g, 

'&quot;'

);

  

return

 str;

}

htmlspecialchars(

'&jfkds<>'

); 

// "&amp;jfkds&lt;&gt;"

动态插入js


function

 injectScript(src) {

    

var

 s, t;

    s = document.createElement(

'script'

);

    s.type = 

'text/javascript'

;

    s.async = 

true

;

    s.src = src;

    t = document.getElementsByTagName(

'script'

)[

0

];

    t.parentNode.insertBefore(s, t);

}

格式化数量


// 方法一

function

 formatNum (num, n) {

  

if

 (

typeof

 num == 

"number"

) {

    num = 

String

(num.toFixed(n || 

0

));

    

var

 re = 

/(-?\d+)(\d{3})/

;

    

while

 (re.test(num)) num = num.replace(re, 

"$1,$2"

);

    

return

 num;

  }

  

return

 num;

}

formatNum(

2313123

3

); 

// "2,313,123.000"

// 方法二

'2313123'

.replace(

/\B(?=(\d{3})+(?!\d))/

g, 

','

); 

// "2,313,123"

// 方法三

function

 formatNum(str) {

  

return

 str.split(

''

).reverse().reduce((prev, next, index) => {

    

return

 ((index % 

3

) ? next : (next + 

','

)) + prev

  });

}

formatNum(

'2313323'

); 

// "2,313,323"

身份证验证


function

 chechCHNCardId(sNo) {

  

if

 (!

this

.regExpTest(sNo, 

/^[0-9]{17}[X0-9]$/

)) {

    

return

 

false

;

  }

  sNo = sNo.toString();

  

var

 a, b, c;

  a = parseInt(sNo.substr(

0

1

)) * 

7

 + parseInt(sNo.substr(

1

1

)) * 

9

 + parseInt(sNo.substr(

2

1

)) * 

10

;

  a = a + parseInt(sNo.substr(

3

1

)) * 

5

 + parseInt(sNo.substr(

4

1

)) * 

8

 + parseInt(sNo.substr(

5

1

)) * 

4

;

  a = a + parseInt(sNo.substr(

6

1

)) * 

2

 + parseInt(sNo.substr(

7

1

)) * 

1

 + parseInt(sNo.substr(

8

1

)) * 

6

;

  a = a + parseInt(sNo.substr(

9

1

)) * 

3

 + parseInt(sNo.substr(

10

1

)) * 

7

 + parseInt(sNo.substr(

11

1

)) * 

9

;

  a = a + parseInt(sNo.substr(

12

1

)) * 

10

 + parseInt(sNo.substr(

13

1

)) * 

5

 + parseInt(sNo.substr(

14

1

)) * 

8

;

  a = a + parseInt(sNo.substr(

15

1

)) * 

4

 + parseInt(sNo.substr(

16

1

)) * 

2

;

  b = a % 

11

;

  

if

 (b == 

2

) {

    c = sNo.substr(

17

1

).toUpperCase();

  } 

else

 {

    c = parseInt(sNo.substr(

17

1

));

  }

  

switch

 (b) {

    

case

 

0

:

      

if

 (c != 

1

) {

        

return

 

false

;

      }

      

break

;

    

case

 

1

:

      

if

 (c != 

0

) {

        

return

 

false

;

      }

      

break

;

    

case

 

2

:

      

if

 (c != 

"X"

) {

        

return

 

false

;

      }

      

break

;

    

case

 

3

:

      

if

 (c != 

9

) {

        

return

 

false

;

      }

      

break

;

    

case

 

4

:

      

if

 (c != 

8

) {

        

return

 

false

;

      }

      

break

;

    

case

 

5

:

      

if

 (c != 

7

) {

        

return

 

false

;

      }

      

break

;

    

case

 

6

:

      

if

 (c != 

6

) {

        

return

 

false

;

      }

      

break

;

    

case

 

7

:

      

if

 (c != 

5

) {

        

return

 

false

;

      }

      

break

;

    

case

 

8

:

      

if

 (c != 

4

) {

        

return

 

false

;

      }

      

break

;

    

case

 

9

:

      

if

 (c != 

3

) {

        

return

 

false

;

      }

      

break

;

    

case

 

10

:

      

if

 (c != 

2

) {

        

return

 

false

;

      };

  }

  

return

 

true

;

}

测试质数


function

 isPrime(n) {

  

return

 !(

/^.?$|^(..+?)\1+$/

).test(

'1'

.repeat(n))

}

统计字符串中相同字符出现的次数


var

 arr = 

'abcdaabc'

;

var

 info = arr

    .split(

''

)

    .reduce((p, k) => (p[k]++ || (p[k] = 

1

), p), {});

console.log(info); 

//{ a: 3, b: 2, c: 2, d: 1 }

使用 void0来解决 undefined被污染问题


undefined

 = 

1

;

!!

undefined

// true

!!

void

(

0

); 

// false

单行写一个评级组件


"★★★★★☆☆☆☆☆"

.slice(

5

 - rate, 

10

 - rate); 

JavaScript 错误处理的方式的正确姿势


try

 {

    something

catch

 (e) {

    window.location.href =

        

"http://stackoverflow.com/search?q=[js]+"

 +

        e.message;

}

匿名函数自执行写法


function

() {}() );

function

() {} )();

function

() {}() ];

function

() {}();

function

() {}();

function

() {}();

function

() {}();

delete

 

function

() {}();

typeof

 

function

() {}();

void

 

function

() {}();

new

 

function

() {}();

new

 

function

() {};

var

 f = 

function

() {}();

1

function

() {}();

1

 ^ 

function

() {}();

1

 > 

function

() {}();

两个整数交换数值


var

 a = 

20

, b = 

30

;

a ^= b;

b ^= a;

a ^= b;

a; 

// 30

b; 

// 20

数字字符转数字


var

 a = 

'1'

;

+a; 

// 1

最短的代码实现数组去重


[...

new

 

Set

([

1

"1"

2

1

1

3

])]; 

// [1, "1", 2, 3]

用最短的代码实现一个长度为m(6)且值都n(8)的数组


Array

(

6

).fill(

8

); 

// [8, 8, 8, 8, 8, 8]

将argruments对象转换成数组


var

 argArray = 

Array

.prototype.slice.call(arguments);

// ES6:

var

 argArray = 

Array

.from(arguments)

// or

var

 argArray = [...arguments];

获取日期时间缀


// 获取指定时间的时间缀

new

 

Date

().getTime();

(

new

 

Date

()).getTime();

(

new

 

Date

).getTime();

// 获取当前的时间缀

Date

.now();

// 日期显示转换为数字

+

new

 

Date

();

使用 ~x.indexOf('y')来简化 x.indexOf('y')>-1


var

 str = 

'hello world'

;

if

 (str.indexOf(

'lo'

) > -

1

) {

  

// ...

}

if

 (~str.indexOf(

'lo'

)) {

  

// ...

}

parseInt() or Number()


两者的差别之处在于解析和转换两者之间的理解。


解析允许字符串中含有非数字字符,解析按从左到右的顺序,如果遇到非数字字符就停止。而转换不允许出现非数字字符,否者会失败并返回NaN。


var

 a = 

'520'

;

var

 b = 

'520px'

;

Number

(a); 

// 520

parseInt(a); 

// 520

Number

(b); 

// NaN

parseInt(b); 

// 520

parseInt方法第二个参数用于指定转换的基数,ES5默认为10进制。


parseInt(

'10'

2

); 

// 2

parseInt(

'10'

8

); 

// 8

parseInt(

'10'

10

); 

// 10

parseInt(

'10'

16

);  

// 16

对于网上 parseInt(0.0000008)的结果为什么为8,原因在于0.0000008转换成字符为"8e-7",然后根据 parseInt的解析规则自然得到"8"这个结果。


+ 拼接操作,+x or String(x)?


+运算符可用于数字加法,同时也可以用于字符串拼接。如果+的其中一个操作符是字符串(或者通过 隐式强制转换可以得到字符串),则执行字符串拼接;否者执行数字加法。


需要注意的时对于数组而言,不能通过 valueOf()方法得到简单基本类型值,于是转而调用 toString()方法。


[

1

,

2

] + [

3

4

]; 

// "1,23,4"

对于对象同样会先调用 valueOf()方法,然后通过 toString()方法返回对象的字符串表示。


var

 a = {};

a + 

123

// "[object Object]123"

对于 a+""隐式转换和 String(a)显示转换有一个细微的差别: a+''会对a调用 valueOf()方法,而 String()直接调用 toString()方法。大多数情况下我们不会考虑这个问题,除非真遇到。


var

 a  = {

  valueOf: 

function

() { 

return

 

42

; },

  toString: 

function

() { 

return

 

4

; }

}

a + 

''

// 42

String

(a); 

// 4

判断对象的实例


// 方法一: ES3

function

 

Person

(name, age) {

  

if

 (!(

this

 

instanceof

 

Person

)) {

    

return

 

new

 

Person

(name, age);

  }

  

this

.name = name;

  

this

.age = age;

}

// 方法二: ES5

function

 

Person

(name, age) {

  

var

 self = 

this

 

instanceof

 

Person

 ? 

this

 : 

Object

.create(

Person

.prototype);

  self.name = name;

  self.age = age;

  

return

 self;

}

// 方法三:ES6

function

 

Person

(name, age) {

  

if

 (!

new

.target) {

    

throw

 

'Peron must called with new'

;

  }

  

this

.name = name;

  

this

.age = age;

}

数据安全类型检查


// 对象

function

 isObject(value) {

  

return

 

Object

.prototype.toString.call(value).slice(

8

, -

1

) === 

'Object'';

}

// 数组

function isArray(value) {

  return Object.prototype.toString.call(value).slice(8, -1) === '

Array

';

}

// 函数

function isFunction(value) {

  return Object.prototype.toString.call(value).slice(8, -1) === '

Function

';

}

让数字的字面值看起来像对象


2.toString

(); 

// Uncaught SyntaxError: Invalid or unexpected token

2.

.toString(); 

// 第二个点号可以正常解析

2

 .toString(); 

// 注意点号前面的空格

(

2

).toString(); 

// 2先被计算

对象可计算属性名(仅在ES6中)


var

 suffix = 

' name'

;

var

 person = {

  [

'first'

 + suffix]: 

'Nicholas'

,

  [

'last'

 + suffix]: 

'Zakas'

}

person[

'first name'

]; 

// "Nicholas"

person[

'last name'

]; 

// "Zakas"


推荐

  • QQ空间

  • 新浪微博

  • 人人网

  • 豆瓣

取消