看不懂的隱式轉換(上)--- 基礎鋪墊

MrZss發表於2019-02-27

前言

看不懂系列 [滑稽.jpg] 最近在找工作,後面的部落格內容也算自己的準備了,嘿嘿 其實自己平常看書的時候,也會發現很多東西講的太官話,有點看不懂 有些資料呢,可能又將的太碎片化了, 所以我經常把書上知識點當做一個擴散點,去擴充套件一些原來不知道的 像這篇,其實講隱式轉換的文章還是比較多,好的也比較多的 但可能我太小白了,有些一筆帶過的內容比如說,原始值,引用值,toString,valueOf這些一筆帶過 所以在講之前先鋪墊鋪墊 講些原理 PS: 小白一個 歡迎吐槽 嘿嘿嘿

原始值和引用值

原始值

儲存在棧(stack)中的簡單資料段,也就是說,它們的值直接儲存在變數訪問的位置。

Undefined、Null、Boolean、Number 和 String 由於這些原始型別佔據的空間是固定的,所以可將他們儲存在較小的記憶體區域 - 棧中。這樣儲存便於迅速查尋變數的值。

引用值

儲存在堆(heap)中的物件,也就是說,儲存在變數處的值是一個指標(point),指向儲存物件的記憶體處。

object,Array , 函式

儲存在變數處的值是一個指標(point),指向儲存物件的記憶體處。

var a = "i am string";
typeof a; // "string"
a instanceof String  //false

var b = new String("i am a string");
typeof b; // "object"
b instanceof String  //true
複製程式碼

WTF ???

WHY ???

一開始看這道題的時候滿臉問號

其實吧 這是因為 "i am string" 他是一個原始值

But

"i am string".length // 8  這些本屬於String的方法卻能被呼叫
複製程式碼

這是應為在必要時。js語言會把字串字面量轉換成String物件。也就是你並不需要顯示的建立一個物件valueOf()

toString valueOf()

toString 使用方法

var x = {};
console.log(x.toString());           
//  [object Object]

//特別的用法
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]

var x = [1,2,3];
x.toString(); //返回'1,2,3'

var x = function(){console.log('lalala')}
x.toString();// 返回'function(){console.log('lalala')}'

var x = 33333;
x.toString();// 返回'33333'
複製程式碼

網上copy的一段示例,接下來詳細瞭解一下toString()常用語法

obj.toString();

這種使用形式可以把除null undefined外,所有物件轉為字串

//boolean型別
true.toString()  //true
false.toString()  // false
//string型別
var str = "stringlalala"
str.toString()  //"stringlalala"
複製程式碼

但是下面出現了一個非常好玩的現象

// Object
var obj = {
    name: "MrZss",
    age: "23"
};
obj.toString(); //[object Object]

// Array
var arr = ["MrZss","23"];
arr.toString();  // "MrZss","23"

//Date
var date = new Date();//
date.toString() //   Wed Feb 27 2019 13:46:35 GMT+0800 (CST)

// Number 
var num = 23;
var num = 23;
console.log(num.toString(2)); //10111 二進位制
console.log(num.toString(8)); //27 八進位制
console.log(num.toString(16)); //17 十六進位制
複製程式碼

問題來了 按理來說 Array Date這些物件toString方法 都是從Object物件繼承來的呀。為什麼表現完全不一樣

友情提醒:Array,RegExp,Date,Number等內建物件中的toString重寫了,用於本身的型別轉化

MDN參考

Object.prototype.toString()

來來來 敲黑板畫重點了

ES6規範描述

看不懂的隱式轉換(上)--- 基礎鋪墊

實在不行就一鍵翻譯吧 [滑稽.jpg]

這一塊我也去搜了搜大佬的資料,看這個理解的比較詳細

Object.prototype.toString()

所以,可以使用Object.prototype上的原生toString()方法判斷資料型別

因為其他物件例如Array,Date的toString方法都沒覆蓋了 所以還是需要使用

Object.prototype.toString.call(value) 來調取

Object.prototype.toString.call(null);//”[object Null]”
Object.prototype.toString.call(undefined);//”[object Undefined]”
Object.prototype.toString.call(“abc”);//”[object String]”
Object.prototype.toString.call(123);//”[object Number]”
Object.prototype.toString.call(true);//”[object Boolean]”
....
就不一一列舉了
可以自己414
複製程式碼

Object.prototype.toString.call、instanceof、typeof又有啥不同呢

typeof undefined //undefined
typeof null //object
typeof true //boolean
typeof 1.11 //number
typeof "lalala" //string
typeof function(){} //function
typeof new Object() //object
typeof new Array()  //object
typeof new RegExp() //object
複製程式碼

typeof 的侷限性

在於 像Array,RegExp,null都會被判斷為object,這就很尷尬了,無法去判斷這些內建物件的具體型別

instanceof 的侷限性

在於你必須知道實際型別和父型別再去判斷對與,,對未知建構函式構造的物件來說無法提前給定,constructor屬性返回的值又不是預期的單純的建構函式名。

Object.prototype.toString 的侷限性

Object.prototype.toString 就非常牛批了,對所有的內建物件都能支援得非常好 唯一不好的地方 自定義的構建的物件,無法通過原型鏈去查父型別

Object.prototype.toString.call('');  //[object String]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); //[object Null]
Object.prototype.toString.call(1111);  // [object Number]
Object.prototype.toString.call(true);  //[object Boolean]
複製程式碼

valueOf

這個方法在Array等物件中也會被覆寫

表現形式如下

先盜一個MDN的圖嘿嘿

看不懂的隱式轉換(上)--- 基礎鋪墊

好了鋪墊完了,待會進入正題

相關文章