成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

前端面試回顧(1)---javascript的面向?qū)ο?

animabear / 677人閱讀

摘要:每個(gè)類有三部分構(gòu)成第一部分是構(gòu)造函數(shù)內(nèi),供實(shí)例對(duì)象化復(fù)制用。第二部分是構(gòu)造函數(shù)外,直接通過(guò)點(diǎn)語(yǔ)法添加,供類使用,實(shí)例化對(duì)象訪問(wèn)不到。組合繼承還有一個(gè)要注意的地方在代碼處,將子類原型的屬性指向子類的構(gòu)造函數(shù)。

前言

前一陣面試,過(guò)程中發(fā)現(xiàn)問(wèn)到一些很基礎(chǔ)的問(wèn)題時(shí)候,自己并不能很流暢的回答出來(lái)。或者遇到一些基礎(chǔ)知識(shí)的應(yīng)用,由于對(duì)這些點(diǎn)理解的不是很深入,拿著筆居然什么都寫(xiě)不出來(lái),于是有了回顧一下這些基礎(chǔ)知識(shí)的想法。

首先就是面試中經(jīng)常會(huì)問(wèn)到的,JS是怎么實(shí)現(xiàn)繼承的,其實(shí)問(wèn)到繼承,面試官想問(wèn)的可能還是你對(duì)JS面向?qū)ο蟮睦斫獍伞?/p>

這一部分的主要參考資料:《JavaScript高級(jí)程序設(shè)計(jì)》、《JavaScript設(shè)計(jì)模式》
如果有什么錯(cuò)誤的地方,也希望看到這篇文章的小伙伴給我指出來(lái),謝謝 ^_^

一、對(duì)象 1.1創(chuàng)建對(duì)象

Javascript是一種基于對(duì)象(object-based)的語(yǔ)言,你遇到的所有東西幾乎都是對(duì)象。
一個(gè)簡(jiǎn)單的對(duì)象創(chuàng)建:

var People = {
    name : "eavan",
    age : 24,
    getName : function(){
        alert(this.name);        //eavan
    }
}

使用的時(shí)候就可以用People.name,獲取People這個(gè)對(duì)象的name屬性,或者是People.getName()來(lái)得到People的name值。
另一種對(duì)象創(chuàng)建方式:


var People = new Object();
People.name = "eavan";
People.age = 24;
People.getName = function(){
    alert(this.name);
}
    

這里用到了new,就順便提一下在使用new的時(shí)候發(fā)生了什么,其實(shí)在使用new的時(shí)候,大致可以認(rèn)為做了這三件事,看下面的代碼:

var People  = {};                      //我們創(chuàng)建了一個(gè)空對(duì)象People
People.__proto__ = Object.prototype;   //我們將這個(gè)空對(duì)象的__proto__成員指向了Object函數(shù)對(duì)象prototype成員對(duì)象
Object.call(People);         //我們將Object函數(shù)對(duì)象的this指針替換成People,然后再調(diào)用Object函數(shù)
1.2封裝

簡(jiǎn)單來(lái)說(shuō)就是對(duì)一些屬性的隱藏域暴露,比如私有屬性、私有方法、共有屬性、共有方法、保護(hù)方法等等。而js也能實(shí)現(xiàn)私有屬性、私有方法、共有屬性、共有方法等等這些特性。

像java這樣的面向?qū)ο蟮木幊陶Z(yǔ)言一般會(huì)有一個(gè)類的概念,從而實(shí)現(xiàn)封裝。而javascript中沒(méi)有類的概念,JS中實(shí)現(xiàn)封裝主要還是靠函數(shù)。

首先聲明一個(gè)函數(shù)保存在一個(gè)變量里面。然后在這個(gè)函數(shù)(類)的內(nèi)部通過(guò)對(duì)this變量添加屬性或者方法來(lái)實(shí)現(xiàn)對(duì)類添加屬相或者方法。

var Person = function(){
    var name = "eavan";             //私有屬性
    function checkName(){};         //私有方法

    this.myName = "gaof";            //對(duì)象共有屬性
    this.myFriends = ["aa","bb","cc"];
    this.copy = function(){}         //對(duì)象共有方法

    this.getName = function(){       //構(gòu)造器方法
        return name;
    };            
}

純構(gòu)造函數(shù)封裝數(shù)據(jù)的問(wèn)題是:對(duì)像this.copy = function(){}這種方法的創(chuàng)建,其實(shí)在執(zhí)行的時(shí)候大可不必綁定到特定的對(duì)象上去,將其定義到全局變量上也是一樣的,而且其過(guò)程相當(dāng)于實(shí)例化了一個(gè)Function,也大可不必實(shí)例化這么多其實(shí)干同一件事的方法。而這個(gè)小問(wèn)題的解決可以用原型模式來(lái)解決。

1.3理解原型

在每創(chuàng)建一個(gè)函數(shù)的時(shí)候,都會(huì)生成一個(gè)prototype屬性,這個(gè)屬性指向函數(shù)的原型對(duì)象。而其是用來(lái)包含特定類型的所有實(shí)例共享的屬性和方法。所以,直接添加在原型中的實(shí)例和方法,就會(huì)被所有實(shí)例所共享。

同樣還是上面的Person的例子,我們可以為其原型添加新的屬性和方法。

Person.isChinese = true;                          //類的靜態(tài)共有屬性(對(duì)象不能訪問(wèn))
Person.prototype.sex = "man" ;            //類的共有屬性
Person.prototype.frends = ["gao","li","du"];
Person.prototype.isBoy = function(){};    //類的共有方法

原型封裝數(shù)據(jù)的問(wèn)題:對(duì)綁定在prototype上的引用類型的變量,由于被所有對(duì)象所共有,其中某一個(gè)對(duì)象對(duì)該數(shù)據(jù)進(jìn)行修改,當(dāng)別的對(duì)象訪問(wèn)該數(shù)據(jù)的時(shí)候,所訪問(wèn)到的值就是被修改后的。
比如如下代碼:

var person1 = new Person();
person1.frends.push("dd");
console.log(person1.frends);    //["gao", "li", "du", "dd"]
var person2 = new Person();
person2.frends.push("ee");
console.log(person2.frends);     //["gao", "li", "du", "dd", "ee"]

原本希望對(duì)person1和person2的friends屬性分別添加新的內(nèi)容,結(jié)果二者的friends屬性居然是“公用”的!

綜上,最常見(jiàn)的方式應(yīng)該是組合使用構(gòu)造函數(shù)和原型模式,構(gòu)造函數(shù)用于定義實(shí)例屬性,原型模式用于定義方法和共享的屬性。

每個(gè)類有三部分構(gòu)成:第一部分是構(gòu)造函數(shù)內(nèi),供實(shí)例對(duì)象化復(fù)制用。第二部分是構(gòu)造函數(shù)外,直接通過(guò)點(diǎn)語(yǔ)法添加,供類使用,實(shí)例化對(duì)象訪問(wèn)不到。第三部分是類的原型中,實(shí)例化對(duì)象可以通過(guò)其原型鏈間接訪問(wèn)到,也是為所有實(shí)例化對(duì)象所共用。

在說(shuō)到對(duì)象實(shí)例的屬性的時(shí)候,我們有一個(gè)問(wèn)題,就是在訪問(wèn)一個(gè)屬性的時(shí)候,這個(gè)屬性是屬于實(shí)例,還是屬于這個(gè)實(shí)例的原型的呢?

比如還是上面的例子,我們?yōu)閜erson2實(shí)例增加一個(gè)sex屬性,這時(shí)候訪問(wèn)person2的sex屬性時(shí),得到的是我們?cè)黾拥闹怠Uf(shuō)明為對(duì)象實(shí)例添加一個(gè)屬性的時(shí)候,這個(gè)屬性就會(huì)屏蔽原型對(duì)象中保存的同名屬性。

   person2.sex = "woman";
    console.log(person1.sex);                //man
    console.log(person2.sex);                //woman

這個(gè)時(shí)候我們可以使用hasOwnProperty()方法來(lái)檢測(cè)一個(gè)屬性是存在于實(shí)例中,還是存在于原型中。如果實(shí)例中有這個(gè)屬性,hasOwnProperty()會(huì)返回true,而hasOwnProperty()并不會(huì)感知到原型中的屬性。所以可以用這個(gè)方法檢測(cè)屬性到底是存在于實(shí)例中還是原型中。

console.log(person1.hasOwnProperty("sex"));        //原型中的屬性,返回false
console.log(person2.hasOwnProperty("sex"));        //實(shí)例中的屬性,返回true
二、繼承

ECMAScript中描述了原型鏈的概念,并將原型鏈作為實(shí)現(xiàn)繼承的主要方法。其基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。

2.1 原型鏈繼承

如下代碼:

function Super(){
    this.val = true;
    this.arr = ["a"];
}
function Sub(){
        //...
}
Sub.prototype = new Super();

var sub = new Sub();
console.log(sub.val)        //true

以上代碼定義了Super和Sub兩個(gè)類型,繼承的核心就一句話:Sub.prototype = new Super() 將父類的一個(gè)實(shí)例賦給子類的原型。這樣子類就能夠使用父類實(shí)例所擁有的方法和父類原型中的方法。

這種情況要想給子類添加自己的方法或者是覆蓋父類中某個(gè)方法的時(shí)候,一定要在放在替換原型語(yǔ)句后面。否則寫(xiě)在原型上的方法都會(huì)丟失。

而且在給子類添加新方法的時(shí)候,不能使用字面量的方式添加新方法,這樣會(huì)導(dǎo)致繼承無(wú)效。
如:

Sub.prototype = new Super();
Sub.prototype = {                        //錯(cuò)誤的方式
    getVal : function(){
        //...
    }
}

以上代碼剛剛把Super的實(shí)例賦給原型,緊接著又將原信替換成一個(gè)對(duì)象字面量,導(dǎo)致現(xiàn)在原型包含的是一個(gè)Object的實(shí)例,并非Super的實(shí)例,因此原型鏈被切斷了,Sub和Super已經(jīng)沒(méi)有關(guān)系了。

原型鏈的問(wèn)題:
最主要的問(wèn)題有兩個(gè):一是由于引用類型的原型屬性會(huì)被所有實(shí)例所共享,所以通過(guò)原型鏈繼承時(shí),原型變成了另一個(gè)類型的實(shí)例,原先的實(shí)例屬性也就變成了現(xiàn)在的原型屬性,如下代碼:

function Super(){
    this.friends = ["peng","gao"];
}
function Sub(){
        //...
}
Sub.prototype = new Super();
var sub1 = new Sub();
var sub2 = new Sub();
sub1.friends.push("du");
console.log(sub2.friends);            //["peng", "gao", "du"]

這個(gè)例子說(shuō)明的就是上面的問(wèn)題,子類的所有實(shí)例共享了父類中的引用類型屬性。

原型鏈繼承的另一個(gè)問(wèn)題是在創(chuàng)建子類行的實(shí)例的時(shí)候,沒(méi)法向父類的構(gòu)造函數(shù)傳遞參數(shù)。

2.2 構(gòu)造函數(shù)繼承

具體實(shí)現(xiàn):

function Super(){
    this.val = true;
    this.arr = ["a"];
}
function Sub(){
       Super.call(this);
}
var sub = new Sub();
console.log(sub.val)        //true

這種模式這是解決了原型鏈繼承中出現(xiàn)的兩個(gè)問(wèn)題,它可以傳遞參數(shù),也沒(méi)有了子類共享父類引用屬性的問(wèn)題。
但這種模式也有他的問(wèn)題,那就是在父類原型中定義的方法,其實(shí)是對(duì)子類不可見(jiàn)的。

2.3組合繼承

既然上述的兩種方式各有各自的局限性,將它倆整合到一起是不是會(huì)好一點(diǎn)呢,于是就有了組合繼承。

function Super(){
    this.val = true;
    this.arr = ["a"];
}
function Sub(){
       Super.call(this);                    //{2}
}
Sub.prototype = new Super();                //{1}
Sub.prototype.constructor = Sub;            //{3}
var sub = new Sub();
console.log(sub.val)        //true

組合繼承還有一個(gè)要注意的地方:
在代碼{3}處,將子類原型的constructor屬性指向子類的構(gòu)造函數(shù)。因?yàn)槿绻贿@么做,子類的原型是父類的一個(gè)實(shí)例,所以子類原型的constructor屬性就丟失了,他會(huì)順著原型鏈繼續(xù)往上找,于是就找到了父類的constructor所以它指向的其實(shí)是父類。

這種繼承方式是使用最多的一種方式。
這種繼承方式解決了上兩種方式的缺點(diǎn),不會(huì)出現(xiàn)共享引用類型的問(wèn)題,同時(shí)父類原型中的方法也被繼承了下來(lái)。

如果要說(shuō)起有什么缺點(diǎn)我們發(fā)現(xiàn),在執(zhí)行代碼{1}時(shí),Sub.prototype會(huì)得到父類型的val和arr兩個(gè)屬性。他們是Super的實(shí)例屬性,只不過(guò)現(xiàn)在在Sub的原型上。而代碼{2}處,在創(chuàng)建Sub實(shí)例的時(shí)候,調(diào)用Super的構(gòu)造函數(shù),又會(huì)在新的對(duì)象上創(chuàng)建屬性val和arr,于是,這兩個(gè)屬性就屏蔽了原型中兩個(gè)同名屬性。

2.4寄生組合式繼承

對(duì)于上面的問(wèn)題,我們也有解決辦法,不是在子類原型中多了一份父類的屬性和方法么,那我原型中就只要父類原型中的屬性和方法,這里我們引入了一個(gè)方法:

function inheritObject(obj){
    var F = function(){};
    F.prototype = obj;
    return new F();
}

這個(gè)方法創(chuàng)建了一個(gè)對(duì)象臨時(shí)性的構(gòu)造函數(shù),然后將傳入的對(duì)象作為這個(gè)構(gòu)造函數(shù)的原型,最后返回這個(gè)臨時(shí)類型的一個(gè)新實(shí)例。

我們可以設(shè)想,如果用這個(gè)方法拷貝一份父類的原型屬性給子類,是不是就避免了上面提到的子類原型中多了一份父類構(gòu)造函數(shù)內(nèi)的屬性??慈缦麓a:

function Super(){
    this.val = 1;
    this.arr = [1];
}
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};

function Sub(){
    Super.call(this);
}
var p = inheritObject(Super.prototype);         //{1}
p.constructor = Sub;                            //{2}
Sub.prototype = p;                              //{3}
 
var sub = new Sub();

基本思路就是:不必為了指定子類型的原型而調(diào)用父類的夠著函數(shù),我們需要的無(wú)非就是父類原型的一個(gè)副本而已。本質(zhì)上就是復(fù)制出父類的一個(gè)副本,然后再將結(jié)果指定給子類型的原型。

三、多態(tài)

所謂多態(tài),就是同一個(gè)方法的多種調(diào)用方式,在javascript中,通過(guò)arguments對(duì)象對(duì)傳入的參數(shù)做判斷就可以實(shí)現(xiàn)多種調(diào)用方式。

例子:

function Add(){
    function zero(){
        return 10;
    }
    function one(num){
        return 10 + num;
    }
function    two(num1, num2){
    return num1 + num2;
}
this.add = function(){
    var arg = arguments,
            len = arg.length;
    switch (len){
        case 0:
            return zero();
        case 1:
            return one(arg[0]);
        case 2:
            return two(arg[0], arg[1]);
        }
    }
}
var A = new Add();
console.log(A.add());                //10
console.log(A.add(5));              //15
console.log(A.add(6, 7));          //13

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/88433.html

相關(guān)文章

  • 回顧自己三次失敗面試經(jīng)歷

    摘要:站在這個(gè)時(shí)間點(diǎn)上,我對(duì)自己之前三次失敗的面試經(jīng)歷做了一次深度回顧。關(guān)于我第三次面試失敗的經(jīng)歷,依然是與輪播圖有關(guān)。當(dāng)然,這次思特奇面試之旅,最后也是以失敗告終,這也是我離進(jìn)大廠最近的一次。 showImg(https://segmentfault.com/img/bVYQuP?w=528&h=513); 前言 時(shí)間的齒輪已經(jīng)來(lái)到了2017年的11月份,距離2018年僅僅還剩下不到兩...

    DC_er 評(píng)論0 收藏0
  • 回顧自己三次失敗面試經(jīng)歷

    摘要:站在這個(gè)時(shí)間點(diǎn)上,我對(duì)自己之前三次失敗的面試經(jīng)歷做了一次深度回顧。關(guān)于我第三次面試失敗的經(jīng)歷,依然是與輪播圖有關(guān)。當(dāng)然,這次思特奇面試之旅,最后也是以失敗告終,這也是我離進(jìn)大廠最近的一次。 showImg(https://segmentfault.com/img/bVYQuP?w=528&h=513); 前言 時(shí)間的齒輪已經(jīng)來(lái)到了2017年的11月份,距離2018年僅僅還剩下不到兩...

    spacewander 評(píng)論0 收藏0
  • 前端思考 - 收藏集 - 掘金

    摘要:并嘗試用為什么你統(tǒng)計(jì)的方式是錯(cuò)的掘金翻譯自工程師的文章。正如你期望的,文中的前端開(kāi)發(fā)單一職責(zé)原則前端掘金單一職責(zé)原則又稱單一功能原則,面向?qū)ο笪鍌€(gè)基本原則之一。 單頁(yè)式應(yīng)用性能優(yōu)化 - 首屏數(shù)據(jù)漸進(jìn)式預(yù)加載 - 前端 - 掘金前言 針對(duì)首頁(yè)和部分頁(yè)面打開(kāi)速度慢的問(wèn)題,我們開(kāi)始對(duì)單頁(yè)式應(yīng)用性能進(jìn)行優(yōu)化。本文介紹其中一個(gè)方案:基于 HTTP Chunk 的首屏數(shù)據(jù)漸進(jìn)式預(yù)加載方案,該方案總...

    LinkedME2016 評(píng)論0 收藏0
  • 2018年騰訊前端二面總結(jié)(面向2019屆學(xué)生)

    摘要:前言很認(rèn)真的說(shuō)吧,在和騰訊面試官的面試的過(guò)程。騰訊二面自我介紹二面的面試官和一面不是同一個(gè)面試官,所以在這個(gè)時(shí)候,我的基本介紹還是和一面一樣,介紹自己的基本信息,以及怎么想到學(xué)習(xí)前端和怎么學(xué)習(xí)前端。 前言 很認(rèn)真的說(shuō)吧,在和騰訊面試官的面試的過(guò)程。有點(diǎn)感覺(jué)是在聊天一樣,他們是面試官,但是感覺(jué)更像是引路人,不管結(jié)果的好壞,在騰訊面試的過(guò)程,只要你認(rèn)真去聽(tīng)去問(wèn),就可以學(xué)到很多東西吧。 如果...

    gself 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<