iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 4
0

這個章節主要是介紹各種 “值” 在使用時,需要注意的地方。

Tony 覺得主要的重點在

(上)

  • 陣列可以給他字串的 key,但不算在陣列的長度中。
  • 陣列是可變的,字串是不可變的。
  • number 都是浮點數。

(下)

  • 小數的計算要小心。
  • 非數值的定義和判斷 NaN, -0, Infinity。
  • call by value VS. call by referance。

陣列

與強型別的語言比較,JS的陣列只是容器。

var a = [1, "2" ,[3]];
a.lenght; // 3

a[0]; // 1
a[2][0]; // 3 都是取值的方法

不需要預設陣列的大小。宣告後,就可以新增 array 需要的值。

var a = [];
a[0] = 1;
a[1] = "2";
a[2] = [3];
a; // [1, "2", [3]];

但如果宣告的是稀疏(sparse)陣列,也就是缺了一格。她雖然會顯示 undefined,但不是真的 undefined。

var a = [];
a[0] = 1;
a[2] = [3];

a[1]; // undefined
a; //(3) [1, empty, Array(1)] 是 empty!

array 是用數值當索引,但他同時也是物件。
(所以他可以讓陣列多一個屬性,造成可以設 key 的假象。本身不算在 .length 之下。)

var a = [];

a[0] = 1;
a["foobar"] = 2;
a; // [1, foobar: 2]

a.length; //1
a["foobar"]; //2
a.foobar; //2

有趣的是,如果把數字的字串當引數用,會被強制轉型喔!

var a = [];
a["13"] = 1;
a.length; // 14

綜合以上,新增 key/value pair,請用物件別用陣列。

類陣列(Array-Likes)

有時候會需要將類陣列的值,轉換成真正的陣列,藉由索引來遍歷。類陣列可能是,各種形式的串列(lists)或字串。

轉換串列成陣列的兩種方法。

  1. 用 slice
function foo() {
    var arr = Array.prototype.slice.call(arguments);
    arr.push("bam");
    console.log( arr );
}

foo( "bar", "baz"); // ["bar", "baz", "bam"]
  1. Array.form() ES6新增方法。
var arr = Array.form( arguments );
  1. 補充:[...arrayLike]
[..."abc"]; // (3) ["a","b","c"]

字串

JavaScript 的 String 實際上不等同字元所組成的陣列。

JS 更嚴格,陣列是可以隨意變更內容,字串是不可變的(immutable)。

var a = "foo";
var b = ["f","o","o"];

a[1] = "O";
b[1] = "O";

a; // "foo";
b; // ["f", "O", "o"];

a[1],在舊 IE 版本不能用,現在都可以用了。但比較正確的讀取是 a.charAt(1)。

因為字串不可變,如何變更? JS 會建立一個新的字串。

c = a.toUpperCase();
c === a; // false
a; // "foo"
c; // "FOO"

所以,string 會藉由使用 array 的方法作轉換。

a.join; // undefined

var c = Array.prototype.join.call( a, "-");

c; // "f-o-o"

但是,如果 array 的方法,會改變原始的 array。就不適用。
因為 string 是不可變 ( immutable ) 的。

a.reverse; // undefined;

var b = ["f","o","o"];
b.reverse(); // ["o", "o", "f"]
b;           // ["o", "o", "f"]

這時如果將 string 轉成可變的 array,就會使一切變可能。

var c = a.split("").reverse().join("");
c; // "oof"

.split(""),會將 string 拆解成 array。.reverse() 反轉後,再用 .join("") 組合成字串。

綜合以上,如果字串很常做運算,請存成 array,需要顯示時加上 join 即可。

數字

JavaScript 只有一個數值型別:number。這個型別包含了,整數(integer) 和 帶小數點的十進位數(fractional decimal numbers)。

JS 沒有真正的整數。因為 42 與 42.0 對 JS 來說都是整數,他們都是沒有小數點的十進位數。

JS 實作用的是 IEEE 754 標準。其中一項雙精度格式,搭配將二進位浮點數存到記憶體的方法,就實現了所有的 number 都是 十進位值。

參考資料

數值語法

以下都是能成立的。

var a = 42;
var b = 42.3;
var c = 0.42;
var d = .42;
var e = 42.0;
var f = 42.; // 沒人在用,但是語法有效。

非常大或非常小的值,會以科學記號來呈現。

var a = 5E10;
a;                 // 50000000000
a.toExponential(); // "5e+10"

var b = a*a;
b;                 // 2.5e+21

var c = 1/a;
c;                 // 2e-11

number 可用 Number 物件包裹器來封裝,可以取用 Number.prototype 內建的方法。
(之後介紹 prototype 和物件,請再回想這裡發生的事)

.toFixed()

可決定顯示 number 小數點後的位數。

var a = 42.5;

a.toFixed(-1); //uncaught error
a.toFixed(0);  // "43"
a.toFixed(1);  // "42.5"
a.toFixed(2);  // "42.50"
.toPrecision()

可決定要顯示的位數。
不同於 .toFixed(),他的起始位置是從整個 number 開始計算。

var a = 42.5;

a.toPrecision(0); // uncaught error
a.toPrecision(1); // "4e+1"
a.toPrecision(2); // "43"
a.toPrecision(3); // "42.5"
a.toPrecision(4); // "42.50"

兩個方法都可以單行完成。

(42).toFixed(3);     // "42.000"
0.42.toPrecision(3); // "0.42"
42..toFixed(3);      // "42.000"
42 .toFixed(3);      // "42.000" 請避免留空格做法。

42.toFixed(3);       // SyntaxError

因為小數點會被先解讀為字面值,也就是 42. 的number。取用 toFixed(3) 方法的 .消失而造成錯誤。

不管哪個,直接用方法取用數值來顯示都是很少見的,是說也不代表好壞。


數值也可以用 16 進位,和 8 進位表示。

0xf3; // 16進位的243
0Xf3; // 同上

0o363; // 8進位的 243
0O363; // 同上,但請別把 O 放在 0 旁邊。

0b11110011; // 2進位的 243
0B11110011; // 同上

雖然都是會過的語法,但請都用小寫比較容易閱讀。

結尾了!

整個第五章打下來有 8xxx 多個字,標記和標點符號都算在內。
我打得很開心,希望你看的也很開心(咦?)。(第七章的量超多。)
源源不絕的知識正在灌進來啊!(加油~)

明天見。

參考資料

  1. JavaScript如何判断参数为浮点型
  2. 你所不知道的 JS

上一篇
Day3 - 型別
下一篇
Day5 - 值(下)
系列文
你為什麼不問問神奇 JavaScript 呢?30

尚未有邦友留言

立即登入留言