JQuery Data方法的一個(gè)小特技
通常我們?cè)谟?JavaScript 操作 DOM 元素的時(shí)候會(huì)往 DOM 上臨時(shí)添加一些參數(shù),用來記住一些狀態(tài),或者從后端取參數(shù)值等。
一般通過在 HTML 標(biāo)簽上添加自定義屬性來實(shí)現(xiàn),但是這樣會(huì)不可避免的訪問 DOM,性能上并不好。如果你使用 jQuery 的話建議使用 $el.data() 方法來取元素上 data-* 的值,比如:
- <div id="demo" data-key="value"></div>
- <script>
- $('#demo').attr('data-key')
- $('#demo').data('key') // ***次訪問 DOM,以后從緩存取
- </script>
這兩個(gè)方法的區(qū)別在于 attr 每次都會(huì)直接訪問 DOM 元素,而 data 方法會(huì)緩存***次的查找,后續(xù)調(diào)用不需要訪問 DOM。
很明顯建議使用后者,但是在 低版本的 jQuery 中默認(rèn)會(huì)對(duì) data 方法取到的值進(jìn)行粗暴的強(qiáng)制數(shù)據(jù)類型轉(zhuǎn)換「parseFloat」。看下面代碼:
- <div id="demo0" data-key="abc">字符串</div>
- <div id="demo1" data-key="123">數(shù)字</div>
- <div id="demo2" data-key="123e456">科學(xué)計(jì)數(shù)法</div>
- <div id="demo3" data-key="0000123">八進(jìn)制數(shù)字</div>
- <script src="jquery-1.6.4"></script>
- <script>
- $('#demo0').data('key') // "abc"
- $('#demo1').data('key') // 123
- $('#demo2').data('key') // Infinity
- $('#demo3').data('key') // 83
- </script>
后面兩種顯然出錯(cuò)了,就是因?yàn)?jQuery 對(duì)屬性值進(jìn)行了強(qiáng)制 parseFloat 操作。這種轉(zhuǎn)換是方便了使用者,如果是數(shù)字的話我們?nèi)〉竭@個(gè)值進(jìn)行計(jì)算什么的就不用再轉(zhuǎn)數(shù)據(jù)類型了,但是一不小心就會(huì)出 bug
發(fā)現(xiàn)這個(gè) bug 的時(shí)候***感覺是 jQuery 不應(yīng)該沒考慮到這一點(diǎn)呀。后來果斷去查了下***版的 jQuery 源代碼,發(fā)現(xiàn)已經(jīng)修復(fù)了。核心代碼在 data.js 35 行,如下
- function getData( data ) {
- if ( data === "true" ) {
- return true;
- }
- if ( data === "false" ) {
- return false;
- }
- if ( data === "null" ) {
- return null;
- }
- // Only convert to a number if it doesn't change the string
- // 重點(diǎn)就在這里 →_→
- if ( data === +data + "" ) {
- return +data;
- }
- if ( rbrace.test( data ) ) {
- return JSON.parse( data );
- }
- return data;
- }
getData 方法就返回了節(jié)點(diǎn)屬性的值,只不過加了一些特殊處理使得我們?nèi)〉搅藳]有 bug 的值,關(guān)鍵地方就在這里: data === +data + "" 。這行代碼做了些什么神奇的事情
將節(jié)點(diǎn)的屬性值強(qiáng)制轉(zhuǎn)換成數(shù)字「+data」后再轉(zhuǎn)成字符串「+ ““」,如果轉(zhuǎn)換后的值與原來相等就取轉(zhuǎn)換后的值
可以簡(jiǎn)單的這么理解:jQuery 會(huì)嘗試轉(zhuǎn)換數(shù)據(jù)類型,如果轉(zhuǎn)換后和轉(zhuǎn)換前的 長(zhǎng)得一樣 那么 jQuery 就認(rèn)為它是需要被轉(zhuǎn)換成數(shù)字的。這樣就可以***規(guī)避上面例子中的兩種問題,我們來測(cè)試一下:
- var data = 'abc'
- console.log(data === +data + "") // false 不轉(zhuǎn)換,直接返回字符串原值
- var data = '123'
- console.log(data === +data + "") // true 轉(zhuǎn)換,使用轉(zhuǎn)換后的數(shù)字類型值
- var data = '123e456'
- console.log(data === +data + "") // false 不轉(zhuǎn)換,直接返回字符串原值
- var data = '0000123'
- console.log(data === +data + "") // false 不轉(zhuǎn)換,直接返回字符串原值
【本文是51CTO專欄作者周琪力的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)注明出處】