javascript函數以及作用域簡介
javascript函數以及作用域簡介
作者:尹正傑
版權聲明:原創作品,謝絕轉載!否則將追究法律責任。
一.基本函數
對於JavaScript中函數參數,實際參數的個數可能小於形式參數的個數,函數內的特殊值arguments中封裝了所有實際參數。JavaScript中函數基本上可以分為以下三類:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5<title>尹正傑的基本函數</title> 6 </head> 7 <body> 8 9 <script> 10 //1.普通函數定義 11 function Get(name) { 12 console.log(name); //打印變量 13 } 14 Get("yinzhengjie"); 15 16 //2.自動執行函數, 17 (function (age) { 18 alert(age); //彈窗效果的變量19 })("18"); 20 21 function func(arg) { 22 arg() 23 } 24 //3.匿名函數,可以當做一個參數傳遞。 25 var yzj = function () {alert("尹正傑")}; 26 func(yzj) 27 28 </script> 29 30 </body> 31 </html>
二.作用域
1.什麽是作用域
JavaScript中每個函數都有自己的作用域,當出現函數嵌套時,就出現了作用域鏈。當內層函數使用變量時,會根據作用域鏈從內到外一層層的循環,如果不存在,則異常。變量的作用域是在聲明時決定的而不是調用執行時決定。也就是說,所有的作用域在創建函數且未執行時候就已經存在。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <script type="text/javascript"> //如果不寫類型的話,默認就是type="text/javascript",註釋方法和golang類似。 9 var a=100,b=200; 10 window.a =100; 11 window.b = 200; 12 function A() { 13 var a=33,b=99; 14 function B() { 15 var a=11,b=22; 16 console.log(a+b); 17 } 18 return B() 19 } 20 A() 21 </script> 22 </body> 23 </html>
2.詞法分析
我們瀏覽器是如果分析我們的html文件呢?其實瀏覽器內置了html,css,javascript引擎分別取解析不同的代碼。瀏覽器的js引擎在遇到函數的時候,在函數執行前,會進行一個預編譯,這個預編譯的過程就是詞法分析。會形成一個活動對象,即Active Object,簡稱AO。詞法分析分大致分為以下三個步驟:
a>.分析函數的參數:
如果沒有參數的話,AO對象沒有任何屬性,例如:AO.age = undefined。如果有的話就回接受參數的值。如AO.age = 100.
b>.分析函數的變量聲明:
會一次性拿到函數內的所有的變量名稱,我們稱如果沒有函數生命表達式就不處理,這些變量名稱為活動對象,它會將所有的變量保存起來,並賦值為undefined,當調用該函數的時候,它才會進行賦值操作。
c>.分析函數的函數聲明表達式
所謂的函數聲明表達式就是關鍵字“function(){}”,如果存在函數名稱和變量名稱重復, 就會用這個變量名稱將之前的變量進行覆蓋喲!
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <script> 9 var str = "locale"; //當然,也可以這樣寫: window.str = "locale"; 10 11 function t() { 12 console.log(str); //輸出“undefined” 13 var str = "locale"; 14 console.log(str); //輸出“locale” 15 } 16 t(); 17 </script> 18 </body> 19 </html>作用域案例1
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <script> 9 function t(age) { 10 console.log(age); //此時的age已經被下面的函數表達式覆蓋了,因此它的值為:“function age() {}”, 11 var age =99; 12 console.log(age); //它的值應該是99,因為我們在他的上一行已經定義了他的值。 13 function age() { 14 } 15 console.log(age); //同理,其值還是99 16 } 17 t(5); 18 </script> 19 </body> 20 </html>作用域案例2
如果你對詞法分析的知識掌握以及很透徹了,那麽上面的2道企業的面試題,你是否一眼能看出真身呢?
三.閉包函數
1.什麽是閉包函數
官方”的解釋是:閉包是一個擁有許多變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分。相信很少有人能直接看懂這句話,因為他描述的太學術。我對閉包函數的理解就是父函數可以取到子函數的變量的函數就叫閉包函數。相信學習了作用域,也都明白全局變量和局部變量的意思吧,我們可以知道在函數中,一個局部變量作用域可以很輕松的拿到全局變量的數值,但是在全局變量作用域中想要拿到局部作用域的變量就得利用閉包函數啦。
2.閉包的作用
閉包可以用在許多地方。它的最大用處有兩個,一個是前面提到的可以讀取函數內部的變量,另一個就是讓這些變量的值始終保持在內存中。我們可以看以下案例:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>尹正傑的閉包函數</title> 6 </head> 7 <body> 8 <script> 9 function A(){ 10 var n= 999; 11 nAdd = function(){n+=1001}; 12 function B(){ 13 alert(n); 14 } 15 return B; 16 } 17 var result=A(); 18 result(); //調用A函數,於是會生成n和nAdd這兩個變量,與此同時還會返回B的執行結果. 19 nAdd(); //我們將匿名函數nAdd執行。 20 result(); //由於上面執行了nAdd匿名函數,也就是將n的數值增加1001,因此我們看到的結果應該是2000才對。 21 </script> 22 </body> 23 </html>
3.使用閉包的註意點
a>.由於閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。解決方法是,在退出函數之前,將不使用的局部變量全部刪除。
b>.閉包會在父函數外部,改變父函數內部變量的值。所以,如果你把父函數當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數內部變量的值。
四.面向對象
其實在javascript編程裏面,並沒有用關鍵字定義一個對象類,它不像python或是golang等其他語言,有類似關鍵字“class”,或是“type .... struct”來聲明一個對象。我們定義javascript的對象時,其實還是用function關鍵字來定義,只不過我們定義函數時並麽有要求首字母是否大寫,而定義一個對象時,潛規則就是函數名的首字母需要大寫。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>尹正傑的面向對象</title> 6 </head> 7 <body> 8 <script> 9 //定義一個javascript的類,並初始化內部數據。 10 function Foo(name,age) { 11 this.Name = name; 12 this.Age = age; 13 } 14 15 //給我們定義j具體的方法.我們稱之為利用原型實現方法重用. 16 Foo.prototype = { 17 "show":function () { 18 alert(this.Name); 19 }, 20 "print":function () { 21 alert("尹正傑"); 22 } 23 }; 24 25 //實例化我們定義的對象,生成obj. 26 obj = new Foo("尹正傑",18); 27 alert(obj.Name); 28 alert(obj.print); 29 30 </script> 31 </body> 32 </html>
javascript函數以及作用域簡介