JS:JS中常見的 “函數名 is not a function” 錯誤


js中常見的錯誤,例如Uncaught TypeError: x is not a function

其原因除了函數本身有錯之外,還有一種很奇怪的情況:函數本身沒有錯,但是運行時就是不能正常運行。這種情況與javascript的特性有關變量與函數聲明前置的優先級。

總結:

js有聲明前置,函數和變量的聲明都會前置,即會在整個js代碼的最開始,不管聲明部分在什么位置。

js中函數的聲明優先於同名變量的聲明,不管先后順序如何。

函數的聲明會在整段js代碼的最前面,不管function() 函數在js的什么位置。

當先聲明了名為x()的函數,再聲明名為var x的變量時,變量名會覆蓋函數,使得在同名變量定義之后,函數變得未定義,即同名變量定義之后 調用同名函數會報錯,即 x is not a function。

當有兩個同名變量和兩個同名函數一起定義時,四個量的名字相同,那么后一個函數或者變量會覆蓋掉前一個對應的量(函數/變量)且四個中最后一個定義量之后在引用此量,該量的類型(變量/函數)是最后一次定義此名量時的類型(變量/函數)。

 

1-4點解釋如下:

首先看代碼:

console.log(x)
console.log(x());
var x=1;
function x(){
    console.log(5);
}
console.log(x)
console.log(x());//此時x變成了一個變量

輸出結果:

function x(){
                console.log(5);
 }

5

1
 Uncaught TypeError: x is not a function

 ----------------------------

js解釋器在對其上下文進行解釋執行時分為三個階段來進行:聲明階段、初始化階段、執行階段。

針對js上下文,首先會進行聲明階段,聲明階段中的特點是聲明前置;聲明又會包括變量聲明前置和函數聲明前置,鑒於以上代碼的輸出結果,我們可以得出函數聲明前置優先於變量聲明前置的特點,並且如果變量名和函數名沖突會忽略變量的聲明,因此聲明過得變量名或函數名不會重復聲明,這樣也可以很好地解釋為什么第一次輸出的是函數而不是undefined。根據js的這些特點我們可以將以上代碼解析成如下:

//聲明階段
function x(){//函數聲明
    console.log(5);
        }
var x;//變量聲明,因為x已經聲明過了,此處不進行聲明(忽略)
//執行階段
console.log(x);
console.log(x());
x=1;
console.log(x);
console.log(x());

如上代碼所述,js將變量和函數的聲明前置,然后再執行代碼。

  • 第二次輸出時,因為聲明階段已經聲明過名為x的函數,所以在執行階段中調用x函數,會執行函數體中的內容。
  • 第三次輸出時,輸出1,因為x被賦值為1.
  • 第四次輸出時,因為x此時是一個變量而不是一個函數,所以js無法解釋“變量()”這樣的格式,就會提示“x is not a function”。

第5點解釋如下:當有兩個同名變量和兩個同名函數一起定義時,四個量的名字相同,那么后一個函數或者變量會覆蓋掉前一個對應的量(函數/變量)。

js中聲明過得變量名或函數名不會重復聲明,如果js代碼中有同名的函數或同名的變量時,程序如何運行,如下代碼:

console.log(x)
console.log(x());
var x=1;
var x=100;
function x(){
console.log(5);
}
function x(){
console.log(500);
}
console.log(x)
console.log(x());//此時x變

根據js解析代碼的特點,將代碼解析成如下:

//聲明階段
function x(){//函數聲明
//console.log(5);此句會被下句代碼覆蓋
console.log(500);
}
var x;//變量聲明,因為x已經聲明過了,此處不進行聲明(忽略)
//執行階段
console.log(x);
console.log(x());
x=1;
x=100;//x的值被覆蓋
console.log(x);
console.log(x());//此時x變成了一個變量

所以輸出的結果就是:

function x(){
                console.log(500);
 }

500

100
 Uncaught TypeError: x is not a function

----------------------------

所以:如果聲明了同名的函數其定義會被后者覆蓋,聲明了同名的變量其值也會被后者覆蓋

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM