1. 程式人生 > >fifthThirteen-- A Rookie Web Front-end development

fifthThirteen-- A Rookie Web Front-end development

目錄

1.定義

1.定義

物件是 JavaScript 語言最主要的資料型別,三種原始型別的值——數值、字串、布林值——在一定條件下,也會自動轉為物件,也就是原始型別的“包裝物件”。

所謂“包裝物件”,就是分別與數值、字串、布林值相對應的NumberStringBoolean三個原生物件。這三個原生物件可以把原始型別的值變成(包裝成)物件。

var v1 = new Number(123);
var v2 = new String('abc');
var v3 = new Boolean(true);

 上面程式碼中,基於原始型別的值,生成了三個對應的包裝物件。

typeof v1 // "object"
typeof v2 // "object"
typeof v3 // "object"

v1 === 123 // false
v2 === 'abc' // false
v3 === true // false

包裝物件的最大目的,首先是使得 JavaScript 的物件涵蓋所有的值,其次使得原始型別的值可以方便地呼叫某些方法。

NumberStringBoolean如果不作為建構函式呼叫(即呼叫時不加new),常常用於將任意型別的值轉為數值、字串和布林值。

Number(123) // 123
String('abc') // "abc"
Boolean(true) // true

 總結一下,這三個物件作為建構函式使用(帶有new)時,可以將原始型別的值轉為物件;作為普通函式使用時(不帶有new),可以將任意型別的值,轉為原始型別的值。

2.例項方法

三種包裝物件各自提供了許多例項方法,詳見後文。這裡介紹兩種它們共同具有、從Object物件繼承的方法:valueOftoString

2.1 valueOf()

valueOf方法返回包裝物件例項對應的原始型別的值。

new Number(123).valueOf()  // 123
new String('abc').valueOf() // "abc"
new Boolean(true).valueOf() // true

2.2 toString() 

toString方法返回對應的字串形式。

new Number(123).toString() // "123"
new String('abc').toString() // "abc"
new Boolean(true).toString() // "true"

3.原始型別與例項物件的自動轉換 

原始型別的值,可以自動當作包裝物件呼叫,即呼叫包裝物件的屬性和方法。這時,JavaScript 引擎會自動將原始型別的值轉為包裝物件例項,在使用後立刻銷燬例項。

比如,字串可以呼叫length屬性,返回字串的長度。

'abc'.length // 3

 上面程式碼中,abc是一個字串,本身不是物件,不能呼叫length屬性。JavaScript 引擎自動將其轉為包裝物件,在這個物件上呼叫length屬性。呼叫結束後,這個臨時物件就會被銷燬。這就叫原始型別與例項物件的自動轉換。

var str = 'abc';
str.length // 3

// 等同於
var strObj = new String(str)
// String {
//   0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"
// }
strObj.length // 3

上面程式碼中,字串abc的包裝物件提供了多個屬性。

自動轉換生成的包裝物件是隻讀的,無法修改。所以,字串無法新增新屬性。

var s = 'Hello World';
s.x = 123;
s.x // undefined

上面程式碼為字串s添加了一個x屬性,結果無效,總是返回undefined

另一方面,呼叫結束後,包裝物件例項會自動銷燬。這意味著,下一次呼叫字串的屬性時,實際是呼叫一個新生成的物件,而不是上一次呼叫時生成的那個物件,所以取不到賦值在上一個物件的屬性。如果要為字串新增屬性,只有在它的原型物件String.prototype上定義。

4.自定義方法

除了原生的例項方法,包裝物件還可以自定義方法和屬性,供原始型別的值直接呼叫。

比如,我們可以新增一個double方法,使得字串和數字翻倍。

String.prototype.double = function () {
  return this.valueOf() + this.valueOf();
};

'abc'.double()
// abcabc

Number.prototype.double = function () {
  return this.valueOf() + this.valueOf();
};

(123).double()
// 246

 上面程式碼在123外面必須要加上圓括號,否則後面的點運算子(.)會被解釋成小數點。

但是,這種自定義方法和屬性的機制,只能定義在包裝物件的原型上,如果直接對原始型別的變數新增屬性,則無效。

var s = 'abc';

s.p = 123;
s.p // undefined

 上面程式碼直接對字串abc新增屬性,結果無效。主要原因是上面說的,這裡的包裝物件是自動生成的,賦值後自動銷燬,所以最後一行實際上呼叫的是一個新的包裝物件。