一道簡單的面試題引起的思考

版權聲明:此文首發於個人簡書帳號人生還有多少個二十年,轉載請註明出處。前端

此處有幾百字嘮叨:
  當天,我早早起牀,跨越上百千米,高德導航,路人指點,跌跌撞撞到達招聘會現場,當時已經是中午十二點半,吃了午飯(半瓶白開水),開始準備投遞簡歷。繞場2周,發現能提供我想要的崗位(前端開發)的公司有十家左右。我總共帶了5份簡歷,投遞了4家中意的公司,其中2家直接現場面試。
  先說說最糟糕的那場面試: 「我是來應聘Web開端的」 (而後面試官糾正了一下,「Web前端」,尷尬了)。面試官接着就個人簡歷提了若干問題,基本上對簡歷的提問,未涉及技術細節,其中有「你github上的代碼有人看嗎?」(我又尷尬了,github上傳的只是我本身作過的一些做品,上傳的目的只是爲了讓HR可以看到我寫的代碼,從未在其它地方說起我有github帳號,天然是沒人訪問了)。當時由於緊張,還有近期睡眠不足,頭腦很遲鈍,問題大多回答得一塌糊塗。
  另外一場面試,面試官應該就是該公司的技術人員,提問的都是技術問題,問題不難,我基本上都會,由於本身平時也認真總結過一些,因此大多數回答地還算流暢。其中有兩個問題把個人臉都丟光了。一個是,「處理過瀏覽器的哪些兼容性問題」,我想了一兩分鐘竟然仍是想不出(腦子短路了)。學了一年多前端的我真沒接觸過兼容性問題嗎?其實,我接觸過的有很多,據說過的也有很多,例子那麼多,但是當時竟然想不出一個例子來(腦子短路了)。另外一個問題,就是我下面要說起的做用域問題,我當時思考的時間過久了...git

這是回憶中的面試題

(實際略有差別,不糾結了):github

function foo(){
    var a = b = 2;
}
foo();
alert(a);
alert(b);

question:說一下腳本的運行結果?
answer: 引用錯誤(FF中給出的錯誤提示:ReferenceError: a is not defined)。
reason:函數內聲明的變量的做用域爲函數做用域,在全局做用域中不能直接訪問到函數內變量的值;而在函數中未聲明就賦值的變量,在非嚴格模式下變成全局變量,成爲window對象的一個屬性,在嚴格模式下則會報錯。此題的代碼至關於如下代碼:面試

var b = 2;
function foo(){
    var a =b;
}
foo();
alert(a);  
alert(b);

顯然,全局做用域中是沒有變量a的,因此alert(a)會致使錯誤,腳本沒法繼續執行。數組

         簡單的面試題已結束, 哈哈,如今讓我當一回面試官吧?瀏覽器


改編題1

function foo(){
    var a = b = 2;
}
foo();
alert(b);
alert(a);

question: 說一下腳本運行的結果?
result:
alert(b); //2
alert(a); //ReferenceError: a is not defined
reason:原理同上函數


改編題2

function foo(){
    var a = b = 2;
}
foo();
alert(typeof a);
alert(typeof b);

question: 說一下腳本運行的結果?
result:
alert(typeof a); //undefined
alert(typeof b); //number
attention: 未定義的變量的數據類型爲undefined,並不會報錯。code


改編題3

var a = 1;
var b = 1;
function foo(b){
    var a = b = 2;
}
foo(b);
alert(a);
alert(b);

question: 說一下腳本運行的結果?
result:
alert(a); //1
alert(b); //1
reason:這裏我主要說一下b的結果,函數中參數中有變量b,至關於在函數中聲明瞭變量b,調用函數的時候,因爲基本類型的變量值是按值傳遞的,因此,函數的局部變量b被賦值爲1,接着,又對局部變量b的值進行了更新,但這並不會影響全局變量b的值,故全局變量b的值仍然爲1對象


改編題4

var a = 1;
var b = 1;
function foo(a,b){
       arguments[0]=2;
       arguments[1]=2;
       b = 3;
       console.log(a);
       console.log(b);
}
foo(a,b);
alert(a);
alert(b);

question: 說一下腳本運行的結果?
result:
console.log(a); //2
console.log(b); //3
alert(a); //1
alert(b); //1
reason: 此處我主要說一下arguments對象,它是函數的一個實參對象,是一個類數組,有length屬性,而且也能夠經過數組表示法獲取指定索引值的元素,甚至能夠被修改(簡言之,arguments對象的值可讀、可寫),對arguments對象的修改直接同步到存放實參的各個變量。索引


改編題5

foo();
alert(a);
alert(b);
function foo(){
    a = b = 2;
}

question: 說一下腳本運行的結果?
result:
alert(a); //2
alert(b); //2
question:函數未聲明,就調用,怎麼不會報錯?
reason:這是由於聲明被提早了(hoisting
),聲明被提高到做用域的頂部,此處,即全局做用域的頂部,在foo()以前。代碼至關於:

function foo(){
    a = b = 2;
}
foo();
alert(a);
alert(b);

改編題6

var a = 1;
var b = 1;
foo();
alert(a);
alert(b);
var foo = function(){
    var a = b = 2;
}

question: 說一下腳本運行的結果?
result:
TypeError: foo is not a function
reason: 這裏使用函數定義表達式,要清楚的是,聲明是會提早的,但賦值卻不會。換句話說,函數調用的時候,foo已經存在了(不信,你能夠試試alert(foo);),可是,它的值是undefined。因此,這裏就出現了類型錯誤。順便提一下,undefined和null沒有任何的屬性和方法。

END
這是個人github網址,初學者能夠看一下,應該會有所幫助。也歡迎大牛們蒞臨指導。

相關文章
相關標籤/搜索