javascript中的變量作用域以及變量提升詳細(xì)介紹
變量作用域
“一個(gè)變量的作用域表示這個(gè)變量存在的上下文。它指定了你可以訪問哪些變量以及你是否有權(quán)限訪問某個(gè)變量?!?/P>
變量作用域分為局部作用域和全局作用域。
局部變量(處于函數(shù)級別的作用域)
不像其他對面對象的編程語言(比方說C++,Java等等),javascript沒有塊級作用域(被花括號包圍的);當(dāng)是,javascript有擁有函數(shù)級別的作用域,也就是說,在一個(gè)函數(shù)內(nèi)定義的變量只能在函數(shù)內(nèi)部訪問或者這個(gè)函數(shù)內(nèi)部的函數(shù)訪問(閉包除外,這個(gè)我們過幾天再寫個(gè)專題)。
函數(shù)級別作用域的一個(gè)例子:
var name = "Richard";
function showName () {
var name = "Jack"; // local variable; only accessible in this showName function
console.log (name); // Jack
}
console.log (name); // Richard: the global variable
沒有塊級作用域:
var name = "Richard";
// the blocks in this if statement do not create a local context for the name variable
if (name) {
name = "Jack"; // this name is the global name variable and it is being changed to "Jack" here
console.log (name); // Jack: still the global variable
}
// Here, the name variable is the same global name variable, but it was changed in the if statement
console.log (name); // Jack
// 不要忘記使用var關(guān)鍵字
// 如果聲明一個(gè)變量的時(shí)候沒有使用var關(guān)鍵字,那么這個(gè)變量將是一個(gè)全局變量!
// If you don't declare your local variables with the var keyword, they are part of the global scope
var name = "Michael Jackson";
function showCelebrityName () {
console.log (name);
}
function showOrdinaryPersonName () {
name = "Johnny Evers";
console.log (name);
}
showCelebrityName (); // Michael Jackson
// name is not a local variable, it simply changes the global name variable
showOrdinaryPersonName (); // Johnny Evers
// The global variable is now Johnny Evers, not the celebrity name anymore
showCelebrityName (); // Johnny Evers
// The solution is to declare your local variable with the var keyword
function showOrdinaryPersonName () {
var name = "Johnny Evers"; // Now name is always a local variable and it will not overwrite the global variable
console.log (name);
}
// 局部變量優(yōu)先級大于全局變量
//如果在全局作用域中什么的變量在局部作用域中再次聲明,那么在局部作用域中調(diào)用這個(gè)變量時(shí),優(yōu)先調(diào)用局部作用域中聲明的變量:
var name = "Paul";
function users () {
// Here, the name variable is local and it takes precedence over the same name variable in the global scope
var name = "Jack";
// The search for name starts right here inside the function before it attempts to look outside the function in the global scope
console.log (name);
}
users (); // Jack
全局變量
所有在函數(shù)外面聲明的變量都處于全局作用域中。在瀏覽器環(huán)境中,這個(gè)全局作用域就是我們的Window對象(或者整個(gè)HTML文檔)。
每一個(gè)在函數(shù)外部聲明或者定義的變量都是一個(gè)全局對象,所以這個(gè)變量可以在任何地方被使用,例如:
// name and sex is not in any function
var myName = "zhou";
var sex = "male";
//他們都處在window對象中
console.log(window.myName); //paul
console.log('sex' in window); //true
如果一個(gè)變量第一次初始化/聲明的時(shí)候沒有使用var關(guān)鍵字,那么他自動加入到全局作用域中。
function showAge(){
//age初始化時(shí)沒有使用var關(guān)鍵字,所以它是一個(gè)全局變量
age = 20;
console.log(age);
}
showAge(); //20
console.log(age); //因?yàn)閍ge是全局變量,所以這里輸出的也是20
setTimeout中的函數(shù)是在全局作用域中執(zhí)行的
setTimeout中的函數(shù)所處在于全局作用域中,所以函數(shù)中使用this關(guān)鍵字時(shí),這個(gè)this關(guān)鍵字指向的是全局對象(Window):
var Value1 = 200;
var Value2 = 20;
var myObj = {
Value1 : 10,
Value2 : 1,
caleculatedIt: function(){
setTimeout(function(){
console.log(this.Value1 * this.Value2);
}, 1000);
}
}
myObj.caleculatedIt(); //4000
為了避免對全局作用域的污染, 所以一般情況下我們盡可能少的聲明全局變量。
變量提升(Variable Hoisting)
所以的變量聲明都會提升到函數(shù)的開頭(如果這個(gè)變量在這個(gè)函數(shù)里面)或者全局作用域的開頭(如果這個(gè)變量是一個(gè)全局變量)。我們來看一個(gè)例子:
function showName () {
console.log ("First Name: " + name);
var name = "Ford";
console.log ("Last Name: " + name);
}
showName ();
// First Name: undefined
// Last Name: Ford
// The reason undefined prints first is because the local variable name was hoisted to the top of the function
// Which means it is this local variable that get calls the first time.
// This is how the code is actually processed by the JavaScript engine:
function showName () {
var name; // name is hoisted (note that is undefined at this point, since the assignment happens below)
console.log ("First Name: " + name); // First Name: undefined
name = "Ford"; // name is assigned a value
// now name is Ford
console.log ("Last Name: " + name); // Last Name: Ford
}
函數(shù)聲明會覆蓋變量聲明
如果存在函數(shù)聲明和變量聲明(注意:僅僅是聲明,還沒有被賦值),而且變量名跟函數(shù)名是相同的,那么,它們都會被提示到外部作用域的開頭,但是,函數(shù)的優(yōu)先級更高,所以變量的值會被函數(shù)覆蓋掉。
// Both the variable and the function are named myName
var myName;?
function myName () {
console.log ("Rich");
}
// The function declaration overrides the variable name
console.log(typeof myName); // function
但是,如果這個(gè)變量或者函數(shù)其中是賦值了的,那么另外一個(gè)將無法覆蓋它:
// But in this example, the variable assignment overrides the function declaration
var myName = "Richard"; // This is the variable assignment (initialization) that overrides the function declaration.
function myName () {
console.log ("Rich");
}
console.log(typeof myName); // string
最后一點(diǎn), 在嚴(yán)格模式下,如果沒有先聲明變量就給變量賦值將會報(bào)錯(cuò)!
相關(guān)文章
HTML5+Canvas調(diào)用手機(jī)拍照功能實(shí)現(xiàn)圖片上傳(上)
這篇文章主要為大家詳細(xì)介紹了HTML5+Canvas,和jquery技術(shù),調(diào)用手機(jī)拍照功能實(shí)現(xiàn)圖片上傳,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04javascript-簡單的日歷實(shí)現(xiàn)及Date對象語法介紹(附圖)
主要是對Date對象的使用,首先回憶一下Date對象的參數(shù)及方法,代碼如下,感興趣的朋友可以參考下哈2013-05-05bootstrap fileinput插件實(shí)現(xiàn)預(yù)覽上傳照片功能
這篇文章主要介紹了bootstrap fileinput插件實(shí)現(xiàn)預(yù)覽上傳照片功能,代碼簡單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-01-01基于JavaScript實(shí)現(xiàn)十五拼圖代碼實(shí)例
這篇文章主要介紹了基于JavaScript實(shí)現(xiàn)十五拼圖代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04js中對函數(shù)設(shè)置默認(rèn)參數(shù)值的3種方法
這篇文章主要介紹了js中對函數(shù)設(shè)置默認(rèn)參數(shù)值的3種方法嗎,3種方法都具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-10-10JavaScript生成一個(gè)不重復(fù)的ID的方法示例
這篇文章主要介紹了JavaScript生成一個(gè)不重復(fù)的ID的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09javascript實(shí)現(xiàn)用戶點(diǎn)擊數(shù)量統(tǒng)計(jì)
本文主要javascript實(shí)現(xiàn)用戶點(diǎn)擊數(shù)量統(tǒng)計(jì)的方法進(jìn)行詳細(xì)介紹,具有很好的參考價(jià)值,需要的朋友一起來看下吧2016-12-12詳解Webpack實(shí)戰(zhàn)之構(gòu)建 Electron 應(yīng)用
本篇文章主要介紹了Webpack實(shí)戰(zhàn)之構(gòu)建 Electron 應(yīng)用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12