首頁>技術>

簡介

基本上所有的程式設計師都使用過javascript,我們在web中使用javascript,我們在伺服器端使用nodejs,js給大家的第一映像就是簡單,但是可能並不是所有人都系統的瞭解過js中的內建物件和資料結構。

今天,一起來看看吧。

基礎型別

js是一種弱型別的動態語言,雖然是弱型別的,但是js本身定義了很多種資料型別。

js中有7種基礎型別:分別是undefined,Boolean,Number,String,BigInt,Symbol和null。

undefined

undefined會自動賦值給剛剛宣告的變數。舉個例子:

var x; //create a variable but assign it no valueconsole.log("x's value is", x) //logs "x's value is undefined"
Boolean和Boolean物件

Boolean的值就是true 或者 false。

除了基礎型別的Boolean值外,還有一個Boolean物件,用來封裝boolean值。

如果是用new Boolean來構造Boolean物件的話,下面的例子中Boolean的初始值都是false:

var bNoParam = new Boolean();var bZero = new Boolean(0);var bNull = new Boolean(null);var bEmptyString = new Boolean('');var bfalse = new Boolean(false);

下面boolean物件的初始值都是true:

var btrue = new Boolean(true);var btrueString = new Boolean('true');var bfalseString = new Boolean('false');var bSuLin = new Boolean('Su Lin');var bArrayProto = new Boolean([]);var bObjProto = new Boolean({});

注意,我們不要使用Boolean物件來進行if條件的判斷,任何Boolean物件,即使是初始值是false的Boolean物件,if條件判斷,都是true:

var x = new Boolean(false);if (x) {  // this code is executed}var x = false;if (x) {  // this code is not executed}

如果非要使用if條件判斷,我們可以使用Boolean函式或者!!如下所示:

var x = Boolean(expression);     // use this...var x = !!(expression);          // ...or thisvar x = new Boolean(expression); // don't use this!
Number和BigInt

Number和BigInt是JS中的兩個數字型別,其中Number表示的雙精度64位二進位制格式,其範圍是-(253 − 1) and 253 − 1.

除此之外,Number還有三個值:+Infinity, -Infinity, 和 NaN。

前面兩個表示的是正負最大值。NaN表示的是 Not-A-Number。

我們可以透過isNaN來判斷是否是一個Number:

function sanitise(x) {  if (isNaN(x)) {    return NaN;  }  return x;}console.log(sanitise('1'));// expected output: "1"console.log(sanitise('NotANumber'));// expected output: NaN

BigInt表示任意精度的整數,使用BigInt可以進行超出Number精度整數的運算。

我們可以透過在整數後面加上n來表示BigInt。

> const x = 2n ** 53n;9007199254740992n> const y = x + 1n; 9007199254740993n

注意,和Boolean一樣,Number和BitInt也有wrapper物件型別。

看下Number的wrapper:

Number('123')  // returns the number 123Number('123') === 123  // trueNumber("unicorn")  // NaNNumber(undefined)  // NaN

看下BitInt的wrapper型別:

const theBiggestInt = 9007199254740991nconst alsoHuge = BigInt(9007199254740991)// ↪ 9007199254740991nconst hugeString = BigInt("9007199254740991")// ↪ 9007199254740991nconst hugeHex = BigInt("0x1fffffffffffff")// ↪ 9007199254740991nconst hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111")// ↪ 9007199254740991n
String

js中的String是不可變的,同樣的String基礎型別也有和它對應的String wrapper物件。

String基礎型別和不使用new的String函式是一致的:

const string1 = "A string primitive";const string2 = String('A string primitive');

上面兩個String是一致的。但是如果使用new來構造String物件,那麼兩者是不一樣的:

let s_prim = 'foo'let s_obj = new String(s_prim)console.log(typeof s_prim) // Logs "string"console.log(typeof s_obj)  // Logs "object"let s1 = '2 + 2'              // creates a string primitivelet s2 = new String('2 + 2')  // creates a String objectconsole.log(eval(s1))         // returns the number 4console.log(eval(s2))         // returns the string "2 + 2"

我們可以透過String物件的valueOf()方法,獲得其String基礎型別。

Symbol

Symbol是一個唯一的不可變的基礎型別,一般用在物件的key中。

// Here are two symbols with the same description:let Sym1 = Symbol("Sym")let Sym2 = Symbol("Sym")console.log(Sym1 === Sym2) // returns "false"

Symbol是不支援new操作的:

let sym = new Symbol()  // TypeError

如果你真的想建立Symbol物件,則可以使用Object():

let sym = Symbol('foo')typeof sym      // "symbol" let symObj = Object(sym)typeof symObj   // "object"
null

null表示引用的是無效的Object物件或者地址。

雖然null可以看做是primitive,但是null其實是一個Object,所有的物件都來自null:

typeof null === 'object' // true
Object

Object是js中的一種資料型別,幾乎所有的物件都繼承自Object,它儲存的是key-value形式的資料,我們可以透過使用Ojbect()方法或者new Object()或者Object字面量的方式來建立Object。

let o = {}let o = {a: 'foo', b: 42, c: {}}let a = 'foo', b = 42, c = {}let o = {a: a, b: b, c: c}

注意使用Object()或者new Object()是一樣的效果,都會得到一個Object物件。

在ES2015之後,我們還可以使用動態的物件屬性:

let param = 'size'let config = {  [param]: 12,  ['mobile' + param.charAt(0).toUpperCase() + param.slice(1)]: 4}console.log(config) // {size: 12, mobileSize: 4}
Function

Function也是一個Object,JS中的所有函式都是Function物件。

(function(){}).constructor === Function

那麼透過Function建構函式和function函式定義創建出來的函式有什麼區別呢?

使用new Function建立的函式,其作用域範圍是global,我們看一下具體的例子:

var x = 10;function createFunction1() {    var x = 20;    return new Function('return x;'); // this |x| refers global |x|}function createFunction2() {    var x = 20;    function f() {        return x; // this |x| refers local |x| above    }    return f;}var f1 = createFunction1();console.log(f1());          // 10var f2 = createFunction2();console.log(f2());          // 20
Date

Date是js中用來操作時間的Object。我們看下Date的常用例子:

let today = new Date()let birthday = new Date('December 17, 1995 03:24:00')let birthday = new Date('1995-12-17T03:24:00')let birthday = new Date(1995, 11, 17)            // the month is 0-indexedlet birthday = new Date(1995, 11, 17, 3, 24, 0)let birthday = new Date(628021800000)            // passing epoch timestamplet [month, date, year]    = ( new Date() ).toLocaleDateString().split("/")let [hour, minute, second] = ( new Date() ).toLocaleTimeString().slice(0,7).split(":")
Array

JS內建了很多種不同型別的Array,最常用的就是Array字面量和Array Object。

我們看下怎麼建立一個Array:

let fruits = ['Apple', 'Banana'];console.log(fruits.length); // 2console.log(fruits[0]);     // "Apple"let fruits = new Array('Apple', 'Banana');console.log(fruits.length); // 2console.log(fruits[0]);     // "Apple"

遍歷Array:

let fruits = ['Apple', 'Banana']fruits.forEach(function(item, index, array) {  console.log(item, index)})// Apple 0// Banana 1

新增Item到Array:

let first = fruits.shift() // remove Apple from the front// ["Banana"]

從前面新增item:

let newLength = fruits.unshift('Strawberry') // add to the front// ["Strawberry", "Banana"]

刪除某個index的item:

let vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot']console.log(vegetables)// ["Cabbage", "Turnip", "Radish", "Carrot"]let pos = 1let n = 2let removedItems = vegetables.splice(pos, n)// this is how to remove items, n defines the number of items to be removed,// starting at the index position specified by pos and progressing toward the end of array.console.log(vegetables)// ["Cabbage", "Carrot"] (the original array is changed)console.log(removedItems)// ["Turnip", "Radish"]

複製array:

let shallowCopy = fruits.slice() // this is how to make a copy// ["Strawberry", "Mango"]

除了Array之外,JS還內建了特定型別的Array:

Int8ArrayUint8ArrayUint8ClampedArrayInt16ArrayUint16ArrayInt32ArrayUint32ArrayFloat32ArrayFloat64ArrayBigInt64ArrayBigUint64Array

這些特定型別的Array中只能儲存特定型別的值。

Keyed collections

除了陣列之外,JS中還有key-value的集合,比如:Map,Set,WeakMap和WeakSet。

對Map來說,我們可以透過使用set,get,has,delete等犯法來對Map進行操作:

let contacts = new Map()contacts.set('Jessie', {phone: "213-555-1234", address: "123 N 1st Ave"})contacts.has('Jessie') // truecontacts.get('Hilary') // undefinedcontacts.set('Hilary', {phone: "617-555-4321", address: "321 S 2nd St"})contacts.get('Jessie') // {phone: "213-555-1234", address: "123 N 1st Ave"}contacts.delete('Raymond') // falsecontacts.delete('Jessie') // trueconsole.log(contacts.size) // 1

遍歷Map:

let myMap = new Map()myMap.set(0, 'zero')myMap.set(1, 'one')for (let [key, value] of myMap) {  console.log(key + ' = ' + value)}// 0 = zero// 1 = onefor (let key of myMap.keys()) {  console.log(key)}// 0// 1for (let value of myMap.values()) {  console.log(value)}// zero// onefor (let [key, value] of myMap.entries()) {  console.log(key + ' = ' + value)}// 0 = zero// 1 = one

使用forEach來遍歷map:

myMap.forEach(function(value, key) {  console.log(key + ' = ' + value)})// 0 = zero// 1 = one

Set中儲存的是唯一的物件。

我們看下Set的操作:

let mySet = new Set()mySet.add(1)           // Set [ 1 ]mySet.add(5)           // Set [ 1, 5 ]mySet.has(1)              // truemySet.delete(1)    // removes 1 from the set

set的遍歷:

// logs the items in the order: 1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2} for (let item of mySet) console.log(item)

WeakMap,WeakSet和Map於Set的區別在於,WeakMap的key只能是Object物件,不能是基本型別。

為什麼會有WeakMap呢?

這種實現有兩個缺點,第一個缺點是每次查詢的時候都需要遍歷key的陣列,然後找到對應的index,再透過index來從第二個陣列中查詢value。

第二個缺點就是key和value是強繫結的,即使key不再被使用了,也不會被垃圾回收。

所以引入了WeakMap的概念,在WeakMap中,key和value沒有這樣的強繫結關係,key如果不再被使用的話,可以被垃圾回收器回收。

因為引用關係是weak的,所以weakMap不支援key的遍歷,如果你想遍歷key的話,請使用Map。

本文連結:http://www.flydean.com/js-built-in-objects-structures/

6
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Java設計模式——命令模式