天天看點

JavaScript資料類型及變量1. JavaScript變量2. 資料類型3. JavaScript變量的問題4. 以下為來自MDN的摘抄5. Literals6. JSON

1. JavaScript變量

JavaScript的變量是松散型變量,和之前在python中的 動态機 很類似,這讓我想起了之前的一篇講python變量的文章,松散型指的是變量可以存任何類型資料,所謂變量隻是僅僅是存值的占位符而已。如下操作完全沒問題,資料類型動态改變。

var temp = 123;
        temp = "west";
           

注:使用

var

定義的變量将成為定義該變量的的作用域中的局部變量

如果不用var代表變量是一個全局變量,這裡又涉及到了暗示全局變量。

也就是說 在函數中定義的變量在函數退出後即會銷毀 ,這裡之前的作用域鍊 提到過。

注:這裡再次強調

var temp = 123;

的步驟,并不是直接指派,涉及到了 預編譯 ,隻有調用該變量時才會給他指派,之後立即被銷毀。

【例】猜它會怎麼報錯?

function dc() {
            var temp = 123;
            temp = "west";
         }
         dc();
         alert(temp);
           

【Error】:

Uncaught ReferenceError: temp is not defined

2. 資料類型

ECMAScript 有五種基本資料類型,如下

  1. undefined

  2. null

  3. boolean

  4. number

  5. string

  6. bigint

  7. symbol

最新版的ECMAScript 的基本資料類型新增了:

  • Symbol
  • BigInt

還有一種複雜資料類型

Object

,當然類似于Function、Number、Error、RegExp也是複雜資料類型。

ECMAScript不支援任何建立自定義類型的機制,就好比C語言的自定義結構體是不支援的。

reference:MDN——最新的 ECMAScript 标準定義了8種資料類型

2.1. undefined和null

實際上

undefined

值派生自

null

值,是以

undefined == null //true

,undefined類型隻有一個值,即undefined,引入它是為了區分空對象指針和未經初始化的變量。

null表示一空對象指針,如果定義的變量将來用于儲存對象,那麼最好将該變量初始化為null,這樣隻要檢查null值就可以知道相應的變量是否已經儲存了一個對象的引用。

還有,沒初始化的和沒聲明的變量使用typeof 會傳回undefined,但是建議都對資料進行初始化,這樣傳回undefined時就會知道變量時還沒聲明而不是沒初始化。

【例】

var car = null;
         if (car != null) {
            //操作
         }
           

注:盡管null和undefined又有特殊關系,但他們完全不同,任何情況都沒有必要把一個變量值顯式地設定為undefined,但對null并不适用,隻要意在儲存對象的變量還沒有真正儲存對象,就應該明确儲存變量為null值。這樣不僅展現null作為空對象指針的慣例,也有助于進一步區分null和undefined。

2.2. Boolean

注意

true、false

區分大小寫

存在

Boolean()

函數将一個值轉換為對應的Boolean值。

2.3. Number

  1. 八進制在嚴格模式下無效,會抛出

    Uncaught SyntaxError: Octal literals are not allowed in strict mode

    ,在進行算術運算時所有八進制和十六進制表示的數值都會轉換為十進制。
  2. 對于小數點後面沒有數字的浮點數,ECMAScript會把它轉換為整數儲存。
  3. 對于浮點數值的精度計算遠不如整數值,比如

    0.1+0.2==0.30000000000000004

    ,是以永遠不要測試某個特定得浮點數值。
  4. Infinity是不能參加計算的數值,如果數值超出範圍會傳回

    Infinity

    表無窮,可使用

    isFinite()

    檢視數值是否在範圍内,如果在最大與最小數值之間會傳回

    true

  5. NaN

    ,即非數值,任何涉及NaN的操作都會傳回NaN,它用來表示本要傳回數值的操作數未傳回數值的情況(這樣就不會報錯了)。其次NaN與任何數值都不相等,包括自己。有

    isNaN()

    函數可接受一個任意類型的參數,它會嘗試把值轉換為數值,比如字元串

    “10”

    和Boolean值,而不能轉換為數值的值會傳回

    true

  6. JS中number就是number,并沒有聲明浮點數、整型數的關鍵字,浮點數最高精度是17位小數

2.4. 數值轉換

  • Number()

    可用于任何資料類型
  • parseFloat()

    (隻解析十進制的值,故隻有一個參數) , 用于把字元串轉換為數值
  • parseInt()

    (有兩個參數,後者為進制參數)用于把字元串轉換為數值

注意(

parseInt(string [, radix])

)是把string轉換成數字,讓後把它當作radix進制的數字轉換成十進制。例如

parseInt('321',2)

這樣的操作會傳回NaN,因為321不可能是2進制的。

parseInt

類似,

parseFloat

從第一個字元開始(位置0)解析字元串,直到末尾或者解析到遇見一個無效的浮點數字字元為止。還要記住字元串中的第一個小數點有效而第二個是無效的。

由于

Number()

函數在轉換字元時比較複雜并且不夠合理,是以在處理整數時更常用的時

parseInt()

,還有ES3和ES5對于八進制字面量的字元串進行解析時存在分歧,在ES3中

console.log(parseInt("070"));

會輸出56,但是ES5中會輸出70,原因是ES5中的parseInt已經不具備解析八進制的能力。這個時候加上parseInt的第二個參數就可以改變這情況,實際上帶上了第二個參數之後都不再需要在字元串中使用進制字面量,比如

console.log(parseInt("70", 8));

不再需要寫070了。

parseFloat

始終會忽略前導的0。十六進制始終會被轉換為0。相比于parseInt多解析了一個小數點,而且它沒有第二個參數,隻解析十進制。
console.log(Number("Hello,Word!")); //NaN
        console.log(Number("")); //0
        console.log(Number("000011")); //11
        console.log(Number(true)); //1
        console.log(parseInt("1234blue")); //1234
        console.log(parseInt("")); //NaN
        console.log(parseInt("0xA")); //10
        console.log(parseInt("22.5")); //22
        console.log(parseInt("070")); //70
        console.log(parseInt("70")); //70
        console.log(parseInt("0xf")); //15
        console.log(parseInt("0xAF", 16)); //175
        console.log(parseInt("AF")); //NaN
        console.log(parseInt("10", 2)); //2
        console.log(parseInt("10", 8)); //8
        console.log(parseInt("10", 10)); //10
        console.log(parseInt("10", 16)); //16
        console.log(parseFloat("1234blue")); //1234
        console.log(parseFloat("0xA")); //0
        console.log(parseFloat("22.5")); //22.5
        console.log(parseFloat("22.34.5")); //22.34
        console.log(parseFloat("0908.5")); //908.5
        console.log(parseFloat("3.125e7")); //31250000
           

2.5. String

注:

  1. PHP中雙引号與單引号會影響對字元串解釋方式的不同
  2. 字元串的值不可改變,要改變變量存的字元串隻能銷毀原來的字元串,再用包含新值的字元串填充該變量。
var test = "Java";
        test = test + "Script";
        alert(test);
           

看似是拼接字元串,實際上不是,系統在背景建立了一個新的可容納JavaScript的變量,再把JavaScript填充進去,,最後再銷毀原來的兩個字元串。

轉換為字元串:

toString()

String()

但需注意二者的不同以及對于

undefined、null

二者的特殊性(因為它倆沒有toString方法)
console.log(null.toString());
        //Uncaught TypeError: Cannot read property 'toString' of null
           

在不知道要轉換的值是否是null、undefined的情況下,為防止報錯可使用String對其進行轉換。

百度百科_字面量

字面量(也叫轉義序列) 含義

\n

換行

\t

制表

\b

空格

\r

回車

\f

進紙(走紙換頁)

\\

斜杠

\'

單引号

\"

雙引号

\xnn

以十六進制代碼nn表示的一個字元(其中n為0~F)

例:\x41表示“A”

\unnnn

以十六進制代碼nnnn表示的一個Unicode字元(其中n為0~F)

例:\u03a3表希臘字元Σ

2.6. Object

一組資料和功能的集合

建立:

var test = Object(); //在不給構造函數傳遞參數的情況下‘()’可省略

重要思想

在ECMAScript中(就像Java中的java.lang.Object對象一樣)Object類型是所有它的執行個體和基礎.換句話說,Object類型所具有的所有屬性和方法也同樣存在于更具體的對象中,和Java建立對象類似。

Object的每個執行個體都具有下列屬性和方法:

  • Construor
  • hasOwnProperty(propertyName)
  • isPrototypeof(object)
  • propertyIsEnumerable(propertyName)
  • toLocaleString()
  • toString()
  • valueOf()

附:JS中toString()、toLocaleString()、valueOf()的差別

在數裡講的很詳細了。

2.7. 附加: typeof

參考:typeof傳回值

使用typeof操作符可傳回下列某個 字元串

  • "undefined"

    ——值未定義
  • "boolean"

    ——值為布爾值
  • "string"

    ——值為字元串
  • "number"

    ——值為數值
  • "object"

    ——值為對象或null,或者其他引用類型資料
  • "function"

    ——值為函數

由于最新的ES又新增了一些内容,是以現在它還可以傳回

  • "bigint"

  • "symbol"

從技術角度來講,function在JS中是一個對象,而不是一種資料類型,但是函數确實有一些特殊的屬性,是以通過typeof來區分它們是有必要的。

注:強調typeof是一個操作符而不是一個函數,括号不是必須的,null之是以會傳回

Object

是因為null最初是作為空對象的占位符的使用的,被認為是空對象的引用。在對正規表達式調用typeof時,Safari5及之前的版本、Chrome7及之前的版本會傳回

"function"

,其他浏覽器會傳回

"object"

因為typeof隻能傳回這幾種字元串,是以它是不完善的,比如在面對object和array時,都隻會傳回

"object"

,對這一缺陷可以使用以下方法彌補
// typeof的完善
        function type(target) {
            var ret = typeof (target);
            var template = {
                "[object Array]": "array",
                "[object Object]": "object",
                "[object Number]": "number - object",
                "[object Boolean]": "boolean - object",
                "[object String]": "string - object",
            }

            if (target === null) {
                return "null";
            }
            if (ret == "object") {
                var str = Object.prototype.toString.call(target);
                return template[str];
            } else {
                return ret;
            }
        }
           

3. JavaScript變量的問題

JavaScript變量松散型的本質,決定了他隻是在特定時間用于儲存特定值的一個名字而已。不存在定義某個變量必須要儲存某種資料類型值的規則,變量的值及資料類型可以在腳本的生命周期内改變。

ECMAScript不認為字元串是引用類型的,這點與其他語言不同。

ECMAScript變量可能包含兩種不同資料類型的值:

  1. 基本資料類型
  2. 引用型

4. 以下為來自MDN的摘抄

其實内容和上面的很多事重複的,主要是想看英文的,是以摘抄重要的點。

參考:Grammar and types

4.1. Basics

  1. case-sensitive(區分大小寫)
  2. uses the Unicode character set(集合)
  3. instructions are called statements and are separated by semicolons (😉.
對于語句末尾到底要不要加分号?MDN_ASI 給出了回答

4.2. Declarations

JavaScript has three kinds of variable declarations.

  • var:Declares a variable, optionally initializing it to a value.
  • let:Declares a block-scoped(塊作用域), local variable(局部變量), optionally initializing it to a value.
  • const:Declares a block-scoped, read-only named constant(隻讀命名常量).
With the keyword

var

. For example, var x = 42. This syntax can be used to declare both local and global variables, depending on the execution context.

With the keyword

const

or

let

. For example, let y = 13. This syntax can be used to declare a block-scope local variable. (See Variable scope below.)

4.3. Evaluating variables

  • The undefined value behaves as false when used in a boolean context.
  • The undefined value converts to NaN when used in numeric context.
  • When you evaluate a null variable, the null value behaves as 0 in numeric contexts and as false in boolean contexts.

4.4. Variable scope

  • When you declare a variable outside of any function, it is called a global variable, it is available to any other code in the current document.
  • When you declare a variable within a function, it is called a local variable, because it is available only within that function.
  • JavaScript before ECMAScript 2015 does not have block statement scope. Rather, a variable declared within a block is local to the function (or global scope) that the block resides within.(在塊中聲明的變量是該塊所駐留的函數(或全局範圍)的局部變量)
  • The scope of x is not limited to the immediate

    if{}

    statement block.

注:This behavior changes when using the let declaration (introduced in ECMAScript 2015).

if (true) {
      let y = 5;
      }
      console.log(y);  // ReferenceError: y is not defined
           

4.5. Variable hoisting

Variable hoisting involves pre-compilation(預編譯),you can refer to a variable declared later, without getting an exception.

Because of hoisting, all var statements in a function should be placed as near to the top of the function as possible. This best practice increases the clarity of the code(代碼清晰度).

In ECMAScript 2015, let and const are hoisted but not initialized. Referencing the variable in the block before the variable declaration results in a ReferenceError, because the variable is in a “temporal dead zone” from the start of the block until the declaration is processed.

4.6. Function hoisting

In the case of functions, only function declarations are hoisted—but not the function expressions.

(隻有函數聲明會被提升,函數表達式不會被提升)

var b = function () {} //函數表達式
        function myFun() {} //函數聲明
           

在Javscript中,解析器在向執行環境中加載資料時,對函數聲明和函數表達式并非是一視同仁的,解析器會率先讀取函數聲明,并使其在執行任何代碼之前可用(可以通路——預編譯)。

至于函數表達式,則必須等到解析器執行到它所在的代碼行,才會真正被解析執行。

4.7. Global variables

關于 GO 和 window 的關系在上一篇文章中提過: window對象

Global variables are in fact properties of the global object.

In web pages, the global object is window, so you can set and access global variables using the

window.variable

syntax.

是以,你可以通過指定 window 或 frame 的名字,在目前 window 或 frame 通路另一個 window 或 frame 中聲明的變量。例如,在文檔裡聲明一個叫 phoneNumber 的變量,那麼你就可以在子架構裡使用 parent.phoneNumber 的方式來引用它。

這裡所說的子架構指的是iframe

HTML内聯架構元素 (

<iframe>

) 表示嵌套的browsing context。它能夠将另一個HTML頁面嵌入到目前頁面中。每個嵌入的浏覽上下文(embedded browsing context)都有自己的會話曆史記錄(session history)和DOM樹。包含嵌入内容的浏覽上下文稱為父級浏覽上下文。頂級浏覽上下文(沒有父級)通常是由 Window 對象表示的浏覽器視窗。

4.8. Constants

You can create a read-only, named constant with the const keyword.

A constant cannot change value through assignment(配置設定) or be re-declared while the script is running. It must be initialized to a value.

嘗試更改常量的值将會導緻:

Uncaught TypeError: Assignment to constant variable.

在同一個範圍内也不能聲明常量和函數同名。

However, the properties of objects assigned to constants are not protected, so the following statement is executed without problems.

(配置設定給常量的對象的屬性不受保護,是以可以重新指派),同樣的如果配置設定給常量的是一個數組,數組中的值也不受保護,也可以像對象的屬性一樣修改。

const a = {
            tt: "Tian"
        };
        a = 2;
        //Uncaught TypeError: Assignment to constant variable.
        a.tt = 23 //23
        // 數組同理
           

4.9. Data structures and types

  • Seven data types that are primitives(原始):
    1. Boolean

      . true and false.
    2. null

      . A special keyword denoting a null value. (Because JavaScript is case-sensitive,null is not the same as Null, NULL, or any other variant.)
    3. undefined

      . A top-level property whose value is not defined.
    4. Number

      . An integer or floating point number. For example: 42 or 3.14159.
    5. BigInt

      . An integer with arbitrary(任意) precision(精度). For example:

      9007199254740992n

      .
    6. String

      . A sequence of characters that represent a text value. For example: “Howdy”
    7. Symbol

      (new in ECMAScript 2015). A data type whose instances are unique and immutable(不可變).
  • and

    Object

4.10. Data type conversion

JavaScript is a dynamically(動态地) typed language,是以你聲明變量是不必指明資料類型,并且資料類型還可以自動地轉換。

4.11. Numbers and the ‘+’ operator

+

算子連接配接數字和字元串,數字将會變成字元。 但有些時候JS不會将數字轉換成字元。比如

'3' - 2 //1

可使用

parseInt()

parseFloat()

将用字元串存儲的數字轉換為數字。

另一種另類的處理方法是使用

+

(一進制運算符) 從字元串中提取數字

'1.1' + '1.1' // '1.11.1'
        (+'1.1') + (+'1.1') // 2.2   
        // Note: the parentheses(括号) are added for clarity(清晰度), not required.
           

5. Literals

Literals 應該翻譯成什麼?字面量?字元?文字?我了解成能直接看出來是什麼類型的資料 “的”這種聲明的形式。

它代表了JS中的值,是在腳本中自己提供的固定的值,而不是變量。翻譯總有偏差,是以它隻叫 Literals。

5.1. Array literals

是0個或者多個表達式組成的清單,每個表達式代表一個數組元素,括在方括号中(

[]

),你可以用 Array literals 建立一個數組,它的元素被初始化成指定值。

Note : An array literal is a type of object initializer

5.2. Boolean literals

The Boolean type has two literal values: true and false.

var bool = new Boolean()
        // bool = Boolean {false}
        typeof bool // "object"
        bool == false // true
        bool === false //false
           

5.3. Floating-point literals

3.1415926
      -.123456789
      -3.1E+12
      .1e-23
           

5.4. Numeric literals

Number and BigInt types can be expressed in decimal (十進制), hexadecimal (16進制), octal (8進制) and binary (2進制).

5.5. Object literals

An object literal is a list of zero or more pairs of property names and associated values of an object, enclosed in curly braces (

{}

).

5.6. RegExp literals

A regex literal is a pattern enclosed between slashes. The following is an example of a regex literal.

var re = /ab+c/;

5.7. String literals

A string literal is zero or more characters enclosed in double (") or single (’) quotation marks.

You can call any of the String object’s methods on a string literal value. JavaScript automatically converts the string literal to a temporary(臨時) String object, then discards the temporary String object.

5.8. 解構指派

參考:https://zh.javascript.info/destructuring-assignment

5.9. 數組解構

解構指派是一種特殊且簡潔的文法,讓我們可以拆分複雜資料類型中的需要的内容到一系列變量中。解構操作對那些具有很多參數和預設值等的函數也很奏效。

let arr = ["Ilya", "Kantor"]

        // 解構指派
        let [firstName, surname] = arr;

        console.log(firstName); // Ilya
        console.log(surname); // Kantor

        // 結合split 
        let [firstName1, surname1] = "Ilya Kantor".split(' ');
        console.log(firstName1); // Ilya
        console.log(surname1); // Kantor
           
  1. 解構并沒有破壞原有的數組。
  2. 對于數組中不想要的元素可以通過多加逗号濾除,
// 不需要第二個元素
        let [firstName, , title] = ["Julius", "Caesar", "Consul", " Republic"];

        alert(title); // Consuls
           
  1. 等号右側可以是任何可疊代對象
let [a, b, c] = "abc"; // ["a", "b", "c"]
        let [one, two, three] = new Set([1, 2, 3]);
           
  1. 指派給等号左側的任何内容
let user = {};
        [user.name, user.surname] = "Ilya Kantor".split(' ');

        alert(user.name); // Ilya
           
  1. 與 .entries() 方法進行循環操作

這寫法非常簡潔。

let user = {
            name: "John",
            age: 30
        };

        // 循環周遊鍵—值對
        for (let [key, value] of Object.entries(user)) {
            alert(`${key}:${value}`); // name:John, then age:30
        }
           

與map結合

let user = new Map();
        user.set("name", "John");
        user.set("age", "30");

        for (let [key, value] of user) {
            alert(`${key}:${value}`); // name:John, then age:30
        }
           
  1. 交換變量技巧
let guest = "Jane";
        let admin = "Pete";
        let marry = "HuiD";

        [guest, marry, admin] = [admin, guest, marry];

        console.log(guest, admin, marry); // Pete HuiD Jane
           
  1. 剩餘的 ‘…’
let arr = ["Jane", "HuiD", "Pete", "Caoke"];
        let [one, ...two] = ["Jane", "HuiD", "Pete", "Caoke"];
        console.log(one); //Jane
        console.log(two); //["HuiD", "Pete", "Caoke"]
           
  1. 預設值

如果指派語句中,變量的數量多于數組中實際元素的數量,指派不會報錯。未指派的變量被認為是 undefined

let [firstName, surname] = [];

        console.log(firstName); // undefined
        console.log(surname); // undefined
        // 預設值
        let [name = "Guest", surname1 = "Anonymous"] = ["Julius"];

        console.log(name); // Julius(來自數組的值)
        console.log(surname1); // Anonymous(預設值被使用了)
           

預設值可以是更加複雜的表達式甚至可以是函數調用,這些表達式或函數隻會在這個變量未被指派的時候才會被計算。

// 隻會提示輸入姓氏
        let [name = prompt('name?'), surname = prompt('surname?')] = ["Julius"]; //Juliu對應到name

        console.log(name); // Julius(來自數組)
        console.log(surname); // 你輸入的值
           

5.10. 對象解構

對象結構和數組結構的差別在于哪裡?
let options = {
            title: "Menu",
            width: 100,
            height: 200
        };

        // 注意這裡變量名和對象中的鍵相同 ,等号左側包含了對象相應屬性的一個“模式(pattern)”,變量的順序并不重要。
        let {
            title,
            width,
            height
        } = options;

        console.log(title); // Menu
        console.log(width); // 100
        console.log(height); // 200
           

如果我們想把一個屬性指派給另一個名字的變量,比如把 options.width 屬性指派給變量 w,那麼我們可以使用冒号來指定:

let options = {
            title: "Menu",
            width: 100,
            height: 200
        };

        // { sourceProperty: targetVariable }
        let {
            width: w,
            height: h,
            title
        } = options;

        // width -> w
        // height -> h
        // title -> title

        console.log(title); // Menu
        console.log(w); // 100
        console.log(h); // 200
           

對于可能缺失的屬性,我們可以使用 “=” 設定預設值。就像數組或函數參數一樣,預設值可以是任意表達式甚至可以是函數調用。它們隻會在未提供對應的值時才會被計算/調用。

我們還可以将冒号和等号結合起來:

let options = {
            title: "Menu"
        };

        let {
            width: w = 100,
            height: h = 200,
            title = "Defult"
        } = options;

        console.log(title); // Menu
        console.log(w); // 100
        console.log(h); // 200
           

同數組解構類似,我們可以隻取其中的某一些屬性,然後把“剩餘的”指派到其他地方。

我們可以使用剩餘模式(pattern),就像我們對數組那樣。一些較舊的浏覽器不支援此功能(例如,使用 Babel 對其進行填充),但可以在現代浏覽器中使用。

let obj = {
            name: "Hui",
            age: 22,
            heigh: 168
        };

        let {
            name,
            ...per
        } = obj;

        console.log(name); //Hui
        console.log(per); //{age: 22, heigh: 168}
           

注意:JavaScript把主代碼流的{…}當作一個代碼塊,是以

let title, width, height;

        // 這一行發生了錯誤,js會把{}當作代碼塊,但實際上它是對象解構
        {title, width, height} = {title: "Menu", width: 200, height: 100};

        // 通過把整個指派表達式用括号 (...) 包起來解決
        ({title, width, height} = {title: "Menu", width: 200, height: 100});
           

5.11. 嵌套解構

let options = {
            size: {
                width: 100,
                height: 200
            },
            items: ["Cake", "Donut"],
            extra: true
        };
        // 為了清晰起見,解構指派語句被寫成多行的形式
        let {
            size: { // 把 size 指派到這裡
                width,
                height
            },
            items: [item1, item2], // 把 items 指派到這裡
            title = "Menu" // 在對象中不存在(使用預設值)
        } = options;
        console.log(title); // Menu
        console.log(width); // 100
        console.log(height); // 200
        console.log(item1); // Cake
        console.log(item2); // Donut


        let arr = [{
            name: "Hui",
            age: 22,
            info: [178, 18]
        }, "DT", ["Jane", "Pete"]];

        let [{
            name,
            age,
            info: [heigh, length]
        }, str, [J, P]] = arr;
        console.log(name); //Hui
        console.log(age); //22
        console.log(heigh); //178
        console.log(length); //18
        console.log(str); //DT
        console.log(J); //Jane
        console.log(P); //Pete
           

5.12. 智能函數參數

參考:https://zh.javascript.info/destructuring-assignment#zhi-neng-han-shu-can-shu

主要針對函數傳參進行代碼清潔

我自己寫解構時出現的幾次錯誤都是因為搞混了數組與對象使用的括号,還有冒号、等号以及對象屬性需要同名等,就這幾點需要記住。

6. JSON

  1. JSON和語言無關,是純資料的規範,是以一些JavaScript特定的屬性會被JSON.stringify跳過,比如:
  • 函數屬性(方法)。
  • Symbol 類型的屬性。
  • 存儲 undefined 的屬性。

這在借助JSON做deepClone的時候需要注意。

let obj = {
            name: "DT",
            age: 23,
            [Symbol.toPrimitive](hint) {
                alert(`hint: ${hint}`);
                return hint == "string" ? `{name: "${this.name}"}` : this.age;
            },
            wife: undefined,
            say: function () {
                console.log("Hui");
            },
        }
        console.log((JSON.stringify(obj))); //{"name":"DT","age":23}
           
參考:Symbol.toPrimitive
  1. 支援嵌套解構

重要的限制:不得有循環引用。

let meetup = {
            title: "Conference",
            room: {
                number: 23,
                participants: ["john", "ann"]
            }
        };

        console.log(JSON.stringify(meetup));
        /* 整個解構都被字元串化了
        {
            "title": "Conference",
            "room": {
                "number": 23,
                "participants": ["john", "ann"]
            }
        }
        */
        let room = {
            number: 23
        };

        meetup.place = room; // meetup 引用了 room
        room.occupiedBy = meetup; // room 引用了 meetup

        // 在這裡,轉換失敗了,因為循環引用:room.occupiedBy 引用了 meetup,meetup.place 引用了 room
        console.log(JSON.stringify(meetup));; // Uncaught TypeError: Converting circular structure to JSON
           
JavaScript資料類型及變量1. JavaScript變量2. 資料類型3. JavaScript變量的問題4. 以下為來自MDN的摘抄5. Literals6. JSON

繼續閱讀