Andy:
ES5 語言規範的 section 9 定義了幾種“抽像運算”(僅供內部使用的操作)。我們將特別關注於:ToString、ToNumber、和ToBoolean
document.all:一個由DOM(不是JS引擎本身)給你的JS程序提供的類數組(對象)。它曾經像一個普通對像那樣動作——是一個truthy。但不再是了 QQ。
Jason:
重點就是一個,清楚的知道變數的型別,避免讓js自動幫你轉型,不然會脫離掌握,剩下的都是對工具的熟練度、熟悉度
Tony:
背出 falsy,或寫下 falsy。
書上列的明確轉型,要能夠知道哪些算公認的明確轉型。+ ~ | !! ?:
要使用這些明確轉型,確保你的夥伴都懂這些。
Lai:
如果你試圖字串化一個可能含有非法 JSON 值的物件,或是在那個 object 上放了不適合序列化的值,應該爲此定義一個 toJSON() 方法,回傳該物件的一個 JSON-safe 版本。
日期轉爲數字可以用強制的方式取得。但取得時間有它自己的語法,應該儘量使用它本來的方式取得。
可以利用 ! 強制轉換,但因爲它會反轉,所以開發人員會利用兩個!!
Kai:
ECMAScript 定義了 abstract operatoin
轉型要知道轉型的前後的東西是否是你要的
Chris:
JSON.stringify(a, b, c)
-1 是有意義的
ToNumber 會先 ToPrimitive
Henry
符哨值 -1 是有原因的(~)
true 會被轉成 1,false, null 會是 0,undefined 是 NaN
JSON.stringify 可以傳入三個參數
mango:
toString(),toNumber(),toBoolean()是如何做值轉換
toBoolean()只有五個會回傳false,其他都是true
turtle:
明確與隱含強制轉型對每個人來說定義都不一定一樣,還是需要團隊溝通。
並非所有 物件 都是 truthy
Jimmy:
JSON.stringify()與toJSON()2者間的差異
~~ 逐次元雙次反轉動作非常類似!!的真假值雙次否定
不要對parseInt()傳入非字串的元素,不然會出現奇怪的行為
共筆區域
強制轉型從以前到現在都具有爭議,有些人認為他是 JS 的缺陷,但對於一些怪異的部分,我們應該徹頭徹尾去了解它的優點與缺點。
轉換值
【 強制轉型 】
定義:將一個值從某個型別轉換成另一個型別的動作,如果明確地進行,通常就叫做型別轉換,而如果隱含地進行,就稱為強制轉型。
特徵:在 JavaScript 中強制轉型的結果,永遠都會是純量的基本型別值,像是 String、Number 或 Boolean,而不是 Object、Function 之類的複雜的值。
有關的專有名詞
type casting(type conversion):發生於靜態型別語言的編譯時期。
type coercion:動態語言在執行時期所進行的轉換。
以上多數人通稱為「coercion」。所以區分的方式分為兩種:
明確的強制轉型(explicit coercion):可明顯看出某個型別轉換動作。
隱含的強制轉型(implicit coercion):型別轉換動作是某個刻意進行其他作業所產生的較不明顯的副作用。
var a = 42;
var b = a + “”
// 感覺程式的目的是要做變數與字串的相加合併(或相加?),但他自己另外進行的轉型。
var c = String(a)
// 目的只有一個:就是要轉型。
抽象的值運算
在探討「明確」和「隱含」前,必須先瞭解值如何轉型為某個基本型別值。
ES5 規格的 section 9 定義了幾個抽象運算,並附有值轉換的規則。
現在主要了解 ToString、ToNumber 及 ToBoolean 身上,也可以看一下 ToPrimitive。
ToString
任何非 string 的值被強制轉型為 string 表示值,轉換過程是由 section 9.8 中的 ToString 抽象運算來處理。
ToSting —— ECMAScript Language Specification
字串強制轉型的結果
別值 轉字串結果
null “null”
undefined “undefined”
true “true”
123(一般數字型別) “123”
特殊案例——特大指數
var a = 1.07 * 1000 * 1000 * 1000 ..
// 1.07 乘以 1000 七次(21個零)
a.toString();
//”1.07e+21″
物件
注意:如果一個物件被強制轉型成一個字串,那過程會經過 ToPrimitive 的抽象處理,詳見ECMA 5 section9.1。
ToNumber 後面會講,現在先跳過。
補充說明
陣列
陣列轉字串,會先將陣列的值字串化後,再以,連接各個值。
toString 可以被明確地被呼叫,或是當一個不是字串的值被用在字串的情境中,他就會被自動呼叫。
Array 本身有 toString 依照 prototype toString 的方法會覆蓋物件的toString。
JSON 字串化
使用 JSON.stringify(..),他會將一個值序列化為一個 JSON 相容的字串。這種序列化和強制轉型不完全相同,但它和 ToString 規則有關連,所以稍微說一下。
JSON.stringify( 42 ); // “42”
JSON.stringify( “42” ); // “”42″” (一个包含雙引號的字串)
JSON.stringify( null ); // “null”
JSON.stringify( true ); // “true”
任何 JSON-safe 的值都可以被 JSON.stringify(..)。
JSON-safe
定義:可被有效表達為 JSON 表示值的任何值。
不是的範例:
undefined
function
symbol
帶有循環參考的物件。(拋出錯誤)
在陣列中碰到,會被取代為 null。
在物件的 key 值遇到,該名值對會被忽略。
JSON.stringify( undefined );
// undefined
JSON.stringify( function(){} );
// undefined
JSON.stringify( [1,undefined,function(){},4] );
// “[1,null,null,4]”
JSON.stringify( { a:2, b:function(){} } );
// “{“a”:2}”
JSON 字串化的特殊行為:一個物件值定義有 toJSON(),那此方法就會被先呼叫,以取得一個用於序列化的物件。
如果想字串化一個非 JSON-safe 的值,那可以定義一個 toJSON() ,回傳一個該物件 JSON-safe 的版本。
var o = { };
var a = {
b: 42,
c: o,
d: function(){}
};
// 在 a 內部建立一個循環參考
o.e = a;
// 會對 JSON.stringify( a ); 丟出錯誤
// 定義一個 JSON 值用於序列化
a.toJSON = function() {
// 序列化過程只含有 b 特性
return { b: this.b };
};
JSON.stringify( a ); // “{“b”:42}”
常見的誤解
toJSON 不是轉為 JSON 字串,而是轉為一個適合用於字串化的 JSON-safe 值。
正確觀念範例:
var a = {
val: [1,2,3],
toJSON: function(){
return this.val.slice( 1 );
}
};
JSON.stringify( a ); // “[2,3]”
常見誤解範例:
var b = {
val: [1,2,3],
toJSON: function(){
return “[” +
this.val.slice( 1 ).join() +
“]”;
}
// 字串化所回傳的字串,而非陣列本身。
};
JSON.stringify( b ); // “”[2,3]””
怪異的部分
JSON.stringify 的引數
JSON.stringify(…)的第二個引數:
名稱:replacer
引數型別:可以是陣列、function
作用:自訂一個物件的遞迴序列化。
用途:提供另一種過濾非 JSON-safe 值的方式
引數是陣列:應該為字串組所構成,每個字串指定的都是物件內的一個特性名稱。
引數是函式:這個函式中會有特性和值兩個引數,他會被呼叫一次,而物件中的名值對都會被依序傳入,在序列化過程中如果跳過一個特性,就會回傳undefined,否則就回傳所提供的值。
範例:
var a = {
b: 42,
c: “42”,
d: [1,2,3]
};
JSON.stringify( a, [“b”,”c”] ); // “{“b”:42,”c”:”42″}”
JSON.stringify( a, function(k,v){
if (k !== “c”) return v;
} );
// “{“b”:42,”d”:[1,2,3]}”

JSON.stringify(…)的第三個引數:
名稱:space
引數型別:正整數或字串
作用:space 可以指定每個縮排層級要用幾個空字元的一個正整數。
用途:用於縮排以產生美觀的輸出,易讀性提高。
範例:
var a = {
b: 42,
c: “42”,
d: [1,2,3]
};
JSON.stringify( a, null, 3 );
// “{
// “b”: 42,
// “c”: “42”,
// “d”: [
// 1,
// 2,
// 3
// ]
// }”
JSON.stringify( a, null, “—–” );
// “{
// —–“b”: 42,
// —–“c”: “42”,
// —–“d”: [
// ———-1,
// ———-2,
// ———-3
// —–]
// }”
小結語
字串、布林、數字以及 null 這些值字串化成 JSON 的方式,基本上就和他們轉為字串型別的方式相同。
物件值傳進 JSON.stringify,而那個物件值上有一個 toJSON 方法,這個 toJSON在字串化前會被自動呼叫,而這個物件可以算是隱含的強制轉型為 JSON-safe。(因為我們沒有主動呼叫 toJSON)
ToNumber
任何不是數字型別而被當作數字來用,例如數學運算,ES5 有定義了 ToNumber 的抽象運算。
字串轉數字
對字串來說,ToNumber 跟數值字面值(第六章)的規則和語法很像。
如果非數字字面值轉型失敗,結果就是 NaN,差別在於 0 前綴的八進位數字不會被當作八進位,而是十進位。
(八進位是 ES5 之前的事)
物件(陣列)
它會先被轉為基本型別值等效值,而產生結果,而這個結果值會根據剛提到的規則被強制轉換成數字。
為了轉換基本型別的等效值,ToPrimitive 抽象運算:
看有沒有 valueOf() 方法,如果有就回傳一個基本型別值,那個值就會被用於強制轉型,看有沒有基本型別值。
如果沒有,toString() 就會提供用於強制轉型的值,看有沒有基本型別值。
如果兩者都沒辦法提供基本型別值,就會丟出 TypeError。
範例:
var a = {
valueOf: function(){
return “42”;
}
};
var b = {
toString: function(){
return “42”;
}
};
var c = [4,2];
c.toString = function(){
return this.join( “” ); // “42”
};
Number( a ); // 42
Number( b ); // 42
Number( c ); // 42
Number( “” ); // 0
Number( [] ); // 0
Number( [ “abc” ] ); // NaN
转载请注明:XAMPP中文组官网 » YDKJS 第四次讀書會 筆記(上)