首先明確ECMAscript中的數據類型分爲兩種:基本類型和引用類型javascript
基本類型:即簡單的數據段,都是按值訪問的,即將一個基本類型的數據賦值給另一個變量,是經過將原數據拷貝一份賦值的,兩變量之間互不影響。如圖:java
引用類型:即保存在內存中的對象,按引用訪問,即將一個引用類型的地址賦值給另外一個變量,當該變量改變時,原變量也會隨之改變。如圖:程序員
基本類型有:Undefined
,Null
,Boolean
,Number
,String
;數組
引用類型:
1.第一類:原生對象(ECMAScript自己自帶對象,有程序員在腳本運行環境中建立來使用):app
object
,Array
,Date
,RegExp
,Function
,基於基本類型還衍生出來了三個包裝類型:Boolean
,Number
,String
,每當咱們讀取一個基本數據類型的實例時,後臺都會建立一個對應的基本包裝類型,從而使咱們可使用不是對象的基本類型調用相應的方法。
2.第二類內置對象(JS語言提供的不依賴於執行宿主的對象,如Global,Math)。
3.宿主對象(JS語言提供的任何依賴宿主環境的對象,如IE中的window,WS中的WScript實例,以及任何用戶建立的類)函數
基本包裝類型和引用類型的區別
使用new
操做符建立的引用類型的實例,在執行流離開當前做用域以前都一直保存內存中,而自動建立的基本包裝類型的對象,只存在於一行代碼執行的瞬間,而後當即被銷燬,即咱們不能在運行時爲基本類型值添加屬性和方法。如圖:測試
typeof會判斷數據類型會返回一個字符串
,以下圖this
// Numbers typeof 37 === 'number'; typeof 3.14 === 'number'; typeof Math.LN2 === 'number'; typeof Infinity === 'number'; typeof NaN === 'number'; // 儘管NaN是"Not-A-Number"的縮寫,意思是"不是一個數字" typeof Number(1) === 'number'; // 不要這樣使用! // Strings typeof "" === 'string'; typeof "bla" === 'string'; typeof (typeof 1) === 'string'; // typeof返回的確定是一個字符串 typeof String("abc") === 'string'; // 不要這樣使用! // Booleans typeof true === 'boolean'; typeof false === 'boolean'; typeof Boolean(true) === 'boolean'; // 不要這樣使用! // Symbols typeof Symbol() === 'symbol'; typeof Symbol('foo') === 'symbol'; typeof Symbol.iterator === 'symbol'; // Undefined typeof undefined === 'undefined'; typeof blabla === 'undefined'; // 一個未定義的變量,或者一個定義了卻未賦初值的變量 // Objects typeof {a:1} === 'object'; // 使用Array.isArray或者Object.prototype.toString.call方法能夠從基本的對象中區分出數組類型 typeof [1, 2, 4] === 'object'; typeof new Date() === 'object'; // 下面的容易使人迷惑,不要這樣使用! typeof new Boolean(true) === 'object'; typeof new Number(1) ==== 'object'; typeof new String("abc") === 'object'; // 函數 typeof function(){} === 'function'; typeof Math.sin === 'function';
由以上結果可知typeof
在數組,正則,日期,對象上的判斷並很差,都是返回object
由此能夠引出另外一個判斷方法Object.prototype.toString()
;toString()
方法返回一個描述某對象的字符串
,若是此方法在自定義的對象中未被覆蓋,則toString()返回"[object type]",其中type
是對象類型。在使用toString()
方法檢測對象類型時,經常使用Object.prototype.toString.call()
或Object.prototype.toString.apply()
來檢測,以下代碼:spa
var toString = Object.prototype.toString; toString.call(new Date);//[object Date] toString.call(new String);//[object String] toString.call(Math);//[object Math] toString.call(undefined);//[object Undefined] toString.call(null);//[object Null]
題一:prototype
var y = 1, x = y = typeof x; x;
//out:"undefined",由於x變量提高,故typeof時,不爲null
題二:
(function f(f){ return typeof f(); })(function(){ return 1; });
//out:"number",由於在當即執行函數裏將function(){return 1}
當作實參傳遞給了形參f
,故當f
執行後返回1
,typeof 1
便返回"number"
題三:
var foo = { bar: function() { return this.baz; }, baz: 1 }; (function(){ return typeof arguments[0](); })(foo.bar);
//out:"undefined",考察this
指針,除了ES6的箭頭函數之外,this
指針永遠指向函數執行時的上下文對象,在此處傳入arguments[0]中,this
指向window
對象,故爲undefined
.
//分組選擇符?難道這不是逗號表達式麼?恩,回頭細究~
題六:這個比較好玩
var x = 1; if (function f(){}) { x += typeof f; } x;//
//out:"1undefined",本覺得會是1function
呢,結果看了解析才知道,是由於javascript語言規範的問題,在條件判斷中加入函數聲明,會返回true,然而javascript引擎在搜索時找不到該函數,因此結果爲1undefined
題七:
(function(foo){ return typeof foo.bar; })({ foo: { bar: 1 } });
//out:undefined ,噗,當作"numberl"了,函數裏的foo指向整個對象,然而整個對象並無bar屬性
indtanceof用來判斷某個構造函數的prototype屬性是否存在於要檢測對象的原型鏈上,以下:
// 定義構造函數 function C(){} function D(){} var o = new C(); // true,由於 Object.getPrototypeOf(o) === C.prototype o instanceof C; // false,由於 D.prototype不在o的原型鏈上 o instanceof D; o instanceof Object; // true,由於Object.prototype.isPrototypeOf(o)返回true D.prototype = new C(); // 繼承 var o3 = new D(); o3 instanceof D; // true o3 instanceof C; // true
ps:prototypeObj.isPrototypeOf(object)用於測試一個對象是否存在於另外一個對象的原型鏈上,object爲被搜索原型鏈的對象
ps2:參考文獻中有這樣一個警示,然而我沒看懂...明日回更,歡迎評論指點。