1. 程式人生 > >JS中常見的 “函式名 is not a function” 錯誤

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

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

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

首先看程式碼:

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

  • 第一次輸出x時,輸出的是x函式,但是x變數的宣告在x函式之前,就算要輸出也應該輸出的是undefined,為什麼會輸出函式?

js上下文中無非就是變數、函式、函式引數,那麼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”。

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(3);
}
var x;//變數宣告,因為x已經宣告過了,此處不進行宣告(忽略)
//執行階段
console.log(x);
console.log(x());
x=1;
x=100;//x的值被覆蓋
console.log(x);
console.log(x());

所以輸出的結果就是:

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

3

100
 Uncaught TypeError: x is not a function

針對變數名同名或函式名同名的情況,我們又可以得出一個特點:如果聲明瞭同名的函式其定義會被後者覆蓋,聲明瞭同名的變數其值也會被後者覆蓋