JS入門
一、JavaScript發(fā)展簡(jiǎn)史
JavaScript一種直譯式腳本語(yǔ)言药蜻,是一種動(dòng)態(tài)類型、弱類型替饿、基于原型的語(yǔ)言,內(nèi)置支持類型贸典。它的解釋器被稱為JavaScript引擎视卢,為瀏覽器的一部分,廣泛用于客戶端的腳本語(yǔ)言廊驼,最早是在HTML(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言下的一個(gè)應(yīng)用)網(wǎng)頁(yè)上使用据过,用來(lái)給HTML網(wǎng)頁(yè)增加動(dòng)態(tài)功能。
在1995年時(shí)妒挎,由Netscape公司的Brendan Eich绳锅,在網(wǎng)景導(dǎo)航者瀏覽器上首次設(shè)計(jì)實(shí)現(xiàn)而成。因?yàn)镹etscape與Sun合作酝掩,Netscape管理層希望它外觀看起來(lái)像Java鳞芙,因此取名為JavaScript。但實(shí)際上它的語(yǔ)法風(fēng)格與Self及Scheme較為接近。
為了取得技術(shù)優(yōu)勢(shì)原朝,微軟推出了JScript驯嘱,CEnvi推出ScriptEase,與JavaScript同樣可在瀏覽器上運(yùn)行喳坠。為了統(tǒng)一規(guī)格鞠评,因?yàn)镴avaScript兼容于ECMA標(biāo)準(zhǔn),因此也稱為ECMAScript壕鹉。
二剃幌、CSS與JS的放置位置
-
CSS應(yīng)放在頁(yè)面頂部的
head
中
由于Rendering Tree是由DOM Tree和CSSOM Tree組合成的,html頁(yè)面需要等到CSS解析完后才能完成渲染晾浴,所以CSS應(yīng)放在head標(biāo)簽內(nèi)负乡,優(yōu)先下載解析,以避免頁(yè)面元素由于樣式缺失造成白屏或FOUC怠肋。 -
JS應(yīng)放在
body
的底部
因?yàn)闉g覽器需要一個(gè)穩(wěn)定的DOM Tree結(jié)構(gòu)敬鬓,而且JS中很有可能有代碼直接改變了其結(jié)構(gòu),瀏覽器為了防止出現(xiàn)JS修改DOM Tree笙各,需要重新構(gòu)建的情況钉答,所以就會(huì)阻塞其他的下載和呈現(xiàn)。
將JS放在head
內(nèi)和body
底部的區(qū)別也在于此:若放在head
里面杈抢,由于瀏覽器發(fā)現(xiàn)head
里面有JS標(biāo)簽就會(huì)暫時(shí)停止其他渲染行為数尿,等待JavaScript下載并執(zhí)行完成才能接著往下渲染,而這個(gè)時(shí)候?qū)l(fā)生白屏惶楼;若放在body
底部右蹦,Rendering Tree已經(jīng)完成大部分,所以此時(shí)頁(yè)面有內(nèi)容呈現(xiàn)歼捐,即使遇到JavaScript阻塞渲染何陆,也不會(huì)有白屏出現(xiàn)。
三豹储、JavaScript數(shù)據(jù)類型
- 數(shù)值(number):整數(shù)和小數(shù)
- 字符串(string):字符組成的文本
- 布爾值(boolean):true(真)和false(假)
- undefined:表示“未定義”或不存在贷盲,即此處目前沒有任何值
- null:表示空值,即此處應(yīng)該有一個(gè)值剥扣,但為空
- 對(duì)象(object):各種值組成的集合巩剖。對(duì)象有三個(gè)子類型狹義的對(duì)象(object),數(shù)組(array)钠怯,函數(shù)(function)佳魔。
數(shù)值、字符串晦炊、布爾值稱為原始類型(primitive type)值鞠鲜,即它們是最原始的數(shù)據(jù)類型宁脊,不能再細(xì)分了。而將對(duì)象稱為復(fù)雜類型(complex type)值镊尺,因?yàn)橐粋€(gè)對(duì)象往往是多個(gè)原始類型的值的合成朦佩,可以看作是一個(gè)存放各種值的容器。至于undefined和null庐氮,一般將它們看成兩個(gè)特殊值语稠。
四、typeof與instanceof
-
typeof
用于返回一個(gè)數(shù)據(jù)原始的數(shù)據(jù)類型弄砍。對(duì)于常見的幾大數(shù)據(jù)類型都可以用typeof 數(shù)據(jù)類型
的方式進(jìn)行判斷(其中typeof null 返回的object)仙畦。 -
instanceof
用于判斷某個(gè)對(duì)象是不是構(gòu)造函數(shù)的一個(gè)實(shí)例,即一個(gè)新聲明的變量是不是調(diào)用了構(gòu)造函數(shù)的內(nèi)置屬性或方法音婶。 - 對(duì)于一個(gè)變量a可用如下方法判斷其數(shù)據(jù)類型:
type a === "number" \\判斷a是否為數(shù)字
type a === "string" \\判斷a是否為字符串
type a === "boolean" \\判斷a是否為布爾值
type a === "function" \\判斷a是否為函數(shù)
JS運(yùn)算符
一慨畸、NaN的作用
-
NaN
不是數(shù)值,全稱為Not a Number衣式。它用于表示一個(gè)本來(lái)要返回?cái)?shù)值的操作數(shù)未返回?cái)?shù)值的情況寸士,此時(shí)為了不報(bào)錯(cuò),就會(huì)返回NaN
。 -
NaN
非常特殊,因?yàn)樗安皇菙?shù)字”趣效,所以它不等于任何數(shù)劫扒,包括其自身轩拨,即NaN != NaN
。任何涉及NaN
的操作(如NaN/10
)都會(huì)返回NaN
這個(gè)特點(diǎn)在多步計(jì)算中有可能導(dǎo)致問題。 -
isNaN(testValue)
可檢查一個(gè)參數(shù)是否為數(shù)值,返回true
或false
凡人。
二、==與===
-
==
:相等運(yùn)算符叹阔,但是不比較參數(shù)的類型挠轴,兩邊參數(shù)類型不同時(shí),會(huì)先進(jìn)行類型轉(zhuǎn)化耳幢,再比較值忠荞。 -
===
:嚴(yán)格相等運(yùn)算符,不僅比較參數(shù)的值帅掘,也比較參數(shù)的類型,只有兩者均一致堂油,才返回true
修档。
JS函數(shù)
一、if語(yǔ)句
- if語(yǔ)句的語(yǔ)法:
if(condition) {
statement
}else {
statement
}
其中的 condition可以是任意表達(dá)式府框;而且對(duì)這個(gè)表達(dá)式求值的結(jié)果不一定是布爾值吱窝。如果該位置是非布爾值,JavaScript會(huì)將這個(gè)值自動(dòng)轉(zhuǎn)為布爾值。
- condition判斷:
- 布爾值:直接作出判斷院峡,true為true兴使,flase為false
- 字符串:除了空字符串。
""
為false外照激,其余(包括包含空格字符串" "
)都為true发魄。 - 數(shù)值:除了0(+0、-0俩垃、0.00励幼、00等)與
NaN
為false,其余都為true口柳。 - undefined:轉(zhuǎn)換為false苹粟。
- null:轉(zhuǎn)換為false
- 對(duì)象:轉(zhuǎn)換為true(包括空數(shù)組
[]
與空對(duì)象{}
)
二、==相等操作符
相等操作符==
在比較兩參數(shù)時(shí)跃闹,若參數(shù)類型不一致嵌削,會(huì)先將它們轉(zhuǎn)換成一樣的類型,再比較其相等性望艺。轉(zhuǎn)換規(guī)則如下:
- 若其中一個(gè)為布爾值苛秕,將其轉(zhuǎn)換為數(shù)值,false為0荣茫,true為1想帅;
- 若其中一個(gè)為字符串,另一個(gè)為數(shù)值啡莉,則將字符串轉(zhuǎn)換為數(shù)值港准,只含數(shù)字的字符串轉(zhuǎn)換為相應(yīng)數(shù)字,空字符串或只含空格字符串轉(zhuǎn)換為0咧欣,其余轉(zhuǎn)換為
NaN
浅缸; - 若其中一個(gè)是對(duì)象,另一個(gè)不是魄咕,則調(diào)用對(duì)象的
valueOf()
方法衩椒,用前述規(guī)則進(jìn)行比較;
以下特殊結(jié)果需特別注意:
null == undefined //true
NaN == NaN //false
false == undefined //fales
false == null //false
NaN != NaN //true
三哮兰、switch語(yǔ)句
- switch表達(dá)式如下:
switch(condition){
case 1:
statement1;
break;
case 2:
statement2;
break;
......
case N:
statementN;
break;
default:
statement;
}
switch語(yǔ)句會(huì)把condition與case進(jìn)行對(duì)應(yīng)毛萌,然后執(zhí)行相應(yīng)case的statement。
- break語(yǔ)句會(huì)在程序執(zhí)行case后跳出當(dāng)前的switch喝滞。若當(dāng)前case沒有break阁将,程序會(huì)遍歷當(dāng)前case之后的case并執(zhí)行statement,直到遇見break或遍歷完所有的case右遭,才跳出switch做盅。
四缤削、其他語(yǔ)句的用法
- while的用法:
var i = 5;
while(i>0){
console.log(i);
i--;
}
當(dāng)()
中的條件為true時(shí),程序會(huì)循環(huán)執(zhí)行while中的語(yǔ)句吹榴,直到()
中的條件變?yōu)閒alse亭敢。
- do-while的用法:
var i = 5;
do{
console.log(i);
i--;
}while(i>0)
do-while語(yǔ)句與while語(yǔ)句的用法大致相同,唯一不用的是图筹,do-while會(huì)先執(zhí)行do里的語(yǔ)句帅刀,再判斷while的條件是否滿足。
- for遍歷數(shù)組的方法:
var arr = [3,4,5];
for(var i=0; i<3; i++){
console.log(arr[i])
}
- for-in遍歷數(shù)組的方法:
var arr = [3,4,5];
for(var i in arr){
console.log(arr[i])
}
- break 和 continue 的用法:
for(var i = 0; i< 6; i++){
if(i % 4 === 0){
break;
}
console.log(i);
}
for(var i = 0; i< 6; i++){
if(i % 4 === 0){
continue;
}
console.log(i);
}
其中break語(yǔ)句會(huì)跳出整個(gè)循環(huán)婿斥,因此結(jié)果為不輸出劝篷;continue語(yǔ)句會(huì)跳出當(dāng)前循環(huán),執(zhí)行下一循環(huán)民宿,因此結(jié)果為1 2 3 5娇妓。
JS作用域鏈與引用類型
一、立即執(zhí)行函數(shù)
- 立即執(zhí)行函數(shù)就是聲明一個(gè)函數(shù)并馬上調(diào)用它活鹰,
function
前后必須用小括號(hào)包裹起來(lái)哈恰。其語(yǔ)法如下:
( function(){
函數(shù)體
} ) ()
- 立即執(zhí)行函數(shù)只有一個(gè)作用:創(chuàng)建一個(gè)獨(dú)立的作用域,這個(gè)作用域里面的變量外面訪問不到(即避免變量污染)志群。
二着绷、作用域與作用域鏈
作用域
JS的作用域可分為全局作用域、函數(shù)作用域和塊級(jí)作用域:
- 全局作用域:在全局對(duì)象(window)中聲明的變量和函數(shù)具有全局作用域锌云,程序的所有部位都可見荠医。
- 函數(shù)作用域:在一個(gè)函數(shù)內(nèi)部聲明的變量和函數(shù)具有局部作用域,只在函數(shù)內(nèi)部可見桑涎,若在函數(shù)外部訪問會(huì)返回undefined彬向。這里注意一點(diǎn):帶參的函數(shù),參數(shù)列表中的參數(shù)也相當(dāng)于是聲明了的局部變量攻冷,在函數(shù)內(nèi)部不需要再次聲明娃胆,直接調(diào)用即可。若函數(shù)對(duì)象中和全局對(duì)象中同時(shí)對(duì)一個(gè)變量聲明/賦值等曼,在函數(shù)內(nèi)部以函數(shù)內(nèi)的聲明/賦值為準(zhǔn)里烦。
- 塊級(jí)作用域:用
let
/const
聲明的變量只在{}
塊級(jí)符號(hào)內(nèi)部可見(es6新特性)。且const
是聲明一個(gè)常量禁谦,在作用域內(nèi)部不能改變胁黑,否則會(huì)報(bào)錯(cuò)。
作用域鏈
- 函數(shù)在執(zhí)行的過程中州泊,先從自己內(nèi)部找變量
- 如果找不到丧蘸,再?gòu)?strong>創(chuàng)建當(dāng)前函數(shù)所在的作用域去找, 以此往上
- 注意找的是變量的當(dāng)前的狀態(tài)
可看如下例子:
var a = 1
function fn1(){
function fn2(){
console.log(a)
}
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
var fn = fn1()
fn() //輸出2
var a = 1
function fn1(){
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
function fn2(){
console.log(a)
}
var fn = fn1()
fn() //輸出1
var a = 1
function fn1(){
function fn3(){
function fn2(){
console.log(a)
}
fn2()
var a = 4
}
var a = 2
return fn3
}
var fn = fn1()
fn() //輸出undefined