前端 面試 記錄一些有意思的題目

2021-08-07 05:36:39 字數 3639 閱讀 4360

function

foo() ;

return

this;

}foo.getname = function () ;

foo.prototype.getname = function () ;

var getname = function () ;

function

getname()

//請寫出以下輸出結果:

foo.getname();

getname();

foo().getname();

getname();

new foo.getname();

new foo().getname();

newnew foo().getname();

先來理解下題目,首先建立了乙個foo()函式,然後在給foo函式增添乙個函式屬性getname,在foo原型上增添乙個getname函式屬性,然後再以函式表示式和函式宣告分別建立了乙個同名函式getname。

第一問:foo.getname()返回2。

第二問:首先需要知道函式表示式和函式宣告的區別。

函式宣告具有變數宣告提公升(即所有宣告變數或宣告函式都會被提公升到當前函式的頂部)

例:

console.log('x'

inwindow);

console.log(typeof func);

var x = 0;

function

func(){}

js引擎會將其解析為:

var x;

function

func(){}

console.log('x'

inwindow); //true

console.log(typeof func); //function

x = 0;

如果能明白的話就能理解下面**的輸出:

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

var x = 1;

console.log(x); //1

function

x(){}

console.log(x); //1

所以js引擎在解析**時候就變成了:

//省略部分**

function

foo() ;

return

this;

}var getname;

function

getname()

getname = function () ;

getname(); //4

後面函式表示式的賦值將前面的getname值個覆蓋了,所以第二問輸出4。

第三問:首先執行foo()函式,並執行getname的賦值語句。

它會查詢當前作用域上是否存在這個變數,如果沒有就向它上層作用域繼續尋找,直到找到window全域性作用域,若還是沒有則在全域性作用域上建立getname變數,

因為window域中存在著getname這個變數即(var getname = function () ;),所以將其替換為(getname = function () ;)

並返回window物件,所以foo().getname()的結果為1;

若**改為:

function

foo() ;

return

this;

}foo().getname(); //typeerror: foo().getname is not a function.

建立getname時候多加乙個var,即在當前作用域中新增乙個區域性變數getname,而在執行完畢後該區域性變數就會被**,並且該函式返回window全域性物件,故在訪問window中的getname會報錯,因為沒有建立window物件無此變數。

即(getname = function () ;)

故此時getname();輸出結果為1。

第五問 new foo.getname(); ,此處考察的是js的運算子優先順序問題。

根據圖中優先順序的描述:

優先順序圖

可以得知:可以得知點(.)的優先順序高於new操作,所以原式相當於是:

new (foo.getname)();
所以結果為2;

第六問 new foo().getname()

根據表的執行結果為:(new foo()).getname();

js返回值分為三類:

1、沒有返回值則建立乙個空物件,並把函式中與this繫結的屬性新增;

function

f()var obj = new f(); // obj: 建立乙個物件,並繫結函式中this所繫結的屬性

2、若有返回值則檢查返回值的型別,若返回值為非引用型別,比如基本型別:(string,number,boolean,null,undefined),則js引擎會忽略該返回值,並且建立乙個新物件,並把函式中與this繫結的屬性新增;

function

f()var obj = new f(); // obj: 建立乙個物件,並繫結函式中this所繫結的屬性

3、若返回值是引用型別,則實際返回值為這個引用型別。

function

f();}

var obj = new f(); //obj:

如果理解這些,再來看下面乙個例子:

var obj;

function

f1()

obj = new f1(); //obj: f1

function

f2()

obj = new f2(); //obj: f2

function

f3()

obj = new f3(); //obj: string

從例子中我們可以得出:無論 『a』還是string('a')建立的都是基本型別值,而new string('a')則建立乙個字串包裝物件。

原題中,返回的是this,而this在建構函式中本來就代表當前例項化物件。

之後呼叫例項化物件的getname函式,因為在foo建構函式中沒有為例項化物件新增任何屬性,遂到當前物件的原型物件(prototype)中尋找getname,故最終輸出3。

第七問:new new foo().getname(); 同樣是運算子優先順序問題。

執行結果為:new ((new foo()).getname)();

先初始化foo的例項化物件,然後將其原型上的getname函式作為建構函式再次new,故最終結果為3

記錄一些有意思的前端面試題

1 乘積函式 function mul array.prototype let argus slice.call arguments,0 let returnfn function returnfn.valueof function returnfn.tostring null return ret...

一些比較有意思的題目

example 輸入 698592 k 4 輸出 6592 solution 一種比較常見的思路是列舉全部k 4的數字,然後再取最小值,然而這樣複雜度會很高。本文的思路是不斷遞迴求得最小值,注意邊界,可以顯著降低複雜度。void find min core vector vec,int k,int ...

一些有意思的東西

近日,在敲 的時候,筆者發現了一些有意思的東西。在我們用迴圈的時候,常常因為一些條件,要提前結束迴圈,而在c語言中,可以打破迴圈的就是break和continue了 1.看這個 它只輸出了兩個6,由此我們可以看出break是打破整個迴圈 2.再看關於continue 可以看出,它輸出了9個6,因此c...