91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript原始值與包裝對象的示例分析

發布時間:2021-05-11 14:59:49 來源:億速云 閱讀:161 作者:小新 欄目:開發技術

這篇文章主要介紹JavaScript原始值與包裝對象的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

JavaScript有什么特點

1、js屬于一種解釋性腳本語言;2、在絕大多數瀏覽器的支持下,js可以在多種平臺下運行,擁有著跨平臺特性;3、js屬于一種弱類型腳本語言,對使用的數據類型未做出嚴格的要求,能夠進行類型轉換,簡單又容易上手;4、js語言安全性高,只能通過瀏覽器實現信息瀏覽或動態交互,從而有效地防止數據的丟失;5、基于對象的腳本語言,js不僅可以創建對象,也能使用現有的對象。

正文

原始類型 (Primitive types)

原始類型也被稱為“基本類型”。

目前在 JavaScript 中有以下幾種原始類型:

  • string(字符串)

  • number(數字)

  • boolean(布爾)

  • null(空)

  • undefined(未定義)

  • bigint(大整數,ES6)

  • symbol(標志?ES6)

? 如下:

typeof 'chenpipi';  // "string"
typeof 12345;       // "number"
typeof true;        // "boolean"
typeof null;        // "object"
typeof undefined;   // "undefined"
typeof 12345n;      // "bigint"
typeof Symbol();    // "symbol"

? 特別注意

typeof null 雖然返回 "object",但是這不代表 null 就是對象,這其實是 JavaScript 的一個 Bug,且從 JavaScript 誕生以來便如此。

在 JavaScript 最初的實現中,JavaScript 中的值是由一個表示類型的標簽和實際數據值表示的。對象的類型標簽是 0。由于 null 代表的是空指針(大多數平臺下值為 0x00),因此,null 的類型標簽是 0,typeof null 也因此返回 "object"。

The history of “typeof null”:https://2ality.com/2013/10/typeof-null.html

原始值 (Primitive values)

原始值也就是原始類型的值(數據)。

A primitive value is data that is not an object and has no methods.

原始值是一種沒有任何方法的非對象數據。

也就是說,string、number 和 boolean 等原始類型的值本身是沒有任何屬性和方法的。

 這個時候嗅覺敏銳的小伙伴是不是已經察覺到有什么不對勁了?

是孜然!我加了孜然!(手動狗頭并劃掉)

? 這里有一個非常有意思的點,但是在討論這個問題之前,先讓我們認識下包裝對象。

包裝對象 (Wrapper objects)

除了 null 和 undefined 外的原始類型都有其相應的包裝對象:

  • String(字符串)

  • Number(數字)

  • Boolean(布爾)

  • BigInt(大整數,ES6)

  • Symbol(標志?ES6)

對象 (Object)

對象是引用類型。

首先,包裝對象本身是一個對象,也是函數。

String instanceof Object;   // true
String instanceof Function; // true
構造函數 (Constructor)

實例 (Instance)

其中 String、Number 和 Boolean 均支持使用 new 運算符來創建對應的包裝對象實例。

? 例如 String 的聲明(節選):

interface StringConstructor {
  new(value?: any): String;
  (value?: any): string;
  readonly prototype: String;
}
declare var String: StringConstructor;

? 使用 new 運算符得到的數據是對象(Object):

// 字符串
typeof 'pp';                      // "string"
typeof new String('pp');          // "object"
new String() instanceof Object;   // true
// 數字
typeof 123;                       // "number"
typeof new Number(123);           // "object"
new Number() instanceof Object;   // true
// 布爾
typeof true;                      // "boolean"
typeof new Boolean(true);         // "object"
new Boolean() instanceof Object;  // true

? 我們可以調用包裝對象實例的 valueOf() 函數來獲取其原始值:

// 字符串
let s = new String('pp');
s.valueOf();                // "pp"
typeof s.valueOf();         // "string"
// 數字
let n = new Number(123);
n.valueOf();                // 123
typeof n.valueOf();         // "number"
// 布爾
let b = new Boolean(true);
b.valueOf();                // true
typeof b.valueOf();         // "boolean"

“異類” (Attention)

而 BigInt 和 Symbol 都屬于“不完整的類”,不支持 new 運算符。

? 例如 BigInt 的聲明(節選):

interface BigIntConstructor {
  (value?: any): bigint;
  readonly prototype: BigInt;
}
declare var BigInt: BigIntConstructor;

可以看到 BigInt 的聲明中沒有 new 運算符相關函數。

普通函數 (Function)

包裝對象也可以作為普通函數來使用。

其中 String()、Number() 和 Boolean() 函數都可以用來對任意類型的數據進行顯式類型轉換。

另外 Object() 函數也可用于顯式類型轉換,但本文不再展開。

String

? 示例代碼:

typeof String();    // "string"
String();           // ""
String('pp');       // "pp"
String(123);        // "123"
String(true);       // "true"
String(false);      // "false"
String(null);       // "null"
String(undefined);  // "undefined"
String([]);         // ""
String({});         // "[object Object]"

? 小貼士 1

當我們使用 String() 函數來轉換對象時,JavaScript 會先訪問對象上的 toString() 函數,如果沒有實現,則會順著原型鏈向上查找。

? 舉個栗子:執行 String({ toString() { return 'pp'; } }) 返回的結果是 "pp",并非 "[object Object]"。

所以 String() 函數并不能夠用來判斷一個值是否為對象(會翻車)。

? 小貼士 2

常用的判斷對象的方式為 Object.prototype.toString({}) === '[object Object]'。

? 舉個栗子:執行 Object.prototype.toString({ toString() { return 'pp'; } }) 返回的是 "[object Object]"。

Number

? 示例代碼:

typeof Number();    // "number"
Number();           // 0
Number('');         // 0
Number('pp');       // NaN
Number(123);        // 123
Number(true);       // 1
Number(false);      // 0
Number(null);       // 0
Number(undefined);  // NaN
Number([]);         // 0
Number({});         // NaN

? 小貼士

對于 Number() 函數來說,可能最實用的轉換就是將 true 和 false 轉換為 1 和 0 吧。

Boolean

? 示例代碼:

typeof Boolean();   // "boolean"
Boolean();          // false
Boolean('');        // false
Boolean('pp');      // true
Boolean(0);         // false
Boolean(1);         // true
Boolean(null);      // false
Boolean(undefined); // false
Boolean([]);        // true
Boolean({});        // true

? 小貼士

某些情況下,我們會在數據中使用 0 和 1 來表示真假狀態,此時就可以使用 Boolean() 進行狀態的判斷。

BigInt

BigInt() 函數用于將整數轉換為大整數。

該函數接受一個整數作為參數,傳入參數若為浮點數或任何非數字類型數據都會報錯。

? 示例代碼:

BigInt(123);        // 123n
BigInt(123n);       // 123n
typeof 123n;        // "bigint"
typeof BigInt(123); // "bigint"

BigInt & Number

需要注意的是,BigInt 和 Number 是不嚴格相等(寬松相等)的。

? 示例代碼:

123n === 123; // false
123n == 123;  // true

Symbol

Symbol() 函數用于創建一個 symbol 類型的值。

該函數接受一個字符串作為描述符(參數),如果傳入其他類型的值則會被轉換為字符串(除了 undefined)。

注意,每一個 symbol 值都是獨一無二的,即使它們的描述符都是一樣的。

且 symbol 類型的數據只能通過 Symbol() 函數來創建。

? 示例代碼:

// 后面的返回值是 Devtools 模擬出來的,并非實際值
Symbol('pp');                   // Symbol(pp)
Symbol(123);                    // Symbol(123)
Symbol(null);                   // Symbol(null)
Symbol({});                     // Symbol([object Object])

// 類型
typeof Symbol('pp');            // "symbol"
Symbol('pp') === Symbol('pp');  // false

// 描述符
Symbol('pp').description;       // "pp"
Symbol(123).description;        // "123"
Symbol({}).description;         // "[object Object]"
Symbol().description;           // undefined
Symbol(undefined).description;  // undefined

原始值不是對象 (Primitive not Object)

? 有意思的來了~

沒有屬性和方法 (No properties, no functions)

本文前面有提到:「原始值是一種沒有任何方法的非對象數據。」

我們都知道對象(Object)上可以有屬性和方法。

但是字符串不是對象,所以你不能給字符串增加屬性。

? 做個小實驗:

let a = 'chenpipi';
console.log(a.length);  // 8
// 嘗試增加新的屬性
a.name = '吳彥祖';
console.log(a.name);    // undefined
// 嘗試修改已有的屬性
typeof a.slice;         // "function"
a.slice = null;
typeof a.slice;         // "function"

? 渣皮小劇場

此時一位頭鐵的小伙伴使用了反駁技能。

渣皮你別在這忽悠人了,我平時寫 Bug 哦不寫代碼的時候明明可以調用到字符串、數字和布爾值上的方法!

? 比如下面這段代碼,能夠正常執行并得到符合預期的結果:

// 字符串
let s = 'chenpipi';
s.toUpperCase();      // "CHENPIPI"
'ChenPiPi'.slice(4);  // "PiPi"
// 數字
let n = 123;
n.toString();         // "123"
(123.45).toFixed(2);  // "123.5"
// 布爾值
let b = true;
b.toString();         // "true"
false.toString();     // "false"

? 無用小知識

有沒有發現,數字的字面量后面不能直接調用函數?例如執行 123.toString() 會報 SyntaxError(語法錯誤)。

這是因為數字(浮點數)本身會用到小數點 .,而調用函數也需要用小數點,這時就出現了歧義(字符串和布爾值就沒有這種煩惱)。

對于這種情況,我們可以使用括號 () 將數字包裹起來,如 (123).toString();或者使用兩個連續的小數點 .. 來調用函數,如 123..toString()。

? 奇了怪了

那么既然字符串不是對象,那么為什么字符串會有屬性和方法呢?

轉念一想,數字就是數字,數字身上怎么會有方法呢?

這確實不符合邏輯,但是這又與實際相矛盾。

咋回事呢???

替身使者 (I can't translate this)

答案揭曉~

? 暗中操作

以字符串(string)為例,當我們在代碼中讀取字符串的屬性或者方法時, JavaScript 會靜默地執行下面的操作:

  1. 將字符串通過 new String() 的方式來創建一個臨時的包裝對象實例;

  2. 通過創建的對象來執行我們的代碼邏輯(讀取屬性或執行函數);

  3. 臨時對象不再使用,可以被銷毀。

? 如下面的栗子:

let a = 'chenpipi';
console.log(a);   // "chenpipi"
// ------------------------------
let b1 = a.length;
console.log(b1);  // 8
// 上面的代碼相當于:
let b2 = (new String(a)).length;
console.log(b2);  // 8
// ------------------------------
let c1 = a.toUpperCase();
console.log(c1);  // "CHENPIPI"
// 上面的代碼相當于:
let c2 = (new String(a)).toUpperCase();
console.log(c2);  // "CHENPIPI"

數字(number)和布爾值(boolean)同理,但數字通過 new Number() 來創建臨時對象,而布爾值則通過 new Boolean() 來創建。

? 除了上面的例子,最有力的證明,就是他們的構造函數:

'chenpipi'.constructor === String;  // true
(12345).constructor === Number;     // true
true.constructor === Boolean;       // true

這一切都是 JavaScript 在暗中完成的,且過程中產生的臨時對象都是一次性的(用完就丟)。

? 原來如此

蕪湖,這么一來就說得通了!

這也就能解釋為什么我們能夠訪問字符串上的屬性和方法,卻不能增加或修改屬性。

那是因為我們實際操作的目標其實是 JavaScript 創建的臨時對象,而并非字符串本身!

所以我們的增加或修改操作實際上是生效了的,只不過是在臨時對象上生效了!

? 就像這樣:

// 代碼中:
let a = 'chenpipi';
a.name = '吳彥祖';
console.log(a.name);  // undefined

// 相當于:
let a = 'chenpipi';
(new String(a)).name = '吳彥祖';
console.log(a.name);  // undefined

// 相當于:
let a = 'chenpipi';
let temp = new String(a);
temp.name = '吳彥祖';
console.log(a.name);  // undefined

最后我們來總結一下:

  1. 多數原始類型都有相應的包裝對象;

  2. 有些包裝對象可以被 new,有些不行;

  3. 包裝對象一般被用來進行顯式的類型轉換;

  4. 對象上有屬性和方法;

  5. 原始值上沒有屬性和方法;

  6. 原始值上也不能有屬性和方法;

  7. 但我們可以像操作對象一樣來操作原始值;

  8. 這是因為 JavaScript 在執行代碼的時候偷偷搞小動作;

  9. JavaScript 會用臨時的包裝對象來替原始值執行操作。

以上是“JavaScript原始值與包裝對象的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

定州市| 东城区| 舒兰市| 佛教| 伊春市| 襄汾县| 乐都县| 都匀市| 马山县| 柏乡县| 资源县| 敖汉旗| 嫩江县| 南漳县| 嘉义市| 庆安县| 章丘市| 随州市| 太白县| 鄂尔多斯市| 汝城县| 吴川市| 织金县| 凌云县| 佛山市| 绥化市| 汾西县| 望谟县| 兴山县| 峨山| 开阳县| 云阳县| 张家港市| 常熟市| 平武县| 东乌珠穆沁旗| 巩留县| 巫山县| 敖汉旗| 浦东新区| 贵港市|