js進階語法之變量提升、函數(shù)提升以及參數(shù)的命名沖突問題解決
前言
預(yù)處理階段:js在編譯代碼時有一個預(yù)處理階段,這個過程會將原本的代碼進行分割處理;
源程序 ---> 預(yù)處理塊+ 剩余代碼塊
預(yù)處理塊中的代碼會優(yōu)先于剩余代碼塊中的代碼執(zhí)行
什么是變量提升,函數(shù)提升
變量提升:當聲明一個變量時,這個聲明過程會被預(yù)處理機制塞入到預(yù)處理塊中優(yōu)先執(zhí)行,這就是變量提升,使用var定義的變量擁有變量提升
函數(shù)提升:當聲明一個函數(shù)時,這個聲明過程會被預(yù)處理機制塞入到預(yù)處理塊中優(yōu)先執(zhí)行,這就是函數(shù)提升,使用function定義的函數(shù)擁有函數(shù)提升
提升的判斷:當一個變量和函數(shù)在正常的順序中沒有聲明但被調(diào)用時就可能產(chǎn)生“提升”
變量提升
變量提升,將變量名放入預(yù)編譯的詞法環(huán)境 var a(undefined)
console.log(a); var a = 1;
以上的代碼會產(chǎn)生變量提升,它等價于下面的代碼,
{// 模擬預(yù)處理塊
var a;
}
// 正常執(zhí)行的剩余代碼塊
console.log(a); // undefined
a = 1;因為變量提升的緣故,a會在打印執(zhí)行前被聲明,所以會打印成undefined
函數(shù)提升
函數(shù)提升,將函數(shù)體放入預(yù)編譯的詞法環(huán)境 function b(){}
console.log(b);
function b(){
console.log('b')
};以上的代碼會產(chǎn)生函數(shù)提升,它等價于下面的代碼,
{// 模擬預(yù)處理塊
function b(){
console.log('b')
};
}
// 正常執(zhí)行的剩余代碼塊
console.log(b);function聲明的函數(shù)都存在函數(shù)提升,所以可以在聲明函數(shù)之前使用函數(shù)(先寫出函數(shù)的用法,在完成函數(shù)的實現(xiàn))
關(guān)于變量提升和函數(shù)提升的判斷
了解了基本的變量提升和函數(shù)提升,接下來開始區(qū)分一些二者的區(qū)別和同時在場的優(yōu)先級
1.變量賦值的函數(shù)
console.log(a);
var a = function(){
console.log('a')
};很顯然這是由var聲明的變量,擁有變量提升,只不過它的值是一個函數(shù)體
{// 模擬預(yù)處理塊
var a;
}
// 正常執(zhí)行的剩余代碼塊
console.log(a); // undefined
a = function(){
console.log('a')
};所以這個a會打印成undefined
2.優(yōu)先級判斷
console.log(b);
var b = function(){
console.log('b1')
};
function b(){
console.log('b2')
};
console.log(b);函數(shù)提升的優(yōu)先級是比變量提升的優(yōu)先級大的,當出現(xiàn)聲明同名的變量和函數(shù)時,在預(yù)處理塊中最終都會變成函數(shù),
{// 模擬預(yù)處理塊
var b;
function b(){
console.log('b2')
};
}
// 正常執(zhí)行的剩余代碼塊
console.log(b);// 能打印'b2'的函數(shù)
b = function(){
console.log('b1')
};
console.log(b);// 能打印'b1'的函數(shù)除了上面這種優(yōu)先級的理解方式,還有下面這種,將function聲明拆成了兩個部分,先聲明函數(shù)名,在賦值函數(shù)體,而變量的聲明在它們之間
{// 模擬預(yù)處理塊
function b
var b;
b = function(){
console.log('b2')
};
}
// 正常執(zhí)行的剩余代碼塊
console.log(b);// 能打印'b2'的函數(shù)
b = function(){
console.log('b1')
};
console.log(b);// 能打印'b1'的函數(shù)tips:以上兩種方式的結(jié)果是一樣的,采用哪種分析方式都可以
3.同名參數(shù)名,變量名,函數(shù)名的優(yōu)先級判斷
同名參數(shù)名,變量名的判斷
var foo = 'hello';
(function(foo){
console.log(foo);
var foo = foo || 'world';
console.log(foo);
})(foo);
console.log(foo);這里只分析了立即執(zhí)行函數(shù)內(nèi)的預(yù)處理
var foo = 'hello';
(function(foo){
// 模擬立即執(zhí)行函數(shù)內(nèi)的預(yù)處理塊
{
var foo;
foo = foo; //傳入的參數(shù)('hello')
}
// 正常執(zhí)行的剩余代碼塊
console.log(foo);
foo = foo || 'world';
console.log(foo);
})(foo);
console.log(foo);所以最后連續(xù)打印了3個hello,傳入的參數(shù)會在預(yù)處理中聲明后賦值給同名變量,foo不為undefined,后面的賦值就不會變成world
當同名參數(shù)名,變量名,函數(shù)名同時存在
function fn (m){
console.log(m);
var m = 1;
function m(){
}
console.log(m);
}
fn(10)同樣有兩種理解方式
function fn (m){
// 模擬預(yù)處理塊
{
var m;
m = m;// 傳入的參數(shù)(10)
function m(){
}
};
}
// 正常執(zhí)行的剩余代碼塊
console.log(m);// function(){}
m = 1;
console.log(m);// 1
}
fn(10)function fn (m){
// 模擬預(yù)處理塊
{
function m
var m;
m = m;// 傳入的參數(shù)(10)
m = function(){
}
};
}
// 正常執(zhí)行的剩余代碼塊
console.log(m);// function(){}
m = 1;
console.log(m);// 1
}
fn(10)可以看到這個函數(shù)的輸出和傳入的參數(shù)沒有任何關(guān)系,因為傳入的參數(shù)會在函數(shù)提升的前面(函數(shù)體賦值的前面),導(dǎo)致傳入的參數(shù)被覆蓋
總結(jié)
所以可以得出同名參數(shù)名,變量名,函數(shù)名的預(yù)處理順序為:
變量提升---參數(shù)傳遞---函數(shù)提升 (聲明函數(shù)名---變量提升---參數(shù)傳遞---函數(shù)體賦值)
所以最終這個名稱會被函數(shù)奪取,這就是函數(shù)提升優(yōu)先級最高的原因
完整代碼和運行結(jié)果展示
// 變量提升,將變量名放入預(yù)編譯的詞法環(huán)境 var a(undefined)
console.log(a);
var a = function(){
console.log('a')
};
console.log(a);
// 函數(shù)提升,將函數(shù)體放入預(yù)編譯的詞法環(huán)境 function b(){}
console.log(b);
var b = function(){
console.log('b1')
};
function b(){
console.log('b2')
};
console.log(b);
// function b 函數(shù)名提升
// var b 變量名提升
// b = (){} 函數(shù)體初始化
// 因為函數(shù)體初始化總在變量名之后,所以每次都是優(yōu)先預(yù)編譯成函數(shù)
// 結(jié)合自執(zhí)行函數(shù)
var foo = 'hello';
(function(foo){
console.log(foo);
var foo = foo || 'world';
console.log(foo);
})(foo);
console.log(foo);
// 依次輸出 hello hello hello
// 預(yù)編譯后
var foo = 'hello';
(function (foo) {
var foo; // undefined;
foo= 'hello'; //傳入的foo的值
console.log(foo); // hello
foo = foo || 'world';// 因為foo有值所以沒有賦值world
console.log(foo); //hello
})(foo);
console.log(foo);// hello,打印的是var foo = 'hello' 的值(變量作用域)
// function m(){
// console.log('m');
// };
// var m;
// m =1;
// function m(){
// }
// console.log(m)
function fn (m){
console.log(m);
var m = 1;
function m(){
}
console.log(m);
}
fn(10)
// function m
// var m
// 參數(shù)m
// m = (){}
// m = 1
// function > parmas > var
到此這篇關(guān)于js進階語法之變量提升、函數(shù)提升以及參數(shù)的命名沖突問題解決的文章就介紹到這了,更多相關(guān)js變量、函數(shù)提升及參數(shù)命名沖突內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
echartjs實現(xiàn)cross十星輔助線實現(xiàn)示例詳解
這篇文章主要為大家介紹了echartjs實現(xiàn)cross十星輔助線實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
JS實現(xiàn)網(wǎng)頁搶購功能(觸發(fā),終止腳本)
小編通過一個網(wǎng)頁式的搶購功能的實現(xiàn)給大家講解一下JS如何觸發(fā)和終止腳本來完成這個任務(wù)。2017-11-11
JavaScript使用Broadcast?Channel實現(xiàn)前端跨標簽頁通信
這篇文章主要為大家詳細介紹了JavaScript如何使用Broadcast?Channel實現(xiàn)前端跨標簽頁通信,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
JavaScript對象學(xué)習(xí)小結(jié)
JavaScript 中的所有事物都是對象:字符串、數(shù)值、數(shù)組、函數(shù).幾乎用到的每個js都離不開它的js對象。此外,JavaScript 允許自定義對象,下面跟著小編學(xué)習(xí)javascript對象學(xué)習(xí)小結(jié),需要的朋友可以參考下2015-09-09
BootstrapTable refresh 方法使用實例簡單介紹
本文就bootstrapTable refresh 方法如何傳遞參數(shù)做簡單舉例說明,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-02-02

