關於js中的值

笑口常開發表於2017-10-11
  1. 陣列

    1. 在 JavaScript 中,陣列可以容納任何型別的值
    2. 陣列宣告後即可向其中加入值,不需要預先設定大小
    3. 可以用delete從陣列中刪除元素,但是這不會改變陣列的長度length
    4. delete陣列中的一個元素會將該位置的值就成了undeclared的,雖然可能在某些瀏覽器中顯示為undefined(親測在chrome中是"empty"),而且在使用陣列的遍歷方法是不能遍歷到這些已經被刪除的元素的
    5. 陣列通過數字進行索引,但有趣的是它們也是物件,所以也可以包含字串鍵值和屬性(但這些並不計算在陣列長度內)
    6. 如果字串鍵值能夠被強制型別轉換為十進位制數字的話,它就會被當作數字索引來處理。eg: var a = [] a["13"] = 1; a.length; // 14
    7. 雖然陣列中可以存放鍵值對,但是更加推薦的方式是使用陣列儲存數字索引值,使用物件來儲存鍵值對
  2. 類陣列

    1. 有時需要將類陣列(一組通過數字索引的值)轉換為真正的陣列,這一般通過陣列工具函式(如 indexOf(..)、concat(..)、forEach(..) 等)來實現。
    2. 通過 arguments 物件(類陣列)將函式的引數當作列表來訪問(從 ES6 開始已廢止) function foo() { var arr = Array.prototype.slice.call( arguments ); arr.push( "bam" ); console.log( arr ); } foo( "bar", "baz" ); // ["bar","baz","bam"]
    3. ES6內建的Array.from()可以實現同樣的功能
  3. 字串

    1. 字串和陣列的確很相似,它們都是類陣列,都有 length 屬性以及 indexOf(..)(從 ES5 開始陣列支援此方法)和 concat(..) 方法:
    2. JavaScript 中字串是不可變的,而陣列是可變的,老版本的IE不支援通過str[1]的方式來訪問字串中某個字元,但始終可以通過str.charAt(1)的方式來訪問
    3. 許多陣列函式用來處理字串很方便。雖然字串沒有這些函式,但可以通過“借用”陣列的非變更方法來處理字串(利用call和apply)等方式,能借用的前提應該是陣列不是在其本身修改,而是建立一個副本吧,畢竟字串是不可變的。
    4. 陣列有一個字串沒有的可變更成員函式 reverse(),但是這個方法字串不能借用,原因和上面說的一樣,由於字串的不變性
  4. 數字 JavaScript 只有一種數值型別:number(數字),Javascript中沒有真正意義上的整數

    1. 預設情況下大部分數字都以十進位制顯示,小數部分最後面的 0 被省略
    2. 特別大和特別小的數字以指數形式表示, 和toExponential()的結果相同,eg: var a = 5E10; a; //50000000000 a.toExponential(); // 5e+10 var b = a * a; b; //2.5e+21 var c = 1 / a; c; 2e-11
    3. 由於數字值可以使用 Number 物件進行封裝,因此數字值可以呼叫 Number.prototype 中的方法,例如toFixed(), toPrecision()
    4. .運算子會被優先識別為數字常量的一部分,然後才是物件屬性訪問運算子,所以: 42.toFixed(3); // SyntaxError, 因為'.'被優先識別為數字常量42的一部分 42..toFixed(3); // 42.000 0.42.toFixed(3); // 0.420 (42).toFixed(3); //42.000 42 .toFixed(3); // 42.000 空格隔了一下,說明'.'不是數字常量的一部分
    5. 數字除了可以使用指數,十進位制進行表示外,還可以使用:
      1. 0xf3 // 243的16進位制
      2. 0363// 243的8進位制
    6. 從ES6開始,嚴格模式不再支援0363八進位制格式, 在ES6中應該使用0o363或者0O363, 但為了好辨認,無論八進位制還是十六進位制或者二進位制等,統一使用小寫:0o363, 0xf3, 0b11110011

    較小的數值

    0.1 + 0.2 == 0.3 // false
    如何判斷0.2和0.3是否相等呢?
    最常見的方法是設定一個誤差範圍值,通常稱為機器精度,在js中這個值是2^-52,在ES6中,可以使用Number.EPSILON來表示這個機器精度
    能夠呈現的最大浮點數: Number.MAX_VALUE,最小的是Number.MIN_VALUE, 它不是負數,但是無限接近於0
    能夠被安全呈現的最大值是2^53 - 1, 即是`Number.MAX_SAFE_INTEGER`, 最小整數是`Number.MIN_SAFE_INTEGER`
    

    整數檢測

    1. isInteger()
    2. isSafeInteger()
    

    32位有符號整數

    1. a | 0 可以將變數 a 中的數值轉換為 32 位有符號整數,因為數位運算子 | 只適用於 32 位整數(js中原來還有這些東西!!!)
    

    不是值的值

        undefined 和 null 常被用來表示“空的”值或“不是值”的值
        `undefined`, `null`
    1. ES5之前,可以給undefined賦值,但是目前給undefined賦值會隱式失敗
    2. void運算子 可返回undefined這個值, 按照慣例我們使用`void 0`來獲取undefined這個值
    

    特殊的數字

    1. 不是數字的數字
        1. NaN 是一個“警戒值”(sentinel value,有特殊用途的常規值),用於指出數字型別中的錯誤情況,即“執行數學運算沒有成功,這是失敗後返回的結果”
        2. NaN是唯一一個非自反的值(即是 x===x不成立),可利用這一點判斷一個值是否是NaN,當然也可以使用全域性函式isNaN()來判斷,但是這個函式是有bug的,它的檢測方式是: 判斷引數是否"如果引數不是真實數字(或者不能轉換為數字)就返回true, 如果是數字了才返回false", eg:
    
    
    
    ```
        var a = 3, b = '3', c='3a', d=NaN
        window.isNaN(a); // false
        window.isNaN(b); // false
        window.isNaN(c); // true
        window.isNaN(d); // true
    ```
     ES6中引入了`Number.isNaN()`,這個函式是正常的
    
    2. 無窮數 1. JavaScript 使用有限數字表示法,所以和純粹的數學運算不同,JavaScript 的運算結果有可能溢位,此時結果為 Infinity 或者 -Infinity。eg: ``` var a = Number.MAX_VALUE; a + a; // infinity a + Math.pow(2, 970); // Infinity a + Math.pow(2, 969); // 1.7976931348623157e+308 ```, 2. 然後我又繼續延伸了一下:
    ```var a = Number.MAX_VALUE;
        a + Math.pow(2, 969) === a; // true
    ```
    原因個人認為是Math.pow(2, 969) 遠遠小於 a, 而js是不能精確表示資料的,又由於Math.pow(2, 969)對a的影響可以忽略不計,所以是否加Math.pow(2, 969)可以認為沒加,類似於0.3-0.2 != 0.1
    3. 後面看到了解釋:
    >    如果數學運算(如加法)的結果超出處理範圍,則由 IEEE 754 規範中的“就近取整”(round-to-nearest)模式來決定最後的結果。例如,相對於 Infinity,Number.MAX_VALUE + Math.pow(2, 969) 與 Number.MAX_VALUE 更為接近,因此它被“向下取整”(round down);而 Number.MAX_VALUE + Math.pow(2, 970) 與 Infinity 更為接近,所以它被“向上取整”
    
    3. 零值 js中,同時存在+0和-0, 數字的符號位(sign)用來代表其他資訊(比如移動的方向)。此時如果一個值為 0 的變數失去了它的符號位,它的方向資訊就會丟失。所以保留 0 值的符號位可以防止這類情況發生。-0轉換為字串會丟失負號資訊,但是從字串轉換為數字是會保留符號資訊的 ```var a = -0, b = '-0'; a.toString(); // 0 Number(b); // -0 JSON.parse(b); // -0 ``` 除此之外,在各種比較中,0和-0應該都是一樣的內容 4. 特殊內容 ES6中新加入了一個`Object.is()`方法用來判斷兩個值是否絕對相等, 該方法的polyfill程式碼: ```if(!Object.is){ Object.is = function(v1, v2){ if(v1===0 && v2===0){ return 1/v1 === 1/v2; }else if(v1 !== v1){ return v2 !== v2; } return v1 === v2; } } ```

    值和引用

    在 JavaScript 中變數不可能成為指向另一個變數的引用。 JavaScript 引用指向的是值。如果一個值有 10 個引用,這些引用指向的都是同一個值,它們相互之間沒有引用 / 指向關係。 簡單值(即標量基本型別值)總是通過值複製的方式來賦值 / 傳遞 複合值(compound value)——物件(包括陣列和封裝物件,參見第 3 章)和函式,則總是通過引用複製的方式來賦值 / 傳遞。 由於引用指向的是值本身而非變數,所以一個引用無法更改另一個引用的指向。 我們無法自行決定使用值複製還是引用複製,一切由值的型別來決定。 如果我們想通過值賦值的方式傳遞陣列,就要為其建立一個副本,這樣傳遞的就不再是原始值, foo(arr.slice()) 如果想將標量基本型別值傳遞到函式內進行更改,就要將其封裝成一個複合值,然後傳遞該複合值 var a = 2, b = new Number(2); function foo(x){ x = x + 1; console.log(x); } foo(b); console.log(b); // 2, 想想為什麼?

相關文章