前段時間我朋友從上家公司離職,上週開始了前端面試(現在已經上班了),一天我下班回到出租房時,他問我原型鏈是什麼?一時半會我竟然也不知道從何說起能夠讓他很清楚的明白,又忽然想起之前我一個朋友也問過我閉包的問題,因此在這裡記錄解惑一下,下面我會以面試官和應聘者的口吻進行介紹理解......
一.閉包
面試官:什麼是閉包?閉包你瞭解嗎?
應聘者:閉包就是能夠讀取其他函式內部變數的函式。
面試官:通俗一點呢?
應聘者:通俗的講就是函式a的內部函式b,被函式a外部的一個變數引用的時候,就建立了一個閉包。
面試官:是這樣,沒錯,那你知道什麼情況下會用到閉包嗎?
應聘者:最常見的是函式封裝的時候,再就是在使用定時器的時候,會經常用到...
面試官:那你簡單寫一個閉包吧
應聘者:
function a(){ var i=0; function b(){ alert(++i); } return b; } var c = a(); c();//外部的變數
面試官:你這個寫法是正確的,那我衍生一下,你回答一下依次會彈出什麼:
function a(){ var i=0; function b(){
i++; alert(i); } return b; } var c = a(); c();//? c();//? c();//?
應聘者:應該是會依次彈出1,2,3。
面試官:沒錯,你回答的很對,你知道其中的原理嗎?能否解釋一下
應聘者:好的,i是函式a中的一個變數,它的值在函式b中被改變,函式b每執行一次,i的值就在原來的基礎上累加 1 。因此,函式a中的i變數會一直儲存在記憶體中。
當我們需要在模組中定義一些變數,並希望這些變數一直儲存在記憶體中但又不會 “汙染” 全域性的變數時,就可以用閉包來定義這個模組。
面試官:非常棒,你說的這是它的一個用處,你能說一下閉包的用處有哪些嗎?
應聘者:它的最大用處有兩個,一個是它可以讀取函式內部的變數,另一個就是讓這些變數的值始終保持在記憶體中。
面試官:那我順便再出個問題考考你吧,請看題:
var num = new Array(); for(var i=0; i<4; i++){ num[i] = f1(i); } function f1(n){ function f2(){ alert(n); } return f2; } num[2](); num[1](); num[0](); num[3]();
應聘者:答案為2,1,0,3(這個時候你瞭解清楚閉包之後,這個答案應該就是隨口而出),解釋如下:
//建立陣列元素 var num = new Array(); for(var i=0; i<4; i++){ //num[i] = 閉包;//閉包被呼叫了4次,就會生成4個獨立的函式 //每個函式內部有自己可以訪問的個性化(差異)的資訊 num[i] = f1(i); } function f1(n){ function f2(){ alert(n); } return f2; } num[2](); //2 num[1](); //1 num[0](); //0 num[3](); //3
面試官:那你知道閉包的優缺點嗎?
應聘者:
優點:
① 減少全域性變數;
② 減少傳遞函式的引數量;
③ 封裝;
缺點:
① 使用閉包會佔有記憶體資源,過多的使用閉包會導致記憶體溢位等
面試官:正好你提到了記憶體洩漏,說說你的解決方法
應聘者:簡單的說就是把那些不需要的變數,但是垃圾回收又收不走的的那些賦值為null,然後讓垃圾回收走;
面試官:看來閉包已經難不倒你了,閉包就到這裡告一段落了,接下來考考你原型和原型鏈。
二.原型和原型鏈
面試官:你好,接下來考考你原型和原型鏈
應聘者:好的,請問
面試官:你解釋一下原型的概念吧!
應聘者: 原型(prototype)是function物件的一個屬性,它定義了建構函式製造出的物件的公共祖先(公共的屬性和方法)通過該建構函式產生的物件,可以繼承改原型的屬性和方法。 原型也是物件。
面試官:通俗一點呢?
應聘者:通俗的說,原型就是一個模板,更準確的說是一個物件模板
面試官:那你接著說一下原型鏈是什麼?
應聘者:每個建構函式都有一個原型物件,原型物件都包含一個指向建構函式想指標(constructor),而例項物件都包含一個指向原型物件的內部指標(__proto__)。如果讓原型物件等於另一個型別的例項,此時的原型物件將包含一個指向另一個原型的指標(__proto__),另一個原型也包含著一個指向另一個建構函式的指標(constructor)。假如另一個原型又是另一個型別的例項,如此層層遞進,這就構成了例項與原型的鏈條。這就是原型鏈的基本概念;
面試官:你這個說太多了,簡單一點
應聘者:就是利用原型讓一個引用型別繼承另一個引用型別的屬性和方法;
舉例說明: Student → Person → Object ,學生繼承人類,人類繼承物件類
面試官:我看你說到了繼承,那你簡單寫一個原型鏈繼承的例子
應聘者:好,如下
function Animal(name) { this.name = name } Animal.prototype.getName = function() { console.log(this.name) } var animal1 = new Animal('Kate') var animal2 = new Animal('Lucy') //物件animal1 和 animal2共享方法getName animal1.getName() animal2.getName()
面試官:ok,那我出個問題考考你,你告訴我結果,題目如下:
var A=function(){} A.prototype.n=1 var b=new A() A.prototype={ n:2, m:3 } var c=new A() console.log(b.n,b.m,c.n,c.m)//多少
應聘者:答案為1,undefined,2,3。原因是b繼承A,所以b.n就為1,而m在A中找不到,所以為undefined,以此類推,c繼承的時候A新增了n和m,所以c.n和c.m分別是2和3;
面試官:你回答的很棒,你知道null和undefined的區別嗎?
應聘者:undefined
是一個表示"無"的原始值,
null
用來表示尚未存在的物件,
面試官:很正確,再出個問題給你,問題如下:
var F=function(){}; Object.prototype.a=function(){ console.log('a()') }; Function.prototype.b=function(){ console.log('b()') } var f=new F(); f.a()//? f.b()//? F.a()//? F.b()//?
應聘者:答案應該為a()、報錯找不到b這個函式、a()、b()。(如果你能瞬間回答出這個答案就代表你已經瞭解原型和原型鏈了)
面試官:看來原型原型鏈也難不倒你了,那面試就到這裡告一段落了。
三.總結
閉包和原型原型鏈的介紹就到這裡介紹了,如果上面有哪些解釋有錯誤麻煩大家指正一下,謝謝了!附加一下我上文提到的朋友:https://www.cnblogs.com/zmayan/p/10912699.html