js基礎(chǔ)-類型、值和變量(下)

pic-2017-10-17.jpg

15兰粉、變量

首先故痊,我們需要了解一下變量的定義:

變量是存儲信息的容器。

為什么需要變量呢玖姑,不止js里面愕秫,程序里面的數(shù)據(jù)來源都要有根有據(jù),比如

alert(a);

為什么會發(fā)生錯誤呢焰络,a是什么東西戴甩,有聲明過了嗎,所以也就需要變量來存儲數(shù)據(jù)了闪彼,讓數(shù)據(jù)來源有根據(jù)甜孤,而不是無中生有(當(dāng)然也有特殊情況,下面我們在討論)畏腕。在js程序中缴川,如果我們使用變量之前會先聲明變量。

變量的聲明用var關(guān)鍵字描馅。
var a="";
var b=true;
var fn=function(){ //dosomething}
var date=new Date();
var obj={};
var arr=[];
var num=123;
var nullStr=null
var uf=undefined;
var pat= /\d+/;//匹配一個或多個數(shù)字

比如從上面可以看出把夸,變量的類型是任意的,js是弱類型語言铭污,js的變量可以是任意類型的恋日。
上面代碼,多數(shù)用到var嘹狞,我們可以簡寫多個變量聲明的方式谚鄙,比如

var a=1;
var b=2;//等價于var a=1, b=2;

值得注意的是:如果圍在var什么語句中給變量賦值,也就是只是聲明了刁绒,但沒有值闷营,那么在給這個變量賦值之前,這個變量的值是undefined

var a;console.log(a); //undefined

這里涉及到了變量的什么提前的知識,有興趣的可以參考我之前寫的文章js(四):提升傻盟。這里我們不深入研究下去速蕊。
當(dāng)我們使用var對同一變量重復(fù)聲明是沒問題的;

var a=1;
var a=2;
var a=3;

這種重復(fù)聲明和賦值有點類型我們css中娘赴,同名選擇器的時候规哲,后面的樣式會覆蓋前面的屬性。

但是要記得的是诽表,給一個沒有什么過的變量賦值唉锌,在非嚴格模式下是沒有錯誤的,但是在嚴格模式下會報錯竿奏。

a=2;
console.log(a);
"use strict";
a=2;console.log(a);

上面例子袄简,一個在非嚴格模式下執(zhí)行的時候,a會變成window下的屬性泛啸,也就是全局變量绿语。

另一個在嚴格模式下執(zhí)行,程序會報錯候址。
因此吕粹,我們寫代碼的時候,應(yīng)該始終使用var來聲明變量岗仑。(關(guān)于這些知識匹耕,都涉及到了js更加深層次的知識與原理性的東西,以后我們會詳細來研究)

既然我們用var聲明了變量荠雕,那么這些變量的作用范圍泌神,我們可以先理解為變量的作用域了。

在全局作用域中聲明的變量是全局變量舞虱,相對的也有局部變量欢际。類似

var win="window"
function fn(){ 
      var win="obj"; 
      console.log(win);
}
console.log(win);
fn();
console.log(win);

在上面例子中我們假設(shè),win所處的環(huán)境是全局環(huán)境矾兜,那么win就是全局變量歌焦,并且變量win的值為'windoq',而在函數(shù)fn里面的win變量所處于函數(shù)fn的局部環(huán)境中冤灾,所有里面的win是局部變量,第一個輸出和第二個輸出我們是毫無疑問的,第三個再次輸出win也是全局的洋魂,因為兩個所處不同環(huán)境的兩個分別用var定義的win變量是不一樣的正什。我們改一下代碼可以看出區(qū)別:

var win="window";
function fn(){ 
      win="obj"; //改動地方 沒有用win聲明 
      console.log(win);
}
console.log(win);
fn();
console.log(win);

同名屬性甲棍,在局部中沒有用var什么迟螺,但是賦值了,也就相當(dāng)于改變了全局作用域下的同名屬性的值荆萤,所有執(zhí)行函數(shù)fn后镊靴,win的值被改變了铣卡。

(值得注意的是,前面說過:在嚴格模式下偏竟,給未經(jīng)聲明的變量賦值會包類型錯誤煮落,這個例子就算在嚴格模式下也不會保存,因為win已經(jīng)在全局作用域下用var聲明過了踊谋,函數(shù)體內(nèi)僅僅只是賦值操作)蝉仇。

15、函數(shù)作用域和聲明提前

塊級作用域

在一些強類型編程語言中殖蚕,比如C,花括號{}內(nèi)的每一段代碼都有各種的作用域轿衔,而且變量在聲明他們的代碼段之外是不可見的,這就是塊級作用域睦疫,而js在ES6之前的js版本是沒有塊級作用域的害驹。這里我們先不涉及到ES6的知識,后面我們再詳細了解笼痛。所以取而代之地使用了函數(shù)作用域裙秋。 變量再聲明他們的函數(shù)體以及這個函數(shù)體嵌套的任何函數(shù)體內(nèi)都是有定義的琅拌。例如

function foo(){
       var a=1; //這里面的變量只有再函數(shù)里面才可以訪問
       var b=2;
}

js的函數(shù)作用域是指函數(shù)內(nèi)聲明的所有變量再函數(shù)體內(nèi)始終可見缨伊,這意味這變量再聲明之前甚至已經(jīng)可用。js的這個特性別非正式的稱為聲明提前进宝,即js函數(shù)里聲明的變量(但不涉及復(fù)制)都被“提前"只函數(shù)體的頂部刻坊。我們直接看代碼

var a="global"; //全局變量、
function foo(){ 
      console.log(a);
      var a="local" //局部變量 
      console.log(a);
}

第一個console.log輸出什么党晋?是undefined谭胚,而不是global或者local,而第二個毫無疑問是local了未玻。
上述過程等價與:將函數(shù)內(nèi)的聲明提前至函數(shù)頂部灾而,同時變量初始化留在原來的位置,有興趣深入了解原理的同學(xué)可以參考我寫的文章提升扳剿。

由于js沒有塊級作用域旁趟,因此我們常常可以見到別人寫代碼的時候?qū)⒆兞柯暶鞣旁诤瘮?shù)體頂部庇绽,而不是將聲明靠近放在使用變量之外锡搜。這種做法使得他們的源代碼非常清晰地反應(yīng)真實的變量作用域

function foo(){
       var iTarget=null; //現(xiàn)在函數(shù)體頂部聲明 
        ....
       iTarget=.... //只用用與賦值等等操作了
}
作為屬性的變量

當(dāng)聲明一個JavaScript全局變量時,實際上是定義了全局對象的一個屬性瞧掺。當(dāng)使用var聲明一個變量時耕餐,創(chuàng)建的這個屬性是不可配置的,也就是說這個變量無法通過delete運算符刪除辟狈〕Φ蓿可能你已經(jīng)注意到了,如果你沒有使用嚴格模式并給一個未聲明的變量賦值的話,JavaScript會自動創(chuàng)建一個全局變量桩砰。以這種方式創(chuàng)建的變量是全局對象的正常的可配值屬性拓春,并可以刪除它們:

var a = 1; // 聲明一個不可刪除的全局變量
 b = 2; // 創(chuàng)建全局對象的一個可刪除的屬性 ,(在嚴格模式下會報錯)
this.c = 3; // 同上 delete a // => false: 變量并沒有被刪除 delete b // => true: 變量被刪除 
delete this.c // => true: 變量被刪除

為什么使用var的變量就不可配置了,這個涉及到了屬性的特性的知識亚隅,有興趣的朋友可以查下資料了解和深入下硼莽,這里我們簡單的了解一下:

  1. 作為對象,每個屬性(變量)下都有幾個屬性(屬性的特性)煮纵,其中configurable,這個屬性確定了屬性(變量)名字能否更改懂鸵,變量能否被刪除。true的話行疏,可以更改匆光,可刪除;反之酿联,不能更改终息,不能刪除。
  1. 在用var 聲明變量時贞让,JS解析器會默認把configurable設(shè)為false周崭,所以它不能改名字,不能被刪掉喳张。

js全局變量是全局對象的屬性续镇,上面在非嚴格模式下,this在全局下指向的是全局對象销部,(關(guān)于this指向這個知識摸航,我們以后再來詳細探討)也就是window。

作用域鏈

簡單的說舅桩,作用域就是變量與函數(shù)的可訪問范圍酱虎,即作用域控制著變量與函數(shù)的可見性和生命周期。在JavaScript中擂涛,變量的作用域有全局作用域和局部作用域兩種读串。在學(xué)習(xí)作用域鏈之前,我們簡單看幾個例子了解下全局作用域和局部作用域歼指。

全局作用域
var a="window";
functin a(){ //dosomethind}

假設(shè)上面代碼代碼的最頂級的位置(也就是沒有任何函數(shù)嵌套爹土,所有當(dāng)前的作用域就是全局作用域),全局作用域就是在全局環(huán)境下變量與函數(shù)的可訪問范圍踩身,這個范圍就是控制著變量和函數(shù)的可見性和聲明周期胀茵,任何在全局作用域下的都可以訪問到全局變量a和全局函數(shù)a(),

局部作用域
function b(){ 
      var foo="123"; 
      function bar(){
             //dosomething
       }
}
console.log(foo) //報錯 bar() 報錯

我們知道,js里面函數(shù)也是對象挟阻,在函數(shù)花括號{}里面的定義的變量琼娘、函數(shù)等峭弟,我們在函數(shù)外面是訪問不到的,這就是函數(shù)的局部作用域脱拼。和全局作用域相反瞒瘸,局部作用域一般只在固定的代碼片段內(nèi)可訪問到,最常見的例如函數(shù)內(nèi)部熄浓,所有在一些地方也會看到有人把這種作用域稱為函數(shù)作用域情臭。

局部作用域擁有對全局作用域的訪問權(quán)限,在函數(shù)嵌套中赌蔑,被嵌套的函數(shù)擁有對外層函數(shù)作用域的訪問權(quán)限俯在,比如

//全局作用域
function foo(){
       var a=1; //foo函數(shù)作用域(局部作用域) 
       function bar(){
             var b=2; 
             function fn(){
                   var c=3 
             }
         }
}

上面函數(shù)里面嵌套了多層函數(shù),a娃惯、bar()是foo的局部變量跷乐,以此類推,變量c在fn()定義,fn()的作用域包含著fn()花括號{}里面的作用域趾浅、bar()愕提、foo()和全局作用域,在fn中可以訪問到變量它的外層作用域包括全局作用域皿哨,以此類推浅侨。

但是全局作用域不能訪問到變量a以及所嵌套的標識符(變量、函數(shù)往史,對象等)仗颈,我們把作用域想象成一條線條佛舱,他們組成了一個單向的椎例,由內(nèi)而外的線,如



圖中请祖,黃色的線的箭頭代表可以訪問的作用域订歪,他們形成一系列的鏈條就是作用域鏈了(本人理解),作用域鏈定義了一系列作用域嵌套時候肆捕,變量與函數(shù)的可見性和生命周期刷晋。

當(dāng)定義一個函數(shù)時,它實際上保存一個作用域鏈慎陵。當(dāng)調(diào)用這個函數(shù)時眼虱,它創(chuàng)建一個新的對象來存儲它的局部變量,并將這個對象添加至保存的那個作用域鏈上席纽,同時創(chuàng)建一個新的更長的表示函數(shù)調(diào)用作用域的“鏈”捏悬。對于嵌套函數(shù)來講,事情變得更加有趣润梯,每次調(diào)用外部函數(shù)時过牙,內(nèi)部函數(shù)又會重新定義一遍甥厦。

js基礎(chǔ)-類型、值和變量到這里了寇钉。
如有錯誤刀疙,歡迎批評,對本文有什么不理解的地方話也可以留言評論交流IǔG怼!
原創(chuàng)文章by zhengyepan
歡迎訪問我的個人網(wǎng)站zhengyepan.com
歡迎討論交流~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撵溃,一起剝皮案震驚了整個濱河市油够,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌征懈,老刑警劉巖石咬,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異卖哎,居然都是意外死亡鬼悠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門亏娜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來焕窝,“玉大人,你說我怎么就攤上這事维贺∷啵” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵溯泣,是天一觀的道長虐秋。 經(jīng)常有香客問我,道長垃沦,這世上最難降的妖魔是什么客给? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮肢簿,結(jié)果婚禮上靶剑,老公的妹妹穿的比我還像新娘。我一直安慰自己池充,他們只是感情好桩引,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著收夸,像睡著了一般坑匠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上咱圆,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天笛辟,我揣著相機與錄音功氨,去河邊找鬼。 笑死手幢,一個胖子當(dāng)著我的面吹牛捷凄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播围来,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼跺涤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了监透?” 一聲冷哼從身側(cè)響起桶错,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎胀蛮,沒想到半個月后院刁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡粪狼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年退腥,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片再榄。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡狡刘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出困鸥,到底是詐尸還是另有隱情嗅蔬,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布疾就,位于F島的核電站澜术,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏虐译。R本人自食惡果不足惜瘪板,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一吴趴、第九天 我趴在偏房一處隱蔽的房頂上張望漆诽。 院中可真熱鬧,春花似錦锣枝、人聲如沸厢拭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽供鸠。三九已至,卻和暖如春陨闹,著一層夾襖步出監(jiān)牢的瞬間楞捂,已是汗流浹背薄坏。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寨闹,地道東北人胶坠。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像繁堡,于是被迫代替她去往敵國和親沈善。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 我眼中的js編程(1)主要介紹了js是用來做什么的椭蹄,這一篇開始及以后總結(jié)js具體該怎么用闻牡。本篇總結(jié)了作用域內(nèi)變量和...
    閆浩奇閱讀 531評論 0 5
  • 第一章: JS簡介 從當(dāng)初簡單的語言,變成了現(xiàn)在能夠處理復(fù)雜計算和交互绳矩,擁有閉包罩润、匿名函數(shù), 甚至元編程等...
    LaBaby_閱讀 1,667評論 0 6
  • 個人理解的基礎(chǔ)功能有:1: GPS信號獲取的穩(wěn)定性翼馆,以及丟失后的軌跡彌補算法哨啃;2: GPS漂移信號的過濾以及修正;...
    知否讀書閱讀 702評論 0 0
  • 好久沒有寫東西了写妥,感覺忘了寫東西的感覺拳球,就像忘了理想一般。前一個月我還生活在希望之中珍特,可生活還是生活祝峻。回家一趟突然...
    107fe232d81b閱讀 498評論 0 0
  • 今天寫的這些扎筒,算是一篇隨筆莱找,一篇關(guān)于無常的自白。 文/薔薇Viki 我總覺得嗜桌,做什么事情都有第一步奥溺。很多事情很難,...
    薔薇筆跡閱讀 848評論 4 3