最近自己回歸基礎(chǔ)看了下javascript的相關(guān)知識(shí)點(diǎn)丈攒,想著看都看了,寫出來(lái)記錄下足跡也是一件好事授霸,遂記錄~
還有還有巡验,哪位大佬有廣州前端開發(fā)工程師的機(jī)會(huì)推薦一下嗎,簡(jiǎn)歷可以戳blog下的resume.png碘耳,我請(qǐng)你吃糖????
在javascript
中有兩種類型显设,一種是基本數(shù)據(jù)類型,一種是引用類型辛辨。
基本類型
基本數(shù)據(jù)類型捕捂,也稱為簡(jiǎn)單數(shù)據(jù)類型,在ES5
中有以下五種:Undefined斗搞、Null指攒、Boolean、Number和String
僻焚,在ES6
中新增了一種簡(jiǎn)單的數(shù)據(jù)類型Symbol
允悦。
Undefined類型
Undefined類型只有一個(gè)值undefined
。在進(jìn)行相關(guān)變量定義的時(shí)候虑啤,未賦值的情況下隙弛,默認(rèn)是賦值為undefined
了。但是也是有些特殊的情況下會(huì)報(bào)錯(cuò)的狞山。情況我大致羅列下:
# 情況1??:變量聲明了全闷,但是沒(méi)有賦值
var message;
console.log(message); // undefined
# 情況2??:變量聲明并賦值了,但是在console運(yùn)行之后
console.log(message); // undefined
var message = 'find a frontend job in Canton!';
# 情況3??:變量沒(méi)聲明萍启,報(bào)引用報(bào)錯(cuò)
// var message;
console.log(message); // Uncaught ReferenceError: message is not defined
# 情況4??:不通過(guò)var聲明室埋,直接寫變量,報(bào)引用錯(cuò)誤
message; // 不等價(jià) var message;
console.log(message); // Uncaught ReferenceError: message is not defined
# 情況5??:不通過(guò)var聲明伊约,直接寫變量賦值
message = 'find a frontend job in Canton!'; // 默認(rèn)在message前添加了var
console.log(message); // find a frontend job in Canton!
# 情況6??:不通過(guò)var聲明姚淆,直接寫賦值,但是在console運(yùn)行之后屡律,報(bào)引用錯(cuò)誤
console.log(message);
message = 'find a frontend job in Canton!'; // 相當(dāng)于沒(méi)message變量
上面羅列的是ES5
中通過(guò)var
聲明的情況腌逢。也許你會(huì)對(duì)情況2??產(chǎn)生疑惑:我都給message
賦值了啊,但是打印出undefined
超埋,這就有點(diǎn)尷尬了搏讶?
因?yàn)樵趈s中執(zhí)行上下文分為兩個(gè)階段佳鳖,第一個(gè)階段是創(chuàng)建階段
,第二個(gè)階段才是執(zhí)行階段
媒惕。
上面情況2??的執(zhí)行情況如下:
1. 創(chuàng)建階段:
executionContextObj = {
scopeChain: { ... },
variableObject: {
message: undefined
},
this: { ... }
}
2. 執(zhí)行階段:
executionContextObj = {
scopeChain: { ... },
variableObject: {
message: 'find a frontend job in Canton!'
},
this: { ... }
}
詳細(xì)的解析可以看下我之前翻譯的一篇文章JS的執(zhí)行上下文和環(huán)境棧是什么系吩?。
上面講到的是var
妒蔚,我們引入ES6
的let 和 const
來(lái)演示下:
# 情況7??:let聲明變量賦值
let message;
console.log(message); // undefined
# 情況8??:let聲明變量但是不賦值穿挨,在console運(yùn)行之后
console.log(message); // Uncaught ReferenceError: Cannot access 'message' before initialization
let message = 'find a frontend job in Canton!';
# 情況9??:const聲明變量但是不賦值,報(bào)語(yǔ)法錯(cuò)誤
const message;
console.log(message); // Uncaught SyntaxError: Missing initializer in const declaration
let和const
改變了var
命令會(huì)發(fā)生變量提升的現(xiàn)象肴盏,即變量可以在聲明之前使用科盛,值為undefined
。它們改變了這種奇怪的現(xiàn)象菜皂,聲明的變量一定要在聲明之后使用贞绵,否則報(bào)錯(cuò)。
當(dāng)然還有其他聲明變量的方法恍飘,比如function
命令等榨崩,這里不一一列舉,只是探討下undefined
的值而已~
Null類型
Null
類型的值是null
章母。從邏輯角度來(lái)看蜡饵,null
值表示一個(gè)空對(duì)象指針。
如果定義的變量準(zhǔn)備在將來(lái)用來(lái)保存對(duì)象胳施,那么最好就是將變量初始化為null
,而不是其他的數(shù)據(jù)值肢专。這樣舞肆,只要直接檢查null
值就可以知道相應(yīng)的變量是否已經(jīng)保存了一個(gè)對(duì)象的引用。如下面的例子:
if(car != null) {
// 對(duì)car對(duì)象執(zhí)行某些操作
}
undefined
值是派生自null
值的博杖。雖然兩者在==
比較時(shí)候是相等的椿胯,如下:
console.log(null == undefined); // true
當(dāng)變量不確定類型的時(shí)候,可以不用為變量賦值剃根,也就是默認(rèn)賦值undefined
了哩盲。但是如果你知道你的變量要保存對(duì)象但是還沒(méi)有真正保存對(duì)象的時(shí)候就要賦值null
了。
Boolean類型
Boolean
類型在日常生活中使用頻繁了狈醉,其值是true
和false
廉油,對(duì)應(yīng)我們口頭的是
和否
。
將布爾值的true
和false
轉(zhuǎn)換為數(shù)值的話苗傅,可以用非0
和0
數(shù)字表示抒线。
console.log( 1 == true); // true
console.log( 0 == false); // true
如果是恒等的比較方式===
,那數(shù)字表示法是要涼涼的~
Number類型
Number
類型有二進(jìn)制表示法渣慕,八進(jìn)制表示法嘶炭,十六進(jìn)制表示法和十進(jìn)制表示法抱慌。這里只討論十進(jìn)制表示法
,因?yàn)樵谄匠5拈_發(fā)中眨猎,用到十進(jìn)制的情況居多??
這個(gè)類型用來(lái)表示整數(shù)值和浮點(diǎn)數(shù)值(即帶小數(shù)點(diǎn)的值)抑进。
整數(shù)值的基本操作很是簡(jiǎn)單,而且沒(méi)啥bug好說(shuō)睡陪,除非不在Number.MIN_VALUE
和Number.MAX_VALUE
范圍內(nèi)寺渗。帶小數(shù)點(diǎn)的還是要留意下的,比如:
let a = 13.04;
let b = 2.5;
console.log(a + b); // 15.54
console.log(a * b); // 32.599999999999994
console.log(a - b); // 10.54
咦咦宝穗,真是讓人尷尬??户秤,怎么上面代碼中兩個(gè)浮點(diǎn)數(shù)相乘會(huì)出現(xiàn)那么多位的數(shù)字啊,不是等于32.6
嗎逮矛?
所以在進(jìn)行浮點(diǎn)數(shù)的運(yùn)算的時(shí)候還是得慎重點(diǎn)鸡号,先轉(zhuǎn)換成整數(shù)計(jì)算,之后再切換回去浮點(diǎn)數(shù)须鼎,比如上面的a * b
可以考慮寫成(a * 100 * (b * 10))/1000
鲸伴。
當(dāng)你要判斷一個(gè)值是否是數(shù)值,可以使用isNaN
來(lái)表示晋控,其返回一個(gè)布爾值汞窗,如下:
console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false
console.log(isNaN('10'); // false , '10'會(huì)被轉(zhuǎn)化為10
console.log('blue'); // true , 不能轉(zhuǎn)化為數(shù)值
console.log(true); // false, 可被轉(zhuǎn)化為數(shù)值1
還有將非數(shù)值轉(zhuǎn)化為數(shù)值的三個(gè)方法:Number()、parseInt()和parseFloat()
赡译。見(jiàn)名思義:
Number()是將傳入的內(nèi)容轉(zhuǎn)換為數(shù)字(整數(shù))或NaN
仲吏。但是在轉(zhuǎn)換字符串的時(shí)候比較復(fù)雜,一般用parseInt()居多蝌焚。parseFloat()就是轉(zhuǎn)化成浮點(diǎn)數(shù)的方法啦裹唆。
String類型
String
類型也就是字符串類型啦。
字符串類型包含一些特殊的字符字面量只洒,也叫轉(zhuǎn)義序列许帐,用來(lái)表示非打印字符串。比如換行符\n
啦毕谴。
在實(shí)際的開發(fā)中成畦,我們需要將數(shù)字類型或?qū)ο箢愋娃D(zhuǎn)換成字符串類型,那么我們可以直接使用toString()
方法進(jìn)行操作啦涝开。好吧循帐,這api的東西大家都會(huì)用,就不說(shuō)了??
Symbol類型
Symbol
類型是ES6
引入的新類型舀武,為了防止對(duì)象中屬性名沖突的問(wèn)題惧浴。
Symbol
值通過(guò)Symbol
函數(shù)生成。這就是說(shuō)奕剃,對(duì)象的屬性名現(xiàn)在可以有兩種類型衷旅,一種是原來(lái)就有的字符串捐腿,另一種就是新增的Symbol
類型。凡是屬性名屬于Symbol
類型柿顶,就都是獨(dú)一無(wú)二的茄袖,可以保證不會(huì)與其他屬性名產(chǎn)生沖突。
具體的看下阮一峰的es6入門中Symbol部分嘁锯。
上面說(shuō)到的是6種基本的數(shù)據(jù)類型宪祥,還有一種是引用類型。
引用類型
引用類型:當(dāng)復(fù)制保存對(duì)象的某個(gè)變量時(shí)家乘,操作的是對(duì)象的引用蝗羊,但是在為對(duì)象添加屬性時(shí),操作的是實(shí)際的對(duì)象仁锯。引用類型值指那些可能有多個(gè)值構(gòu)成的對(duì)象耀找。
引用類型有這幾種:Object、Array业崖、RegExp野芒、Date、Function双炕、特殊的基本包裝類型(String狞悲、Number、Boolean)以及單體內(nèi)置對(duì)象(Global妇斤、Math)摇锋。
基本包裝類型
這個(gè)有點(diǎn)好玩,咦站超?上面的基本數(shù)據(jù)類型都有String荸恕、Number和Boolean
啦,怎么這里還有這些顷编。是的,上面的基本類型是通過(guò)基本包裝類型來(lái)創(chuàng)建的剑刑。如下:
var s1 = 'find a frontend job in Canton';
var s2 = s1.substring(2);
上面的代碼實(shí)際進(jìn)行了下面的步驟:
(1)創(chuàng)建String類型的一個(gè)實(shí)例媳纬;
(2)在實(shí)例中調(diào)用指定的方法;
(3)銷毀這個(gè)實(shí)例施掏。
上面的三個(gè)步驟轉(zhuǎn)化為代碼如下:
var s1 = new String('find a frontend job in Canton');
var s2 = s1.substring(2);
s1 = null;
(正規(guī))的引用類型和基本包裝類型的主要區(qū)別就是對(duì)象的生存期钮惠。使用new
操作符創(chuàng)建的引用類型的實(shí)例,在執(zhí)行流離開當(dāng)前作用域之前都一直保存在內(nèi)存中七芭。而自動(dòng)創(chuàng)建的基本包裝類型的對(duì)象素挽,則只存在于下一行代碼的執(zhí)行瞬間,然后立即被銷毀狸驳。這意味著我們不能在運(yùn)行時(shí)為基本類型值添加屬性和方法预明。來(lái)看下下面的例子:
var s1 = 'find a frontend job in Canton';
s1.name = 'jia ming';
console.log(s1.name); // undefined
只能通過(guò)基本包裝類的原型來(lái)添加了缩赛,比如改寫toString
方法:
var s1 = 'find a frontend job in Canton';
String.prototype.toString = function() {
console.log('my name is jia ming');
}
console.log(s1.toString()); // my name is jia ming
嗯~苦口婆心介紹了javascript
的數(shù)據(jù)類型,那么下面才是重頭戲撰糠。我們?cè)趯?shí)際的開發(fā)中酥馍,如何識(shí)別不同的數(shù)據(jù)類型呢?
數(shù)據(jù)類型判斷
數(shù)據(jù)類型有上面的7種類型阅酪,其中基本類型是Undefined旨袒、Null、Boolean术辐、Number砚尽、String和Symbol
,還有一種引用類型辉词。引用類型又包含比較多種的對(duì)象必孤,比如Object
、Array
等较屿。
我們首先想到的是通過(guò)typeof
來(lái)判斷隧魄,直接上代碼來(lái)試下吧:
let symbol = Symbol('jia ming');
let str = 'find a frontend job in Canton!';
let flag = true;
let height = 99;
let job;
let obj = null;
console.log(typeof symbol); // symbol
console.log(typeof str); // string
console.log(typeof flag); // boolean
console.log(typeof height); // number
console.log(typeof job); // undefined
console.log(typeof obj); // object
嗯~很ok啦,對(duì)基本的數(shù)據(jù)類型都能判斷到啦隘蝎,這個(gè)null
得到的結(jié)果是object
购啄,你可以當(dāng)成特殊情況來(lái)處理啦 -- 無(wú)中生有,一生萬(wàn)物嘛嘱么。
我們?cè)賮?lái)看下引用類型打印出來(lái)的是什么東東??
let person = {
name: 'jia ming',
info: 'find a frontend job in Canton!',
};
let arr = ['jia ming', 'find a frontend job in Canton!'];
let reg = new RegExp('jia ming', 'g');
let date = new Date();
let fn = () => {
return 'find a frontend job in Canton!';
}
let math = Math.min(2, 4, 8);
console.log(typeof person); // object
console.log(typeof arr); // object
console.log(typeof reg); // object
console.log(typeof date); // object
console.log(typeof fn); // function
console.log(typeof math); // number
咦咦~著實(shí)讓人尷尬啊狮含,這個(gè)為啥那么多object啊,我的小心臟??曼振。我們只是簡(jiǎn)單通過(guò)typeof
校驗(yàn)比較尷尬啊几迄,我們換個(gè)思路,我們來(lái)結(jié)合call
改變下上下文對(duì)象冰评,改寫一個(gè)方法進(jìn)行判斷映胁,如下:
let person = {
name: 'jia ming',
info: 'find a frontend job in Canton!',
};
let arr = ['jia ming', 'find a frontend job in Canton!'];
let reg = new RegExp('jia ming', 'g');
let date = new Date();
function handleType(obj, type) {
if(typeof obj === 'object') {
return Object.prototype.toString.call(obj) === `[object ${type}]`;
}
return false;
}
console.log(handleType(person, 'Object')); // true
console.log(handleType(arr, 'Array')); // true
console.log(handleType(reg, 'RegExp')); // true
console.log(handleType(date, 'Date')); // true
美滋滋,可以實(shí)現(xiàn)區(qū)別判斷的哈甲雅〗馑铮可是上面的基本類型中null也是object
啊,然后是Math類型的typeof也是number
啊抛人,這個(gè)你可以自己做下處理啦。這里就不考慮了~
后話
有哪位大佬推薦下前端開發(fā)的崗位嗎妖枚?base廣州廷臼,關(guān)于我請(qǐng)戳blog下的resume.png。請(qǐng)你吃棒棒糖??
文章首發(fā):https://github.com/reng99/blogs/issues/27
同步掘金:https://juejin.im/post/5cf25097f265da1b8e708733
更多內(nèi)容:https://github.com/reng99/blogs
參考
《JavaScript高級(jí)程序設(shè)計(jì)》