JavaScript 作用域
-
- JavaScript 作用域
- JavaScript 局部作用域
- JavaScript 全局變量
- JavaScript 變量生命周期
- 函數參數
- HTML 中的全局變量
- ES6中的變量和作用域
-
- 通過let和const決定塊作用域
- const建立不可變的變量
- JavaScript 變量提升
- JavaScript 初始化不會提升
- 在頭部聲明你的變量
你越是認真生活,你的生活就會越美好
——弗蘭克·勞埃德·萊特
《人生果實》經典語錄
JavaScript 作用域
作用域
是
可通路變量
的集合。
在 JavaScript 中,
對象和函數
同樣也是變量。
在 JavaScript 中,
作用域為可通路變量,對象,函數的集合
。
JavaScript
函數作用域
: 作用域在函數内修改。
JavaScript 局部作用域
變量在
函數内聲明
,變量為局部作用域。
局部變量:
隻能在函數内部通路
。
// 此處不能調用 carName 變量
function myFunction() {
var carName = "Volvo";
// 函數内可調用 carName 變量
}
因為
局部變量
隻作用于
函數内
,是以
不同的函數
可以使用
相同名稱的變量
。
局部變量
在函數開始執行時建立,
函數執行完後
局部變量會
自動銷毀
。
JavaScript 全局變量
變量在
函數外
定義,即為
全局變量
。
全局變量有
全局作用域
: 網頁中
所有腳本
和函數均可使用。
var carName = " Volvo";
// 此處可調用 carName 變量
function myFunction() {
// 函數内可調用 carName 變量
}
如果變量在
函數内沒有聲明
(沒有使用 var 關鍵字),
該變量為全局變量
。
以下執行個體中 carName 在函數内,但是為全局變量。
function myFunction() {
carName = "Volvo";
// 此處可調用 carName 變量
}
myFunction()
// 此處可調用 carName 變量 前提是myFunction函數執行過
console.log(carName) // Volvo
JavaScript 變量生命周期
JavaScript 變量生命周期
在它
聲明時初始化
。
局部變量
在
函數執行完畢後銷毀
。
全局變量
在
頁面關閉後銷毀
。
函數參數
函數參數
隻在
函數内
起作用,是
局部變量
。
HTML 中的全局變量
在 HTML 中, 全局變量是 window 對象: 所有資料變量都屬于 window 對象。
function myFunction() {
carName = "Volvo";
}
myFunction()
//此處可使用 window.carName
console.log(window.carName)
PS:
你的全局變量,或者函數,可以覆寫 window 對象的變量或者函數。
局部變量,包括 window 對象可以覆寫全局變量和函數。
ES6中的變量和作用域
通過let和const決定塊作用域
let
和
const
建立的變量
隻在塊作用域中
有效。它們隻存于包含它們的塊中。下面示範的代碼,通過let在if語句塊中聲明一個tmp變量。這個變量僅在if語句中有效。
function func() {
if (true) {
let tmp = 123;
console.log(tmp); // => 123
}
}
func() // 123
console.log(tmp); // => ReferenceError: tmp is not defined
相比之下,
var聲明的變量
作用域的範圍是
函數範圍内
的:
function func() {
console.log(tmp) // undefined 變量聲明提升 還沒指派
if (true) {
var tmp = 123
console.log(tmp) // 123
}
console.log(tmp) // 123
}
func()
console.log(tmp) // Uncaught ReferenceError: tmp is not defined
塊作用域意味着你可在有函數内有變量的陰影。
function func() {
let foo = 5;
console.log(foo) // 5
if(true) {
let foo = 10;
console.log(foo) // 10
}
console.log(foo) // 5
}
func()
const建立不可變的變量
由
let
建立的變量是可變的:
let foo = 'abc'
foo = 'def'
console.log(foo) // def
由
const
建立的是變量是一個
常量
,這個變量是
不可變
的:
const foo = 'abc'
foo = 'def' // Uncaught TypeError: Assignment to constant variable.
如果一個常量指的是一個
對象
,那麼
const并不影響常量本身的值
是否是可變的,因為它總是指向那個對象,但是對象本身仍然是可以被改變的。
const obj = {}
obj.prop = 123
console.log(obj.prop) // 123
console.log(obj) // {prop: 123}
obj = {} // Uncaught TypeError: Assignment to constant variable.
如果你想讓
obj
真正成為一個
常量
,你必須
當機它的值
:
const obj = Object.freeze({});
obj.prop = 123;
console.log(obj) // {}
也就是說,如果
const定義
的常量指向的是一個對象。這個時候,它實際上指向的是目前對象的位址。這個位址是在棧裡面的,而這個真實的對象是在堆棧裡面的。是以,我們使用const定義這個對象後,是可以改變對象的内容的。但是
這個位址是不可以改變的
。意思也就是不可以給這個對象重新指派,比如
const obj= {}, obj = {}
,即使是這樣,obj好像什麼也沒有改變,但還是錯誤的。
然而在
普通模式
下,并沒有報錯,而obj.name = 'abc’這是完全可以的。這跟JavaScript存儲引用對象的值的方式有密切的關系。
const obj = Object.freeze({})
const newObj = {}
obj.name = 'w3cplus'
newObj.name = 'damo';
console.log(obj) // {}
console.log(newObj) // {name: "damo"}
使用Babel把上面ES6的代碼編譯成ES5代碼:
'use strict';
var obj = Ob
JavaScript 變量提升
- JavaScript 中,
都将被函數及變量的聲明
。提升到函數的最頂部
- JavaScript 中,
,也就是變量可以在使用後聲明
。變量可以先使用再聲明
-
不存在變量提升類
以下兩個執行個體将獲得相同的結果:
例子1
x = 5; // 變量 x 設定為 5
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x; // 在元素中顯示 x
var x; // 聲明 x
例子2
var x; // 聲明 x
x = 5; // 變量 x 設定為 5
console.log(x) // 5
要了解以上執行個體就需要了解 “
hoisting(變量提升)
”。
變量提升
:
函數聲明
和
變量聲明
總是會被解釋器悄悄地
被"提升"到方法體的最頂部
。
類
不存在變量提升
new Foo() // Uncaught ReferenceError: Foo is not defined
class Foo {}
JavaScript 初始化不會提升
JavaScript 隻有聲明的變量會提升,初始化的不會。
執行個體1
var x = 5; // 初始化 x
var y = 7; // 初始化 y
console.log(x) // 5
console.log(y) // 7
執行個體2
var x = 5; // 初始化 x
console.log(x) // 5
console.log(y) // undefined
var y = 7; // 初始化 y
執行個體 2 的 y 輸出了 undefined,這是因為變量聲明 (var y) 提升了,但是初始化(y = 7) 并不會提升,是以 y 變量是一個未定義的變量。
執行個體 2 類似以下代碼:
var x = 5; // 初始化 x
var y; // 聲明 y
console.log(x) // 5
console.log(y) // undefined
y = 7; // 設定 y 為 7
在頭部聲明你的變量
對于大多數程式員來說并不知道
JavaScript 變量提升
。
如果程式員不能很好的了解變量提升,他們寫的程式就容易出現一些問題。
為了避免這些問題,通常我們
在每個作用域開始前聲明
這些變量,這也是正常的 JavaScript 解析步驟,易于我們了解。
謝謝你閱讀到了最後~
期待你關注、收藏、評論、點贊~
讓我們一起 變得更強
參考
JavaScript 作用域
推薦閱讀
了解js中this的指向(幾條規則加例子+call,apply,bind改變this指向)