函式宣告和原型鏈

2021-08-18 18:45:32 字數 3529 閱讀 8850

今天整理了一天的二叉樹,卻還是一頭霧水,不知道大家有沒有學習的好方法,之前以為前端不需要資料結構和演算法如此精通。看了一些筆試題之後心灰意冷了。今後整理好會發布的

var a=function(name)

var b=function(name)

var c=function(name);

a.prototype.name="tom";

b.prototype.name="tom";

c.prototype.name="tom";

//求下面三個輸出值

alert(new a().name);//tom

alert(new b().name);//undefined

alert(new c().name);//jon

這題考到的知識點是原型鏈,首先new a()是new乙個帶引數列表,也就生成了a的例項物件,但是我們沒有傳入引數(undefined),a的情況是先判斷是否有name,因為在建構函式上name為undefined嘛,所以不會走到this.name=name這句話,於是它向原型物件上找這個屬性,找到了tom。

在「較真的前端」看到一道題,感覺有點類似,也拿出來和大家分享。

function foo();

return this;

}foo.getname = function();

foo.prototype.getname = function();

var getname = function();

function getname();

接來下是幾個各種變形的問題:

foo.getname();
此處是呼叫靜態方法,無需例項化,所以答案是2

getname();
呼叫全域性的getname()函式,本例有函式宣告和函式表示式兩種,函式宣告被提公升到作用域最前面,而函式表示式是建立函式時進行賦值,所以答案為4。且需要等到表示式賦值那句話才能呼叫(因為是函式,如果是變數則為空),之前呼叫的話是:

uncaught typeerror: getname is not a function

foo().getname();
先執行foo函式,將getname賦值function();注意此刻getname是沒有var的,所以先向當前foo函式作用域內尋找getname變數,再向當前作用域的上層尋找(即window),也就是第二問的alert(4)函式。於是改變了window的getname函式。之後它返回的是this,這個this指的是window,所以此句相當於window.getname()。考察了變數作用域和this指向問題

getname();
直接呼叫getname()函式相當於呼叫window.getname(),但已經在第三問的時候改了,於是答案是1

new foo.getname();
運算子優先順序!!!點的優先順序》new無引數;點運算完後有個括號(),此時變成了new有引數列表,所以直接執行new,new有引數》函式呼叫。答案是2

new foo().getname();
相當於(new foo()).getname();首先new有引數列表(18)跟點的優先順序(18)是同級,同級的話按照從左向右的執行順序,所以先執行new有引數列表(18)再執行點的優先順序(18),最後再函式呼叫(17)。括號內是優先順序。也就是先new了乙個建構函式foo的例項物件,new出來的例項物件的this指向的就是這個例項物件本身。因為建構函式本身沒有賦值this.getname,所以只能去原型鏈上找,於是找到了3

new new foo().getname();
最後一問是上面一題的變形,相當於(new (new foo()).getname)();將上一問的getname(即原型鏈上的)當作建構函式再例項化乙個物件,所以結果依然是3

var a="00";

(function())();

可以結合上一題的擴充套件題中的函式宣告一起體會一下!幸好此處是變數,如果此處是函式的話就會報錯啦!因為函式呼叫要在函式表示式賦值之後(除非你還有個函式宣告,即匿名函式那種形式)。

(typeof (new (class  })))
拆開來看

var test = class

};typeof test;//"function"

var test = new test();

typeof test;//"object"

這裡的難點反而不是es6語法了。請謹記new關鍵字做了什麼:

建立乙個物件obj

將此物件obj的__proto__指向構造器的prototype

this指向新物件obj,並用新建立的物件obj執行建構函式

返回這個物件obj

所以test作為test的例項表示新返回的物件,typeof test自然為"object"。

(function() )();

console.log(typeof a!=='undefined');//false

console.log(typeof b!=='undefined');//true

個人覺得這道題的難點不在於從左到右宣告,從右到左賦值。而是原本不存在於window中的a竟然可以用typeof來訪問。。。

console.log(a);//undefined

console.log(b);//b is not defined

var a = b = 2;

如第四題所言,new會返回乙個新的物件,所以只要看見new,object的一系列相關問題就都要帶上。string()與直接字面量是沒有區別的。

var obj1 = new string("wihihoeid");

var obj2 = new string("wihihoeid");

console.log(obj1 == obj2);//false

console.log(obj1 === obj2);//false

var obj3 = "wihihoeid";

var obj4 = string("wihihoeid");

console.log(obj3 == obj4);//true

console.log(obj3 === obj4);//true

原型和原型鏈 及 instanceof函式

function a var a new a a a.proto a.prototype a.prototype.proto object.prototype object.prototype.proto null定義 instanceof運算時會遞迴查詢l的原型鏈,即l.proto proto p...

原型和原型鏈 及 instanceof函式

function a var a new a a a.proto a.prototype a.prototype.proto object.prototype object.prototype.proto null定義 instanceof運算時會遞迴查詢l的原型鏈,即l.proto proto p...

原型和原型鏈 及 instanceof函式

function a var a new a a a.proto a.prototype a.prototype.proto object.prototype object.prototype.proto null定義 instanceof運算時會遞迴查詢l的原型鏈,即l.proto proto p...