每日進步一點點 2018 11 14

2021-08-31 21:27:21 字數 2946 閱讀 9715

function fn();

return this;

fn.getname =function ();

fn.portotype.getname = function ();

var getname = function ();

function getname();

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

fn.getname();

getname();

fn().getname();

getname();

new fn.getname();

new fn().getname();

new new fn().getname();

此題涉及的知識點眾多,包括變數定義提公升、this指標指向、運算子優先順序、原型、繼承、全域性變數汙染、物件屬性及原型屬性優先順序等等。

此題包含7小問,分別說下:

第一問先看此題的上半部分做了什麼,首先定義了乙個叫fn的函式,之後為fn建立了乙個叫getname的靜態屬性儲存了乙個匿名函式,之後為fn的原型物件新建立了乙個叫getname的匿名函式。之後又通過函式變數表示式建立了乙個getname的函式,最後再宣告乙個叫getname函式。

第一問的fn.getname自然是訪問fn函式上儲存的靜態屬性,自然是2,沒什麼可說的。

第二問第二問,直接呼叫getname函式。既然是直接呼叫,那麼就是訪問當前上文作用域內的叫getname的函式,所以1 2 3都沒什麼關係。此題有無數面試者回答為5。此處有兩個坑,一是變數宣告提公升,二是函式表示式。

變數宣告提公升:

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

例如下**:

console.log('a' in window);//true

var a;

a=0;

**執行時js引擎會將宣告語句提公升至**最上方,變為:

var a;

console.log('a' in window);//true

a=0;

函式表示式:

var getname與function getname都是宣告語句,區別在於var getname是函式表示式,而function getname是函式宣告。關於js中的各種函式建立方式可以看  大部分人都會做錯的經典js閉包面試題  這篇文章有詳細說明。

函式表示式最大的問題,在於js會將此**分拆為兩行**分別執行。

例如下**:

console.log(a);//輸出:function a(){}

var a=1;

function a(){}

實際執行的**為,先將var a=1拆分為var a;和a=1;兩行,再將var a;和function a(){}兩行提公升至最上方變成:

var a;

function a(){}

console.log(a);

x=1;

所以最終函式宣告的a覆蓋了變數宣告的a,log輸出為a函式。

同理,原題中**最終執行時的是:

function fn();

return this;

var getname;//只提公升變數宣告

function getname();//提公升函式宣告,覆蓋var的宣告

fn.getname = function ();

fn.prototype.getname = function();

getname = function();//最終的賦值再次覆蓋function getname宣告

getname();//最終輸出4

第三問第三問的fn().getname();先執行了fn函式,然後呼叫fn函式的返回值物件的getname屬性函式。

fn函式的第一句getname = function();是一句函式賦值語句,注意它沒有var宣告,所以先向當前fn函式作用域內尋找getname變數,沒有。再向當前函式作用域上層,即外層作用域內尋找是否含有getname變數,找到了,也就是第二問中的alert(4)函式,將此變數的值賦值為function()。

此處實際上是將外層作用域內的getname函式修改了。

注意:此處若依然沒有找到會一直向上查詢到window物件,若window物件中也沒有getname屬性,就在window物件中建立乙個getname變數。

之後fn函式的返回值是this,而js的this問題中已經有非常多的文章介紹,這裡不再多說。

簡單地講,this的指向是由所在函式的呼叫方式決定的。而此處的直接呼叫方式,this指向window物件。

遂fn函式返回的是window物件,相當於執行window.getname(),而window中的getname已經被修改為alert(1),所以最終會輸出1.

此處考察了兩個知識點,乙個是變數作用域問題,乙個是this指向問題。

第四問直接呼叫getname函式,相當於window.getname(),因為這個變數已經被fn函式執行時修改了,遂結果與第三問相同,為1.

第五問new fn.getname();,此處考察的是js的運算子優先順序問題。實際上將getname函式作為了建構函式來執行,遂彈出2.

第六問new fn().getname();,首先看運算子優先順序括號高於new,實際執行為(new fn()).getname();

遂先執行fn函式,而fn此時作為建構函式卻有返回值,原題中,返回的是this,而this在建構函式中本來就代表當前例項化物件,遂最終fn函式返回例項化物件。

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

遂最終輸出3.

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

最終實際執行為:

new (new fn()).getname();

先初始化fn的例項化物件,然後將其原型上的getname函式作為建構函式再次new。

遂最終結果為3.

每日進步一點點 偏函式的學習使用

usr bin env python coding utf 8 devversion python3.6.8 date 2021 11 16 22 39 pycharm test from functools import partial 偏函式的學習 1.解決某些方法呼叫只能傳函式名,但傳的函式需...

每天進步一點點

很多朋友總喜歡問 成功靠什麼?其實,成功很難單一的歸納為靠什麼條件,如果一定要回答,只能從某種意義上說 很多人的成功就是靠他們每天比別人 多做一點點 正如古人有云 業精於勤,荒於嬉。這裡所說的勤,也就是比別人多做一點點,即付出多一點的勞動和努力。不要小看這一點點,又如古語說 集腋成裘,積沙成丘。如果...

每天進步一點點

在模組化程式設計時,在子模組中宣告變數 例如unsigned char aa 不需要在標頭檔案中宣告 要在主函式中呼叫,要寫成 extern unsigned char aa 而不能寫成 extern aa 寫成extern aa 則無法改變aa的值。2014年9月22日 21 12 00 品質因數...