❝本篇文章面向羣體:入門級
❞
難度等級:★☆☆☆☆
內容較多,建議點贊收藏後閱讀html
變量做爲js中最多見也是咱們最先接觸的js知識點,相信你們都不陌生,變量幾乎存在於全部的編程語言中,百度百科中對於變量的解釋爲 「變數或變量,是指沒有固定的值,能夠改變的數。變量以非數字的符號來表達,通常用拉丁字母。」 而JavaScript中的變量是鬆散類型(弱類型)的,所謂鬆散類型就是能夠用來保存任何類型的數據,在聲明變量時無需指定變量的類型。因此,當咱們聲明一個變量以後,能夠存儲任意類型的數據。es6
在js中聲明一個變量一般經過關鍵字加一個變量名的形式來聲明一個變量,那對於變量名在js中是如何要求的呢?編程
除了這些js明文規定的變量命名規則以外,爲了代碼可讀性更高,咱們一般也對變量命名有行業通用的命名規範。markdown
age
、 time
,避免使用無心義的字符組合,如aaa
、bbb
$
做爲關鍵字,因此咱們也應儘可能避免使用$
做爲變量名userAge
、myFirstName
上面說了,js聲明變量的方法爲關鍵字加一個變量名,說完了變量名,咱們就來講一下聲明變量的關鍵字,js中聲明變量的關鍵字有如下三種框架
var
關鍵字是咱們學習js最早接觸也是早期聲明變量最爲經常使用的關鍵字,使用方法直接在var
關鍵字後面直接跟變量名便可,如編程語言
var message = 'hello world' console.log(message) // hello world 複製代碼
var
關鍵字特色函數
var message = 'hello' message = 'world' console.log(message) // world 複製代碼
var
聲明的變量初始值均爲undefined
var message console.log(message) // undefined 複製代碼
var message, test, handleName console.log(message) // undefined console.log(test) // undefined console.log(handleName) // undefined 複製代碼
var
關鍵字能夠省略message = 'hello' console.log(message) // hello // js 中若是省略var關鍵字,則會自動建立全局變量 function foo() { message = 'hello' console.log(message) // hello } foo() console.log(message) // hello // 若是使用,則會建立當前做用域的變量 function foo() { var message = 'hello' console.log(message) // hello } foo() console.log(message) // message is not defined 複製代碼
* 注意,在嚴格模式下不可省略關鍵字,不然會報錯oop
let
關鍵字是ES2015(ES6) 新增長的重要的 JavaScript 關鍵字,用法和 var
同樣學習
let message = 'hello world' console.log(message) // hello world 複製代碼
let
關鍵字與var
不一樣的地方spa
var message let message // Identifier 'message' has already been declared let test = 'test' let test = 'hello' // Identifier 'test' has already been declared 複製代碼
let
所聲明的變量,只在 let
命令所在的代碼塊內有效{ let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1 複製代碼
利用 let
的這一特性能夠解決很經典的一個問題
for (var index = 0; index < 6; index++) { setTimeout(function() { console.log(index) }, 100) } 複製代碼
這段代碼的結果輸出的是6個6,這是由於這裏的index是用 var
定義的,每一輪循環所用的index都是全局變量,因此等到100毫秒後執行的時候,index已經循環完變成了6,那麼利用 let
僅在當前代碼塊有效的這個特性,就能夠很好的解決這個問題
for (let index = 0; index < 6; index++) { setTimeout(function() { console.log(index) }, 100) } // 0 1 2 3 4 5 複製代碼
由於 let
僅在當前代碼塊有效,因此這裏每一輪循環都至關於定義了一個新的index,因此最後輸出的時循環時候的值。你可能會問,若是每一輪循環的變量i都是從新聲明的,那它怎麼知道上一輪循環的值,從而計算出本輪循環的值?這是由於 JavaScript 引擎內部會記住上一輪循環的值,初始化本輪的變量i時,就在上一輪循環的基礎上進行計算。
const
關鍵字是ES2015(ES6) 新增長的重要的 JavaScript 關鍵字,用法和 var
同樣,只不過 const
生成的是一個或多個常量,在有些時候,咱們定義的值不但願被覆蓋或者修改,咱們就能夠用 const
const message = 'hello world' console.log(message) // hello world 複製代碼
const
關鍵字 和 var
關鍵字不一樣的地方
const a // Missing initializer in const declaration const b = 'test' // 正確 複製代碼
const a = 'hello' a = 'world' // Uncaught TypeError: Assignment to constant variable. 複製代碼
其實const聲明的常量並不是嚴格意義上的常量,由於當咱們用const定義一個常量的值爲引用類型(下面會講基本類型和引用類型)時候,雖然咱們不能進行從新賦值,但咱們能夠修改引用類型的值。
複製代碼
const a = { name: '小明' } a.name = '小豪' console.log(a.name) // 小豪 複製代碼
咱們知道,js中的值能夠保存全部數據類型,那麼js中的數據類型又都有什麼呢? JavaScript中的數據類型有六種,其中有五種簡單數據類型(也叫基本數據類型),還有一種複雜的數據類型——對象(Object),因爲本文主要講的是變量相關知識,因此對數據類型不深刻講解,知識大概說一下。
五種基本的數據類型:Undefined、Null、Boolean、Number和String。這5種基本數據類型是按值訪問的,由於能夠操做保存在變量中的實際的值。咱們就直接按正常思路來就好了。
var a = '小明' var b = a a = '小豪' console.log(b) // '小明' 複製代碼
❝因爲對象的知識相對較多,後續會有專門的文章進行介紹總結。
❞
若是有點基礎同窗都知道,原始類型存儲的是值,對象類型存儲的是地址(指針), 那麼當咱們定義一個變量的值爲對象的時候,因爲存儲的實際是這個對象在內存中的地址,至關於咱們在這裏只是引用了這個對象,因此在對一些變量進行復制賦值和修改時候就會出現一些意想不到的事情,好比下面的代碼
var a = { name: '小明' } var b = a b.name = '小豪' console.log(a.name) // 小豪 複製代碼
在上面的例子中,咱們把a賦值給b,實際上只是把a所引用的對象地址賦值給了b,這時候a和b其實指向的是一個對象,因此當咱們修改其中任何一個的時候,都是在對同一對象進行修改
這樣很好的解釋了咱們上面所說的const定義的常量可修改的問題,當咱們用const定義的常量爲對象時,其實咱們在這個常量裏保存的只是一個對象的地址,不管咱們怎麼修改這個對象,const定義的常量裏保存的地址是沒有變化的,因此上面例子中對const定義的對象進行修改其實並無違背const定義的變量不可修改的原則,只有咱們給這個常量從新賦值一個新對象(也就是新地址)的時候,纔會觸發const定義的常量不可修改的規則。
做用域,咱們這裏爲了理解,能夠簡單的理解爲做用域就是變量能夠生效及訪問的地方。JavaScript中分爲全局做用域和局部做用域,全局做用域裏的變量在全部的地方均可以訪問,局部做用域只能在當前做用域被訪問。
在一些相似於c語言的編程語言中,每一對花括號包裹的區域都有本身的做用域,咱們稱之爲塊狀做用域,而在JavaScript中沒有塊級做用域(es6以前),取而代之的是函數做用域,因此咱們一般所說的局部做用域也就是函數做用域。
var a = "hello" // 全局做用域 function foo() { // 在此做用域能夠訪問到a console.log(a) // 'hello' var b = 'world' } foo() console.log(a) // 'hello' // 因爲變量b定義在函數foo內,因此在函數foo的做用域外訪問不到 console.log(b) // b is not defined 複製代碼
在js中能夠存在函數嵌套函數的狀況,因此咱們很是容易見到函數做用域嵌套的狀況,這時候就會造成一條做用域鏈,在js中,當你使用一個變量時,JavaScript引擎會首先在當前做用域內尋找,若是找不到,就會到上一層做用域尋找,若是一直找到頂層做用域(也就是全局做用域)還找不到時,就會報錯。
ES2015(ES6) 新增長了 let
關鍵字,從而可讓咱們在塊級做用域(大括號)中聲明變量。
在JavaScript 中,函數及變量的聲明都將被提高到當前做用域的最頂部。
//var a <------------------ console.log(a) // undefined ↑ var a // ----------------> 複製代碼
在上面的例子中,咱們雖然聲明語句在打印語句的後面,可是咱們打印a卻並無報錯,就是由於這裏的變量聲明被提到了當前做用域的最上面,咱們稱之爲變量提高。
在JavaScript中 var a = 'test'
實際上是分爲兩步進行的,分別是變量聲明 var a
和 變量賦值 a = 'test'
, 變量聲明會被提早,可是變量賦值不會被提早,咱們來看下面的例子
console.log(a) // undefined var a = 'test' // 上述代碼的執行步驟能夠用下面的代碼理解 var a console.log(a) a = 'test' 複製代碼
結合上面的函數做用域,咱們來看一下下面的例子
var a = 'test' function foo() { console.log(a) var a = 'hello' } foo() 複製代碼
你們猜一下打印的結果是什麼,沒錯,就是 undefined
,咱們這裏定義了全局變量a,又定義了函數局部變量a,因此咱們在執行函數 foo()
時,實際上是找的函數 foo()
裏的局部變量a,局部變量a經過變量提高到了函數 foo()
的頂部,可是變量賦值卻沒有提高,因此最後打印結果爲 undefined
,上面的代碼能夠理解爲下面這樣
var a = 'test' function foo() { var a console.log(a) a = 'hello' } foo() 複製代碼
須要注意的是 let
和 const
不存在變量提高,在你定義他們以前使用會報錯。比較有意思的是,let
和 const
的報錯還不同
console.log(test) // Cannot access 'test' before initialization const test = 'hello' console.log(message) // message is not defined let message = 'hello' // 若是咱們在局部做用域裏寫,報錯就同樣了 function foo() { console.log(message) // Cannot access 'message' before initialization let message = 'world' } foo() 複製代碼
❝做者確實基礎較差,寫文章更多的目的是爲了提升本身的能力,可是總結寫下來不免有囉嗦和失誤的地方,若是能夠幫到別人固然十分開心,若是你們發現什麼問題也歡迎隨時提出,我也會持續的學習,不斷的對文章新型修改,但願你們一塊兒進步,加油
❞
本文使用 mdnice 排版