語法分析, 分析3樣東西 第1步: 先分析參數 第2步: 再分析變量聲明 第3步: 分析函數聲明 一個函數能使用的局部變量,就從上面的3步分析而來 具體步驟: 0: 函數運行前的1瞬間, 生成 Active Object (活動對象),下稱AO 1: 1.1 函數聲明的參數,形成AO的屬性,值全是undefined, 1.2 接收實參,形成AO相應的屬性的值 2: 分析變量聲明聲明聲明! 如 var age, 如果AO上還沒有age屬性,則添加AO屬性,值是undefined 如果AO上已經有age屬性,則不做任何影響 3: 分析函數聲明,如 function foo() {}, 則把函數賦給AO.foo屬性 注: 如果此前foo屬性已存在,則被無情的覆蓋了 */ function t(age) { alert(age); } t(5); // 5 t();// undefined /* 詞法分析過程: AO {age:undefined} 運行過程: t(5)--> AO.age=5; alert(AO.age); //5 t() ---> AO.age沒得到賦值, 還是undefined */ function t2(age) { var age = 99; alert(age); } t2(5); /* 分析過程: 0: 形成AO = {} 1: 1.1 分析形參 AO = {age:undefined} 1.2 接收形參 AO = {age:5} 2: 分析var age, 發現AO已有age屬性,不做任何影響 執行過程: AO.age = 99; alert(age); */ function t3(greet) { var greet = 'hello'; // 試着把這一句變成 var greet;再做分析 alert(greet); function greet() { } alert(greet); } t3(null); // hello hello /* 詞法分析過程: 0: AO = {} 1: 1.1 分析參數 AO = {greet:undefined} 1.2 分析參數 AO = {greet:null} 2: 分析greet變量聲明,AO已經有greet屬性,因此不做任何影響 3: 分析greet函數聲明, AO.greet = function() {} , 被覆蓋成函數 執行過程: greet = 'hello'; alert(greet); alert(greet); */ // 再看這道題 function a(b) { alert(b); function b(){ alert (b); } b(); } a(1); /* 分析期: 0: AO = {} 1: 1.1分析參數 AO = {b:undefined} 1.2接收參數 AO = {b:1} 2: 分析var 聲明,此函數沒有var 3: 分析函數聲明, AO = {b: function(){alert(b);}} 執行期: alert(b); // function b(); // 由作用域尋找到a函數中的b,即 function,alert()出來 */ function a(b) { alert(b); b = function (){ alert (b); } b(); } a(1); /* 學員常見答案: 1,1 1, function 1, undefined function ,function */ /* 詞法分析過程: 0: AO = {} 1: 分析參數 AO = {b:undefined} --> {b:1} 2: 分析var聲明,沒有. 3: 分析函數聲明?? 沒有! (注: b = function() {} ,是一個賦值過程,在執行期纔有用) 執行過程: alert(b); // 1 b = function() { alert(b); } b(); // function */ // 函數聲明,與函數表達式 /* JS被稱爲披着C外衣的Lisp語言, lisp是一種強大的函數式語言 函數可以賦值給變量,可以作爲參數來傳遞. */ function t1() { } t2 = function() { } // 這2種方式,效果不同的, // t1是函數聲明, 雖然全局內也得到一個t1變量,值是function // 而t2 只是一個賦值過程------值是誰? 值是右側的表達式的返回結果,即函數 // 就是說 function () {} 在js看來,就和 3*2, 6/3 一樣,是個表達式,返回一個結果 // 因此,t1 t2 兩種方式在詞法分析時,有着本質區別 // 前者 在詞法分析階段,就發揮作用 // 而後者,在運行階段,才發揮作用 // 知道了函數表達式的概念,再看看一個你以前看不懂的東西 (function(window,undefined) { })(window); 這是jquery的最外層代碼 /* (function(window,undefined){}) // 內層表達式,返回值是函數,包在小括號裏,當成表達式來執行\ (function(window,undefined){})(window) // 立即調用 // 而內層函數又沒有起名字,稱爲匿名函數, // 這種手法,匿名函數,立即執行,不污染全局. 稱爲 立即執行匿名函數表達式 */ // 思路: 爲什麼傳window, 而又不會傳undefined? /* 答: 傳window是爲了速度 function() { function() { function () { function () { function () { document.getElementById... // 這個document將會尚作用域層層上找,直到最外層 } } } } } jquery就是爲了加快內部查找變局變量的速度, 而直接把window以參數形式傳進來 這樣 window 就在jquery內部的 AO上 不傳undefined是爲了安全 因爲在IE,FF低版本中 , undefined竟然可以重新賦值 ,如 undefined = 3; 聲明undefined局部變量(名字是undefined而已), 同時,又不傳參,值自然是undefined 防止了外界對undefined的污染 */
function t1(){ var d function t2(){ d = 5; e=6; }t2();}t1();console.log(d); //d is not definedconsole.log(e); //6console.log(window.d);//undefined
//注意:變量以window.xxx引用,變量不存在,以某個屬性不存在報的錯 undefined
// 變量以xxx引用的時候,尋找不到,則報的是 xxx is not undefined
// var 僅僅是一個聲明變量的操作, d = 5 只是一個賦值操作