天天看點

js 對象添加屬性和值_JS 資料類型複習筆記 v1.0.0

js 的裝箱和倒箱

js 有六種基本資料類型,分别是 Number、String、Boolean、Null、Undefined、Symbol,它們都隻是簡單的值,沒有方法或者屬性。下面看個例子:

let foo = 520;
foo.toString(); // '520'
// 不會報錯
           

不會報錯的原因是:js 為了友善操作,Number、String、Boolean、Symbol 這四種基本資料類型,也具備“包裝”的能力,這四個也叫 “基本包裝類型” 。

我們在操作經過 typeof 操作後的值為 number、string、boolean、symbol 的字元的時候,js 執行引擎會對它們進行一個裝箱、倒箱的過程。是以上面的

foo.toString()

在背地裡其實是這樣運作的:

(1) 把 520 包裝成 new Number(520) // typeof new Number(520) === 'object'

(2) new Number(520).toString()

(3) 銷毀 new Number(520)

是以,即使這樣寫也不會報錯:

let foo = 2;
foo.property;
           

另外,值得注意的是,這樣寫會報錯:

2.toString()
           

因為 javascript 的解析順序是從左到右,會先解析

2.

。正确的使用方式如下:

(2).toString(); //'2'
           

Array

Array 是 js 語言中經常用到的一種資料格式,特點是有序的鍵值對。從了解的角度,[1,2,3]可以看成{ 0:1, 1:2, 2:3, length:3, [Symbol.iterator]:fn }的另一種表達方式。

javascript 的程式設計中,

我們利用

Object.getPrototypeOf

函數來尋找[]的最原始的原型對象。

Object.getPrototypeOf

會傳回給定對象的原型。如果給定對象沒有原型,則傳回 null 。

是以為了找到[]的原始原型,需要不斷試探,直到傳回值為 null。下面我們寫個簡單的驗證函數:

function getOriginPrototype(obj) {
  let proto = obj;
  while (Object.getPrototypeOf(proto) !== null) {
    proto = Object.getPrototypeOf(proto);
  }
  return proto;
}

getOriginPrototype(Array) === Object.prototype; // true
           

經過上面的驗證,我們得知 array 是被設計成一種特别的對象,它的原型繼承自 Object.prototype。

typeof [] === "object"; // true
[] instanceof Object; // true
           

object 類型的一些缺陷

當你初始化一個對象或者向一個對象添加一個新的鍵值對的時候,javascript 總是會自動地把鍵名轉化成字元串。如:

const foo = { 0: 1 };
foo[0]; // 1
foo["0"]; // 1
           

當然,數組也一樣:

const bar = [1, 2];
bar[0]; //1
bar["0"]; //1
           

是以,es2015 引入了一種新的資料類型,就是 Map。Map 不會對鍵名做任何轉化:

const foo = new Map();
foo.set(0, 1);
foo.set("0", -1);
foo.get(0); // 1
foo.get("0"); // -1
           

null

null 在 javascript 表示“空”、“無”的意思。

typeof null 的值為"object",《javascript 進階程式設計》一書的解釋是 null 是個空的對象的指針。但業界普遍認為這是 javascript 的一個失敗的設計,顯然,typeof null 的值更應該是"null"而不是"object"

undefined

介紹 undefined

undefined 表示“未定義”。

undefined 相對 null,它在 js 扮演的角色要多很多,下面我們用代碼來介紹 undefined:

function sayHello() {
  const foo = "hello world";
}
// 這裡可以認為sayHello的傳回結果為undefined
sayHello(); // undefined

function sayHello() {
  const foo = "hello world";
  return;
}
sayHello(); // undefined

function sayHello(bar) {
  return bar;
}
// bar為undefined
sayHello(); // undefined
           

可以感受到的是,

null

看起來是“主動”的,隻有你手動賦予一個變量的值為

null

,這個變量在記憶體中才會指向

null

;而

undefined

看起來是“被動”的,程式中很多地方,很多變量的值或者函數的運作結果的值會自動指向

undefined

這個記憶體。通常,手動把 undefined 指派給一個變量是沒有意義的。

屬性值為 undefined

我們都知道,一個對象中,未定義的屬性的值為 undefined:

const foo = {};
foo.property; // undefined
           

但我們必須意識到的是,{ a:undefined }和

{ }

意思是不同的,即使它們的屬性a的值都為undefined。下面我們用

Object.getOwnPropertyDescriptor

來了解其中的差別:

const foo = { a:undefined };
Object.getOwnPropertyDescriptor(foo,'a'); // {value: undefined, writable: true, enumerable: true, configurable: true}

const bar = {};
Object.getOwnPropertyDescriptor(bar,'a'); // undefined
           

在javascript程式設計中,

foo

對象會被認為是存在屬性a的,它的值指向

undefined

。但

bar

對象會被認為不存在屬性a。對此,我們用Object.keys來觀察兩者的表現:

const foo = { a:undefined };
Object.keys(foo);  // ["a"]

const bar = {};
Object.keys(bar);  // []
           

是以,當你想删除一個對象的屬性時,你應該使用delete操作符,而不是把undefined賦給屬性。

const foo = { a:1 };
foo.a = undefined;  // not good

delete foo.a; // good
           

繼續閱讀