ES5-數據類型補充

本篇主要是對ES5中常見的數據類型進行一些補充和說明html

基本數據類型

常常被問及一些基本的數據類型,我也不打算深刻研究,某個數據究竟在內存中是怎麼樣存儲的。 JavaScript是一門弱類型的語言,JavaScript變量的類型取決於變量值的類型。正則表達式

你須要知道的一些基本數據類型express

  • number 數字
  • string 字符串
  • boolean 布爾
  • undefined Undefined未定義
  • null null空值

使用運算符 typeof 對以上進行運算你會發現除了null爲object以外,其餘都是對應的字符串形式 number,string,boolean都有其對應的包裝函數 Number,String,Boolean編程

在我本身的定義中,對象是鍵值對的組合,是一個詞典,因爲Function也能存儲對應的屬性,故我將其歸結到Object類型,因此,除了以上五種以外,也就還剩Object類型數組

使用方式

// 直接量形式使用便可
var _num = 1;
var _str = "string";
var _bool = true;
var _null = null;
var _undefined = undefined;
複製代碼

對number的說明:因爲數字是能夠帶小數的,故還可能有如下形式bash

var num = .1;   // or: var num = 1.;
複製代碼

引用數據類型

對C有了解的可能就會知道,有些變量存儲單元是對應的直接值,而有些存儲單元存儲的某個內存地址,地址所指向的位置就是其真實的數據存儲的位置(以上不考慮堆棧中的其餘數據和狀態所表示的結構)。數據結構

基本類型和引用類型的異同

我沒有特別詳盡的語言去概述基本類型和引用類型的異同ide

  • 基本類型是按值訪問的,且不能更改基本類型的值,好比你不可能把5改爲6吧
  • 基本類型是在序列中直接能夠進行大小比較的,好比 5 > 4
  • 基本類型是存儲在棧內存中的
  • 引用類型是存儲在棧內存和堆內存中的,是按引用訪問的
  • 引用類型的值是可變的
    var obj = {};
    obj.name = "newName"
    複製代碼
  • 引用類型相互比較的時候,只能比較地址是否同樣

若是咱們本身不搞事情,typeof能夠區分function和其餘引用類型,經過instanceof運算符也能推斷出某個對象是不是某個構造函數的實例,經過Object.prototype.toString能精確獲取。可是在ES6中,若是本身要放炸彈:Symbol.hasInstance -> instanceof,Symbol.toStringTag -> Object.prototype.toString,也請儘可能考慮一下爆炸的範圍函數

// 盜用jQuery中的各類類型校驗函數
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
複製代碼

常見引用類型

Object 普通對象

咱們常常看到的多數是Object的實例,即直接由函數Object構造調用而來的實例post

var obj = {};   //直接量形式
obj = new Object();
obj = Object(); // 這種形式對不一樣的參數會有不一樣的處理,參見如下說明
// 如下方式我也寫一下
obj = eval('({})');
obj = new Function('return {}')();
複製代碼

Date 日期操做

常使用的日期的操做,這個我以爲查文檔可能會更好,我比較喜歡moment.js這個庫。

RegExp

正則表達式:var expression = /pattern/flags; 具體也本身查文檔更好,推薦查看犀牛書。我也把本身的記錄分享出來

ES3中規定,一個正則表達式直接量會在執行到它時轉換爲RegExp對象,同一段代碼所表示的正則表達式直接量的每次運算都返回同一個對象
ES5與ES3相反,每次都返回新的對象

直接量字符
    ^ $ . ? * + = ! : | \ / () [] {}	\t \n...
字符類
    [...] [^...] . \w \W \s \S \d \D [\b]
重複
    {n, m} {n,} {n} * + ?(可選)
    非貪婪重複:儘量的多的匹配字符,若不須要,則只須要在上述重複後面添加 '?'
    注意:正則表達式的模式匹配老是會尋找字符串中第一個可能匹配的位置
        例: /a+?b/ -> 'aaab'	該匹配從第一個字符開始,因此全匹配
選擇、分組、引用
    | 用於分隔供選擇的字符,選擇項的嘗試匹配是從左到右,直到發現匹配項,一旦左邊匹配,就會忽略右邊
    () 
        用於將單獨的項組合成子表達式;
        在完整的模式中定義子模式,能夠進行抽取
        表達式(?:...)只是分組,而不會生成引用,即分組不會編碼
指定匹配位置
    \b匹配單詞邊界,位於\w \W之間的邊界or單詞與字符串的開始或結尾之間的邊界(匹配發生的合法的位置) ^ $
    \B將把匹配的錨點定位在不是單詞邊界的地方 /\B[Ss]cript/ == JavaScript|postscript !=script|Scripting
    任意表達式均可以做爲錨點條件
        (?=) 先行斷言
        (?!) 負先行斷言
    錨字符
        ^		匹配字符串開頭,多行檢索中,匹配一行的開頭
        $		..........結尾
        \b 		匹配一個單詞邊界,注意 [\b]匹配的是退格符
        \B 		匹配非單詞邊界位置
        (?=p)	零寬正向先行斷言,要求接下來的字符都與p匹配,但不能包括匹配p的那些字符
        (?!p)	零寬負向........,要求............不與p匹配,...
複製代碼

Array 數組類型

數組類型:存放一組值的數據結構,對其基本的操做和函數須要牢記於心

構造函數的說明:參數若是隻有一個,且是數字則表示長度,其餘則做爲元素,ES6中Array.of和Array.from對其進行了補充的操做

會改變數組的操做:pop/push、shift/unshift、splice
遍歷:forEach、some、every、filter、map、reduce/reduceRight
其餘操做:slice、concat、sort、indexOf、lastIndexOf

filter、map、reduce是函數式中針對集合編程的基礎:數據流+高階函數

Function 函數類型

ES5中所見的函數都由Function構造調用而來,依據官方說明,函數的產生式有以下形式

  1. 函數聲明:function Identifier(FormalParameterList){FunctionBody}
  2. 匿名函數表達式:function(FormalParameterList){FunctionBody}
  3. 命名函數表達式:function Identifier(FormalParameterList){FunctionBody}

基本包裝類型

爲了便於操做基本類型的值,ECMAScript提供了三種特殊的引用類型:Number、String、Boolean

var _num = new Number(1);   // 千萬不要省略new運算符,不然是作類型轉換
var _str = new String("string");
var _bool = new Boolean(true);

// 對Object函數調用時的說明
console.info(Object(1));
console.info(Object("string"));
console.info(Object(true));
// 對以上三種基本數據,會返回對應的包裝類型

// 當參數是null、undefined時直接生成一個新的對象
console.info(Object(null));
console.info(Object(undefined));

// 當參數是引用類型時直接返回該引用
console.info(Object({key: 'value'}));
複製代碼

探究自動包裝的特徵
後臺隱式建立對應包裝對象,在這個實例上調用指定方法,最後銷燬這個實例

String.prototype.getSelf = function(){
    return this;
};
var result = "string".getSelf();
console.info(result, typeof result);    //String{"string"} "object"
// delete String.prototype.getSelf;

var num = 1;
console.info(num instanceof Number);    // false
// console.info("toString" in num); // in 不能用在基本類型上

Number.prototype.getFn = function(){}

// 12.6.4 for-in 語句
// 產生式 IterationStatement : for ( LeftHandSideExpression in Expression ) Statement 按照下面的過程執行 :
// 1. 令 exprRef 爲解釋執行 Expression 的結果 .
// 2. 令 experValue 爲 GetValue(exprRef).
// 3. 若是 experValue 是 null 或 undefined,返回 (normal, empty, empty).
// 4. 令 obj 爲 ToObject(experValue).
for(var attr in 1){
    console.info(attr); // getFn
}

 // 對此的說明存在於 規範12.10中對產生式with中進行數據類型轉換
with(1){
    console.info(getFn);    // 輸出函數
}
複製代碼

總結:當基本類型數據在作存取運算時,會發生自動轉換爲包裝對象的操做

內置對象類型:global/window、Math

提供的對應的可操做方法 請自行查閱文檔

valueOf、toString、toPrimitive的說明

ToPrimitive抽象操做:將參數轉爲非對象類型,檢查該值是否有 valueOf() 方法。若是有而且返回基本類型值,就使用該值進行強制類型轉換。若是沒有就使用 toString()的返回值(若是存在)來進行強制類型轉換。

var _valueOf = Number.prototype.valueOf;
Number.prototype.valueOf = function(){
    console.info("valueOf", typeof this);    //"object"
    var result = _valueOf.call(this);
    console.info("valueOf-result", result, typeof result);  // 原始值
    // return this;
    return result;
};
var _toString = Number.prototype.toString;
Number.prototype.toString = function(){
    console.info("toString", typeof this);
    var result = _toString.call(this);

    console.info("toString-result", result, typeof result); // 原始值的字符串形式
    return _toString.call(this);
};
var _num = new Number(true);
console.warn(100 + _num);
複製代碼

object -> string
1. 調用toString方法,若是返回一個原始值,將這個值轉爲String並返回
2. 沒有toString or 返回的不是原始值,調用valueOf
3. JavaScript沒法從toString或者valueOf方法獲取一個原始值,拋出一個類型異常

object -> number
1. 調用valueOf,若是返回一個原始值,轉爲number並返回
2. 調用toString,若是返回一個原始值,轉爲number並返回
3. 不然拋出異常

類型 valueOf返回值 備註 toStrig返回值
Boolean 對應的基本類型 對應基本類型值的字符串形式
Number 對應的基本類型 對應基本類型值的字符串形式
String 對應的基本類型 對應基本類型值的字符串形式
Array 數組 引用類型 Array.toString一致
Function 函數 引用類型 function的字符串表示形式
Object 對象 引用類型 '[object Object]'
RegExp 正則對象 引用類型 字面量字符串形式
Error error對象 引用類型

數據類型變換

通常轉換形式:

ToString:非字符串到字符串的轉換

普通對象,除非自定義toString函數,不然調用內置的toString進行轉換;其餘對象強制類型轉換,請參考上述

ToNumber:

true: 1, false: 0, "":0, null: 0, undefined: NaN
對象類型轉換,則調用抽象操做ToPrimitive

ToBoolean:

全部假值 :undefined null false 0 -0 NaN "" 爲false,非假值都是true

顯示強制類型轉換

  1. 字符串和數字的相互轉換:Number、String(沒有new關鍵字)
  2. 顯示函數解析數字字符串:parseInt/parseFloat
  3. 顯示轉換爲布爾值:Boolean構造函數,運算符!、&&、||都是直接轉換

隱式類型轉換

  1. 字符串和數字之間的隱式類型轉換

    若是某個操做數是字符串或者可以經過如下步驟轉換爲字符串的話, + 將進行拼接操做。
    若是其中一個操做數是對象(包括數組)

    首先對其調用ToPrimitive 抽象操做(規範 9.1 節),
    該抽象操做再調用 [[DefaultValue]] (規範 8.12.8節),以數字做爲上下文

    運算符+和String轉換區別

    ToPrimitive抽象操做 在運算符+時,先調用valueOf,而後調用toString 而String顯示轉換時,直接調用toString

  2. 布爾值到數字隱式類型轉換 true -> 1 false -> 0

  3. 隱式強制類型轉換爲布爾值
    if/for/while/do..while的條件判斷
    ?..:.. && ||

  4. || 和 &&
    選擇器運算符,返回值並不必定是布爾類型,而是兩個操做數其中一個的值

寬鬆相等和嚴格相等

== 容許在相等比較中進行強制類型轉換,而 === 不容許

11.9.3.1 的最後定義了對象(包括函數和數組)的寬鬆相等 == 。兩個對象指向同一個值時即視爲相等,不發生強制類型轉換
11.9.3 節中還規定, == 在比較兩個不一樣類型的值時會發生隱式強制類型轉換,會將其中之一或二者都轉換爲相同的類型後再進行比較

1.1 字符串和數字
(1) 若是 Type(x) 是數字, Type(y) 是字符串,則返回 x == ToNumber(y)的結果。
(2) 若是 Type(x) 是字符串, Type(y) 是數字,則返回 ToNumber(x) == y的結果。

1.2 其餘類型和布爾值
(1) 若是 Type(x) 是布爾類型,則返回 ToNumber(x) == y 的結果;
(2) 若是 Type(y) 是布爾類型,則返回 x == ToNumber(y) 的結果。

1.3 null和undefined比較
(1) 若是 x 爲 null , y 爲 undefined ,則結果爲 true 。
(2) 若是 x 爲 undefined , y 爲 null ,則結果爲 true 。

1.4 對象和非對象比較
(1) 若是 Type(x) 是字符串或數字, Type(y) 是對象,則返回 x == ToPrimitive(y)的結果;
(2) 若是 Type(x) 是對象, Type(y) 是字符串或數字,則返回 ToPromitive(x) == y的結果。
封裝對象會自動進行拆封

簡記:boolean->number, string->number, null等於undefined, 對象類型轉爲基本類型

console.info([] == 0);  // true
console.info(false == []);  // true
console.info(null == 0);    // false
console.info([] + 1);   // "1"
console.info({} + 1);   // 1 :由於js在執行過程當中語句優先,{}被解析爲代碼塊
console.info([] + {}, {} + []); // 多少本身慢慢能夠分得清楚了
複製代碼

抽象關係比較

比較雙方首先調用 ToPrimitive ,若是結果出現非字符串,就根據 ToNumber 規則將雙方強制類型轉換爲數字來進行比較。 若是比較雙方都是字符串,則按字母順序來進行比較

參考資料:
《You Don't Know JS: Types & Grammar》中卷
《JAVASCRIPT 語言精髓與編程實踐》
《JavaScript 高級程序設計》
《JavaScript 權威指南》
《ES5文檔》(www.ecma-international.org/ecma-262/5.…)

相關文章
相關標籤/搜索