成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【前端面試】原型和原型鏈

lufficc / 2831人閱讀

摘要:該方法實(shí)際上就做了我們上面寄生組合繼承中的工作后面的參數(shù)是給原型對(duì)象添加屬性可選屬性非必填即把自身作為新創(chuàng)建對(duì)象的構(gòu)造函數(shù)。

1.題目

如何準(zhǔn)確判斷一個(gè)變量是數(shù)組

寫一個(gè)原型鏈繼承的例子

繼承實(shí)現(xiàn)的其他方式

es6 實(shí)現(xiàn)繼承的底層原理是什么

描述new一個(gè)對(duì)象的過程

zepto及其他源碼中如何使用原型鏈

2.知識(shí)點(diǎn) 2.1 構(gòu)造函數(shù)

特點(diǎn):以大寫字母開頭

function Foo(name,age){
    //var obj = {}
    //this = {}
    this.name = name;
    this.age = age;
    this.class = "class1"
    // return this
}

var f1 = new Foo("liming",19);

擴(kuò)展

var o = {} 是 var o = new Object() 的語法糖

var a = [] 是 var a = new Array() 的語法糖

function Foo(){} 相當(dāng)于 var Foo = new Function(){}

2.2 原型規(guī)則

五條規(guī)則:

1.所有引用類型(對(duì)象,數(shù)組,函數(shù))都具有對(duì)象特性,即可以自由擴(kuò)展屬性

2.所有引用類型(對(duì)象,數(shù)組,函數(shù))都具有一個(gè)__proto__(隱式原型)屬性,是一個(gè)普通對(duì)象

3.所有的函數(shù)都具有prototype(顯式原型)屬性,也是一個(gè)普通對(duì)象

4.所有引用類型(對(duì)象,數(shù)組,函數(shù))__proto__值指向它構(gòu)造函數(shù)的prototype

5.當(dāng)試圖得到一個(gè)對(duì)象的屬性時(shí),如果變量本身沒有這個(gè)屬性,則會(huì)去他的__proto__中去找

for (var key in object) {
    //高級(jí)瀏覽器中已經(jīng)屏蔽了來自原型的屬性
    //建議加上判斷保證程序的健壯性
    if (object.hasOwnProperty(key)) {
        console.log(object[key]);
    }
}
2.3 原型鏈

obj.__ proto . proto . proto __ ...

Object.prototype === null

instanceof 用于判斷引用類型屬于哪個(gè)構(gòu)造函數(shù)

obj instanceob Foo

實(shí)際意義:判斷 Foo.prototype 在不在 obj的原型鏈上

3.題目解答 3.1 如何準(zhǔn)確判斷一個(gè)變量是數(shù)組

arr instanceof Array

3.2 寫一個(gè)原型鏈繼承的例子

封裝dom查詢

function Elem(id){
    this.elem = document.getElementById(id);
};

Elem.prototype.html = function(val){
    var elem = this.elem;
    if (val) {
        elem.innerHTML = val;
        return this;
    }else{
        return elem.innerHTML;
    }
}

Elem.prototype.on = function(type,fun){
    var elem = this.elem;
    elem.addEventListener(type,fun);
    return this;
}

var div1 = new Elem("id1");
div1.html("test").on("click",function(){
    console.log("點(diǎn)擊");
})
3.3 繼承實(shí)現(xiàn)的其他方式 3.3.1 原型繼承
        var obj = {
            0:"a",
            1:"b",
            arr:[1]
        }
        
        function Foo(arr2){
            this.arr2 = [1]
        }

        Foo.prototype = obj;

        var foo1 = new Foo();
        var foo2 = new Foo();

        foo1.arr.push(2);
        foo1.arr2.push(2);

        console.log(foo2.arr);  //[1,2]
        console.log(foo2.arr2); //[1]

優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單

缺點(diǎn):

1.無法向父類構(gòu)造函數(shù)傳參

2.同時(shí)new兩個(gè)對(duì)象時(shí)改變一個(gè)對(duì)象的原型中的引用類型的屬性時(shí),另一個(gè)對(duì)象的該屬性也會(huì)修改。因?yàn)閬碜栽蛯?duì)象的引用屬性是所有實(shí)例共享的。

3.3.2 構(gòu)造繼承
        function Super(b){
            this.b = b;
            this.fun = function(){}
        }
        function Foo(a,b){
            this.a = a;
            Super.call(this,b);
        }

        var foo1 = new Foo(1,2);
        console.log(foo1.b);

優(yōu)點(diǎn):可以向父類傳參,子類不會(huì)共享父類的引用屬性

缺點(diǎn):無法實(shí)現(xiàn)函數(shù)復(fù)用,每個(gè)子類都有新的fun,太多了就會(huì)影響性能,不能繼承父類的原型對(duì)象。

3.3.3 組合繼承
function Super(){
    // 只在此處聲明基本屬性和引用屬性
    this.val = 1;
    this.arr = [1];
}
//  在此處聲明函數(shù)
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
    Super.call(this);   // 核心
    // ...
}
Sub.prototype = new Super();    

優(yōu)點(diǎn):不存在引用屬性共享問題,可傳參,函數(shù)可復(fù)用

缺點(diǎn):父類的屬性會(huì)被實(shí)例化兩次,獲取不到真正實(shí)例父類(無法區(qū)分實(shí)例是父類創(chuàng)建還是父類創(chuàng)建的)

優(yōu)化:

         function Super(b){
            this.b = b;
            this.fun = function(){}
        }

        Super.prototype.c = function(){console.log(1111)}

        function Foo(a,b){
            this.a = a;
            Super.call(this,b);
        }


        Foo.prototype = Super.prototype;
        //修復(fù)構(gòu)造函數(shù):
        var foo1 = new Foo(1,2);

缺點(diǎn):無法區(qū)分實(shí)例是父類創(chuàng)建還是子類創(chuàng)建的

3.3.4 寄生組合繼承
         function Super(b){
            this.b = b;
        }

        Super.prototype.c = function(){console.log(1111)}

        function Foo(a,b){
            this.a = a;
            Super.call(this,b);
        }

        var f = new Function();
        f.prototype = Super.prototype;
        Foo.prototype = new f();
        //等同于 Foo.prototype = Object.create(Super.prototype);
        
        var foo1 = new Foo(1,2);

對(duì)父類的prototype進(jìn)行一次寄生,即包裝成一個(gè)空對(duì)象的prototype,再把這個(gè)對(duì)象實(shí)例化出來作為子類的peototype。

缺點(diǎn):無法區(qū)分實(shí)例是父類創(chuàng)建還是子類創(chuàng)建的

可以添加以下代碼:

Foo.prototype.constructor = Foo

這種解決方法不能用于上面的組合優(yōu)化方法,因?yàn)樽宇惛割愐玫氖峭粋€(gè)原型對(duì)象,修改會(huì)同時(shí)修改。

總結(jié):

繼承主要是實(shí)現(xiàn)子類對(duì)父類方法,屬性的復(fù)用。

來自原型對(duì)象的引用屬性是所有實(shí)例共享的,所以我們要避免從原型中繼承屬性。

在構(gòu)造函數(shù)中通過call函數(shù)可以繼承父類構(gòu)造函數(shù)的屬性和方法,但是通過這種方式實(shí)例化出來的實(shí)例會(huì)將父類方法多次存儲(chǔ),影響性能。

通過組合繼承我們使用call繼承屬性,使用原型繼承方法,可以解決以上兩個(gè)問題,但是通過這種方式實(shí)例化出來的對(duì)象會(huì)存儲(chǔ)兩份父類構(gòu)造函數(shù)中的屬性。

用父類的原型構(gòu)造一個(gè)新對(duì)象作為子類的原型,就解決了多次存儲(chǔ)的問題,所以最終的寄生組合繼承就是最佳繼承方式,它的缺點(diǎn)就是書寫起來比較麻煩。

3.3.6 node源碼中的繼承實(shí)現(xiàn)
function inherits(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
}; 

function Stream(){
    //...
}

function OutgoingMessage() {
  Stream.call(this);
  //...
}

inherits(OutgoingMessage, Stream);

OutgoingMessage.prototype.setTimeout = ...

以上是寄生組合繼承的一個(gè)實(shí)例。

1.在OutgoingMessage構(gòu)造函數(shù)中通過call繼承Stream構(gòu)造中的屬性。

2.調(diào)用inherits方法繼承Stream原型中的屬性。

3.擴(kuò)展OutgoingMessage自身原型的函數(shù)。

inherits方法中使用了Object.create方法,該方法的作用是通過指定的原型對(duì)象和屬性創(chuàng)建一個(gè)新的對(duì)象。

ctor.prototype=Object.create(superCtor.prototype,{.....});

該方法實(shí)際上就做了我們上面寄生組合繼承中的工作

var f = new Function();
f.prototype =superCtor.prototype;
return new f();

后面的參數(shù)是給原型對(duì)象添加屬性,可選屬性(非必填),即把自身作為新創(chuàng)建對(duì)象的構(gòu)造函數(shù)。

value: 表示constructor 的屬性值;
writable: 表示constructor 的屬性值是否可寫;[默認(rèn)為: false]
enumerable: 表示屬性constructor 是否可以被枚舉;[默認(rèn)為: false]
configurable: 表示屬性constructor 是否可以被配置,例如 對(duì)obj.a做 delete操作是否允許;[默認(rèn)為: false]
3.4 es6繼承的實(shí)現(xiàn)方式

參考我這篇文章:https://segmentfault.com/a/11...

3.5 描述new一個(gè)對(duì)象的過程

創(chuàng)建一個(gè)對(duì)象

{}._proto_ = 構(gòu)造函數(shù).prototype

this指向這個(gè)對(duì)象

執(zhí)行代碼即對(duì)this賦值

返回this

3.6 zepto及其他源碼中如何使用原型鏈
var Zepto = (function(){

    var $,zepto = {}
    
    // ...省略N行代碼...
    
    $ = function(selector, context){
        return zepto.init(selector, context)
    }

    zepto.init = function(selector, context) {
        var dom
        
        // 針對(duì)參數(shù)情況,分別對(duì)dom賦值
        
        // 最終調(diào)用 zepto.Z 返回的數(shù)據(jù)
        return zepto.Z(dom, selector)
    }    

   fnction Z(dom, selector) {
      var i, len = dom ? dom.length : 0
     for (i = 0; i < len; i++) this[i] = dom[i]
      this.length = len
      this.selector = selector || ""
    }

   zepto.Z = function(dom, selector) {
     return new Z(dom, selector)
   }
  
    $.fn = {
        // 里面有若干個(gè)工具函數(shù)
    }
      
  
    zepto.Z.prototype = Z.prototype = $.fn
  
    
    // ...省略N行代碼...
    
    return $
})()

window.Zepto = Zepto
window.$ === undefined && (window.$ = Zepto)

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100858.html

相關(guān)文章

  • 關(guān)于個(gè)人第一天前端面試面試問答QA,希望能對(duì)其他找前端工作的朋友有所幫助。

    摘要:兩日前,發(fā)了一篇吐槽,莫名的火了一把。關(guān)于的第一個(gè),其實(shí)就是聲明一個(gè)常量,不允許變更。另外對(duì)象迭代這里出自,阮一峰大神寫的入門指南,對(duì)象篇。 兩日前,發(fā)了一篇吐槽,莫名的火了一把。經(jīng)過大家的建議與鼓勵(lì),于是修改了簡(jiǎn)歷,開始了重新投遞,2天后接到第一份面試邀請(qǐng)。 此文為個(gè)人面試經(jīng)歷,QA問答過程與總結(jié),不透露面試公司及面試人員,內(nèi)容真實(shí),如果有面試過我的大佬看到博客,歡迎指出問題。 循序...

    Youngdze 評(píng)論0 收藏0
  • 前端面試回顧(1)---javascript的面向?qū)ο?/b>

    摘要:每個(gè)類有三部分構(gòu)成第一部分是構(gòu)造函數(shù)內(nèi),供實(shí)例對(duì)象化復(fù)制用。第二部分是構(gòu)造函數(shù)外,直接通過點(diǎn)語法添加,供類使用,實(shí)例化對(duì)象訪問不到。組合繼承還有一個(gè)要注意的地方在代碼處,將子類原型的屬性指向子類的構(gòu)造函數(shù)。 前言 前一陣面試,過程中發(fā)現(xiàn)問到一些很基礎(chǔ)的問題時(shí)候,自己并不能很流暢的回答出來?;蛘哂龅揭恍┗A(chǔ)知識(shí)的應(yīng)用,由于對(duì)這些點(diǎn)理解的不是很深入,拿著筆居然什么都寫不出來,于是有了回顧一...

    animabear 評(píng)論0 收藏0
  • 前端面試題 -- JavaScript (一)

    摘要:前言前兩天總結(jié)了一下方面的面試題傳送門,今天翻看了一些面試中常見的幾個(gè)問題只是一部分,會(huì)持續(xù)更新,分享給有需要的小伙伴,歡迎關(guān)注如果文章中有出現(xiàn)紕漏錯(cuò)誤之處,還請(qǐng)看到的小伙伴留言指正,先行謝過以下有哪些數(shù)據(jù)類型種原始數(shù)據(jù)類型布爾表示一個(gè)邏輯 前言 前兩天總結(jié)了一下HTML+CSS方面的面試題 (傳送門),今天翻看了一些 JavaScript 面試中常見的幾個(gè)問題(只是一部分,會(huì)持續(xù)更新...

    junnplus 評(píng)論0 收藏0
  • 近期前端面試中經(jīng)常碰到的問題總結(jié)

    摘要:手寫深拷貝這個(gè)問題也是被問到了不止一遍,就連美團(tuán)也問到了。個(gè)人能力有限,沒能挺到美團(tuán)的最后一輪面試,不過面試的幾家公司也是涉及到了各行各業(yè),這篇文章只是對(duì)即將面試的前端小伙伴們一個(gè)參考,最后效果還是要看個(gè)人努力的。 最近想著去市場(chǎng)中試試水,看看自己的幾斤幾兩。哈哈,然后大概遇到了這么幾類問題吧。寫出來和大家分享一下。 原生類 1.原型及原型鏈的問題 這個(gè)問題面試的公司都有問。其實(shí)這...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<