前言:下面的方法能快速的解面試題,主要針對 =>作用域與變量提升的面試題<= 。並且沒有this改變指向的情況
(有錯或者不足的地方,隨時修改補充)
函數的兩種形似:1.函數申明(function xx(){ })。2.函數表達式(let xx = function(){ })。
變量提升(預解析):瀏覽器剛打開就會預先把帶var的 和 函數申明(function xx(){ })進行變量提升,var xx =undefined | xx=function xx(){ }
作用域:全局作用域:window。 局部作用域:函數體內。 ES6中還有塊的概念,塊:是個花括號 { } =>在函數申明被花括號包着的括號上方,打印函數是undefined
重名:如果var 了一個或多個變量,和聲明一個或多個函數,重名了。此時可以看做(變量提升的時候,后面的覆蓋了前面的,函數申明 覆蓋了 var。)
/*********************上面是知識基礎,是鋪墊。*************下面是總結的一套方法**************************/
1.沒有參數的時候:看有沒有var,或者函數申明(也就是說如果有變量提升,在函數體內就變成私有變量了,函數體內修改了不會影響父級。)
有,子集是undefined,也不會找父級,下面修改了(簡單和復合類型)都不會影響父級。
沒有,子集找不到,會找到父級,下面修改了(簡單和復合類型)都會影響父級。
2.有參數的時候:(有傳參,在函數體內就變成私有變量了,函數體內修改了 不會影響父級。除非用的同一個空間地址,也就是復合函數)
子集找不到,或者是undefined,(有沒有var,或者函數申明)都會找參數,簡單類型修改了不會影響父級,復合類型修改了會影響父級,除非重新賦址了。
例子1:
1 /*全局作用域 2 1.變量提升:先找var 和函數申明 3 var a = undefined 4 fn = function fn(){...} 5 2.從上而下逐行解讀代碼:只看 = 號后面的 6 */ 7 console.log(fn); //fn = function fn(){...} 8 var a = 5; 9 console.log(a);//5 10 11 function fn() { 12 /*局部作用域 13 1.變量提升:先找var 和函數申明 14 var a = undefined 15 var fn = undefined 16 fn = function fn(){alert(1);} 17 (重名了,函數 覆蓋了 var) 18 2.從上而下逐行解讀代碼:只看 = 號后面的 19 */ 20 fn = 30; 21 console.log(fn); //30 22 var fn = function () { 23 alert(1); 24 }; 25 a = 50; 26 console.log(fn, a); //function(){alert(1);},50 27 function fn() { 28 alert(5); 29 } 30 console.log(fn); //function(){alert(1);} (解讀的時候看 = 等號,有等號賦值后就看等號后面的) 31 var a = fn = 70;//相當於var了一個a = 70 和賦值了一個 fn = 70 32 console.log(a, fn); //70,70 33 //window.fn = 70; 34 window.a = 80 35 } 36 fn(); 37 console.log(a, fn); //80,整個大的代碼塊 (沒有參數,看函數體內有沒有var fn 和fn的函數聲明。有,函數體內形參私有作用域,里邊的fn改變了,不會影響外面的fn,除非是掛在window下,比如window.a = 80)
例子2:
1 function b(x, y, a) { 2 console.log(a);//3 先找本身有沒有,本身找不到,會找參數有沒有,再找父級,找到全局。為止,全沒有就報錯。 3 arguments[2] = 10;//相當於 a = 10 4 console.log(a);//10 本身找的到,,就不會往外找 5 } 6 a = b(1, 2, 3); 7 console.log(a);//a,拿到時是函數b的默認返回值,(undefined)
結語:想把這種類型的題目吃透,一定要多練,光說不練假把式。復雜一點,還要學習閉包的機制,this指向的問題,運算符優先級的問題,下面再給個例子
例子3:(考慮 運算優先級的面試題)
1 var a=9; 2 function fn(){ 3 a=0; 4 return function(b){ 5 return b + (a++);//b先加上a,得出結果。a再自增 6 } 7 } 8 var f=fn();//a = 0 9 console.log(f(5)); //5 a = 1 10 console.log(fn()(5)); //a=0 5 a = 1 11 console.log(f(5)); //6 a=2 12 console.log(a); //2
例子4:(閉包 和 this指向 的綜合面試題)
1 var num = 10; 2 var obj = {num: 20}; 3 /* 4 obj = { 5 num:20, 6 fn:function (n) { 7 this.num += n; 8 num++; 9 console.log(num); 10 } 11 } 12 fn = function (n) { 13 this.num += n; 14 num++; 15 console.log(num); 16 } 17 */ 18 obj.fn = (function (num) { //num=20 19 //window.num = 60 20 this.num = num * 3; 21 num++; 22 //num=21 23 return function (n) { 24 this.num += n; 25 num++; 26 console.log(num); //22 23 27 } 28 })(obj.num); //匿名函數自執行的this就是window 29 var fn = obj.fn; 30 fn(5);//60 += 5 65 window.num = 65 num=22 31 obj.fn(10); //20 += 10 obj.num = 30 32 console.log(num, obj.num); //65 30