你不知道的js類型轉化和原型鏈

昨天晚上接到了螞蟻金服的電面。其中有一道題,讓我印象深入,結束以後,我就去查了資料,寫了一篇拙劣的文章來總結。前端

問題

var a = {}; a.__proto__ === ?
複製代碼
var a = 1; a.__proto__ === ?
複製代碼

當時模棱兩可,我知道他們的頂端都是Object.prototype就直接回答這個選項,由於當時內心想着一切不是皆對象嗎,那對象的原型鏈頂端不就是Object.prototype嗎?還有爲何數字有原型鏈?腦子浮現出Functin,Array各類數據類型,可是仍是很是的模糊,回答了以後面試官也沒有繼續追問(可能以爲我不清楚吧),可是這個問題始終是我內心的一個結,查了一些資料後,並對其進行了整理。面試

你們都知道,JavaScript的數據類型分爲兩種,一種是基礎數據類型,另外一種是引用數據類型。瀏覽器

什麼是基礎類型(primitive )?

[A primitive (primitive value, primitive data type) is data that is not an object and has no methods.]沒有屬性和方法的數據。bash

類型轉化

首先咱們看第二個問題,從第二個問題着手來說解,var a = 1; a.__proto__=== ? 去瀏覽器運行下能夠知道,a.__proto__=== Number.prototype, 而後咱們再這樣運行 a.__proto__.__proto__=== Object.prototype獲得的結果居然是true。函數

在前端咱們說了,js分兩種類型,那爲何一個數字(a)的原型鏈頂端是Object的原型?二者是怎麼聯繫的?primitive 不是沒有屬性和方法嗎?哪裏來的原型鏈?ui

原來是這樣的,js是弱語言,若是他發現類型不匹配的時候,他會幹嗎?他會類型轉化(Auto Convert)啊。spa

因此以上的問題變形一下就變成了var a = 1; new Number(a).__proto__=== ?這樣問題就變得很明瞭了,一個Number方法,構造了一個Number的實例,那麼原型鏈確定是Number的原型啊(即Number.prototype)。再者,一個Number方法構造出的實例,必然有原型鏈。既然已是一個實例,就是一個對象,再往上,必然是Object.prtotype。prototype

再看一下栗子。code

var a = "abc";
console.info(a.length);

var b = 1;
console.info(b.toString());
複製代碼

這就是咱們日常一直在使用的,理解上面的問題,你心中確定知道了緣由,爲何a,b是primitive ,可是爲何還有其餘的屬性。也是由於類型的轉化,等同於cdn

var a = "abc";
console.info(new String(a).length);
var b = 1;
console.info(new Number(b).toString());
複製代碼

小結

總結以上,因此,js基礎類型確實和引用類型沒有關係!沒有關係!讓他們發生關係的是!類型轉化。(由於js自身緣由,強行讓他們發生了關係)。而且基礎類型沒有方法,沒有屬性。

因此我以爲那句,js萬物皆對象,真的有點坑人。

原型鏈

可是後來我又想,不是還有一些function,array,date之類的嗎,那些又是什麼,屬於什麼。此次我一併將他們理清楚。還有那些強行發生關係的構造函數,例如Number,String,Boolean,Date?

以上就是我整理的關係以及引用類型的原型鏈走向。

提示(有些不太明白同窗可能會誤會):

(我把Date,Number,Boolean,String歸類到了Function。而剛纔不是說原型鏈上是Objec.prototype麼,那是你要搞清楚方法和new 方法(),方法經過new對象就變成了Object。下面也進行一些證實)

小結

Object只是在js中充當了一個複雜的類型,包含了許多的子集,可是Object和基礎類型仍是屬於平行關係了。

延伸

經過以上的理解,還本身建立了一個用原型鏈對類型判斷的方法。(由於聽說用Object.prototype.toString.call()這樣的實現方式有點醜陋並且奇怪的方法,別人會不明白你寫的是什麼東西。)

var a = null;	
var b = 1;
var c = '1';
var d = undefined;
var g = true;
var e = function (){};
var f = [];
var h = new Date();
var i = {}

function type(a) {
	if(a === null) {
		return 'null';
	}
	if(typeof a === 'number') {
		return 'number';
	}
	if(typeof a === 'string') {
		return 'string'
	}
	if(typeof a === 'undefined') {
		return 'undefined';
	}
	if(typeof a === 'boolean') {
		return 'boolean';
	}
	if(a instanceof Array) {
		return 'array';
	}
	if(a instanceof Date) {
		return 'date';
	}
	if(a instanceof Function) {
		return 'function';
	}
	if(a instanceof Object) {
		return 'object';
	}
}

console.log(type(a)); // null 
console.log(type(b)); // number
console.log(type(c)); // string
console.log(type(d)); // undefined
console.log(type(f)); // array
console.log(type(e)); // function
console.log(type(g)); // boolean
console.log(type(h)); // date
console.log(type(i)); // object
複製代碼

總結

經過以上無非就想說明基礎類型和引用類型的關係,以及各個類型的原型鏈。說的有點亂,若是有不對的地方請提出,我及時更正,以避免帶來誤導。 留下一個問題,若是以上說的你都理解了,那麼你必然知道這個答案。

var a = 1;
a.a = 1;
console.log(a.a);
複製代碼
相關文章
相關標籤/搜索