原文鏈接:https://github.com/vqun/blog/issues/1
- 基本概念
===
1.1 變量
ECMA變量是松散型的妥凳,愛保存啥類型的數(shù)據(jù)都行。變量申明使用的是var,當(dāng)然也可以不用智玻。使用var证膨,申明局部變量,不使用申明全局變量有鹿。不使用var是為JS界所鄙視的旭旭,所以,建議申明變量時(shí)葱跋,帶上var持寄。
function f(){
var x = 1; // x是局部變量,只在f
y = 2; // y是全局變量
}
f();
alert(x); // 報(bào)錯(cuò)
alert(y); // 2(當(dāng)然娱俺,前提是你注釋了上一句話)
變量有三個(gè)階段:申明稍味、賦值和使用。
申明和賦值是兩個(gè)完全不同的概念荠卷,解釋器對于這兩個(gè)階段也是完全不同的模庐,申明是在代碼期(寫代碼時(shí)期,業(yè)界喜歡叫預(yù)編譯還是啥的)僵朗,賦值是在運(yùn)行期赖欣。
var a; // 這是申明
a = 1; // 這是賦值
var b = 2; // 這句話,在代碼期验庙,解釋器只做了var b顶吮;在運(yùn)行期,做了b = 2
這也牽扯一下JS界都喜歡問的一個(gè)題:
alert(c); // undefined
var c = 3;
之所以是undefined粪薛,涉及到了所謂的“Hoisting”(變量提升)悴了。變量提升里說了,變量申明會(huì)被提前,于是乎上述代碼被等同于:
var c;
alert(c);
c = 3;
這其實(shí)是因?yàn)樯昝骱唾x值在兩個(gè)不同階段湃交。
1.2 區(qū)分大小寫
這個(gè)你懂的
1.3 標(biāo)識符
說一點(diǎn)熟空,一般認(rèn)為的標(biāo)識符,是非保留字搞莺,以_息罗、$、字母開頭才沧。實(shí)際上迈喉,還可以是Unicode、ASIIC温圆,因此挨摸,連中文都可以直接作為標(biāo)簽符的,例如:
var 你好 = 1;
alert(你好);
var \u7788 = 2;
alert(\u7788);
上面兩個(gè)都可以正常運(yùn)行岁歉。當(dāng)然得运,這種用寫法在實(shí)際編程里是不推薦的,只是曾經(jīng)有吃飽沒事干的面試官出過這種面試題锅移,算是普及一下
1.4 注釋
兩種注釋風(fēng)格熔掺,和C/C++類似,單行注釋和多行注釋:
// 單選注釋
/*
* 多行注釋
*/
1.5 分號
關(guān)于分號帆啃,編程習(xí)慣就是在語句的結(jié)尾加分號金赦。當(dāng)然塔鳍,如果你想裝逼,好好看ECMA262,里面告訴你了什么時(shí)候要加分號核无,什么時(shí)候不用浮梢。
1.6 關(guān)鍵字和保留字
曾經(jīng)有人問编曼,關(guān)鍵字和保留字有什么區(qū)別靶剑。其實(shí),從實(shí)際角度講呢压怠,因?yàn)槟愣疾粫?huì)去當(dāng)成標(biāo)識符眠冈,所以沒區(qū)別;概念角度講呢菌瘫,關(guān)鍵字是真不能用(加了引號可以)蜗顽,保留字呢,目前可用雨让,以后估計(jì)就不能用了雇盖。
1.7 數(shù)據(jù)類型
五種基本類型+一種引用類型。五種基本類型:Undefined栖忠、Null崔挖、Number贸街、String、Boolean狸相,一種引用類型:Object薛匪。
typeof:這是一個(gè)比較讓人無語的操作符,以致于業(yè)界都不喜歡用它來判斷數(shù)據(jù)類型脓鹃。其實(shí)逸尖,讓人無語,主要是因?yàn)閷ull将谊,array使用typeof時(shí)冷溶,返回的不是期望的“null”和“array”渐白,而是“object”尊浓。這個(gè)其實(shí)沒什么,從理解角度講纯衍,是挺合理的栋齿,null本身就是代表的空對象,array本身在JS里根本沒這個(gè)類型襟诸。當(dāng)然瓦堵,Number、Boolean等直接new出來的歌亲,typeof結(jié)果也是“object”菇用。
1.8 操作符
操作符都有返回值。合理利用這個(gè)返回值陷揪,可以提升你的代碼逼格惋鸥。比如,一般人都這么寫:
var obj = {
"a": {
"name": "hello",
"value": 1
},
"b": {
"name": "world",
"value": 2
}
}, tmp, n, ret = {};
for(var k in obj){
tmp = obj[k];
n = tmp.name;
!!n && ret[n] = tmp;
}
博主喜歡這么裝逼:
var obj = {
"a": {
"name": "hello",
"value": 1
},
"b": {
"name": "world",
"value": 2
}
}, tmp, n, ret = {};
for(var k in obj)
!!(n = (tmp = obj[k]).name) && ret[n] = tmp;
有木有覺得逼格一樣子提升了好幾個(gè)檔次悍缠,連for循環(huán)的花括號都省了卦绣。。飞蚓。其實(shí)滤港,我會(huì)告訴你,只是因?yàn)楹笳叩男阅芨吲颗。晕也庞玫摹?br> 1.9 語句
語句包括:if溅漾、do-while、while著榴、for添履、for-in、label兄渺、break和continue缝龄、with以及switch汰现。除了with,其他的都很簡單叔壤,只要記得JS沒有塊作用域就可以了瞎饲。
關(guān)于with,“with會(huì)在原作用域鏈里插入新的作用域炼绘,影響性能”這句話是JS界里流行的幾句話[1]之一嗅战。確實(shí),因?yàn)樽饔糜蜴湹膯栴}俺亮,with存在性能問題驮捍,不過,很多模版引擎卻用了with來實(shí)現(xiàn)脚曾,如underscoreJs內(nèi)置的template东且,其“編譯”完之后的代碼里,就用了with來遍歷對象本讥,以達(dá)到在模版里直接使用對象的屬性名珊泳。
[1]JS界里流行的幾句話:
1. 變量申明會(huì)被提到最前面
2. eval是邪惡的
3. with會(huì)在原作用域鏈里插入新的作用域,影響性能
1.10 函數(shù)
函數(shù)定義有三種方式:函數(shù)申明拷沸、函數(shù)表達(dá)式和構(gòu)造函數(shù)色查。
// 函數(shù)申明
function f(){
console.log("declaration");
}
// 函數(shù)表達(dá)式
var f = function(){
console.log("expression");
}
// 構(gòu)造函數(shù)
var f = new Function("console.log('constructor')");
函數(shù)申明會(huì)在預(yù)編譯階段就確定,表達(dá)式和構(gòu)造函數(shù)是在運(yùn)行時(shí)確定撞芍。這再牽扯一下業(yè)界面試題喜歡玩的一個(gè)題:
alert(a); // 輸出那個(gè)function
var a = 1;
alert(a); // 輸出1
function a(){
console.log("function")
}
alert(a); // 輸出1
上述代碼中秧了,由于在預(yù)編譯時(shí),function a(){...}確定了序无,因此验毡,在運(yùn)行時(shí),第一個(gè)alert就將這個(gè)函數(shù)申明alert出了愉镰,而第二個(gè)第三個(gè)alert米罚,就很明顯了。