高級(jí)2 - this_原型鏈_繼承

this相關(guān)問(wèn)題

問(wèn)題1:apply、call有什么作用,什么區(qū)別

  • apply()call()函數(shù)都可以 指定this值和參數(shù)值的情況下調(diào)用某個(gè)函數(shù)。
  • call()apply()的作用一樣,區(qū)別在于提供給原函數(shù)的參數(shù)的方式不一樣
    • apply()函數(shù)只接受兩個(gè)參數(shù),提供給原函數(shù)的參數(shù)以數(shù)組或類(lèi)數(shù)組對(duì)象的形式存在
    • call()接收無(wú)限個(gè)參數(shù), 第二個(gè)參數(shù)及其后面的參數(shù)就是提供給原函數(shù)的參數(shù)。

問(wèn)題2:以下代碼輸出什么

var john = { 
  firstName: "John" 
}
function func() { 
  alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()     //  彈出John:hi!

問(wèn)題3: 下面代碼輸出什么,為什么

func()   //  彈出window對(duì)象

function func() { 
  alert(this)
}
  • 因?yàn)樵诤瘮?shù)func()被直接調(diào)用時(shí),this綁定到全局對(duì)象。在瀏覽器中,window 就是該全局對(duì)象

問(wèn)題4:下面代碼輸出什么

function fn0(){
    function fn(){
        console.log(this);
    }
    fn();
}

fn0();  //  輸出window對(duì)象


document.addEventListener('click', function(e){
    console.log(this);   //  輸出document對(duì)象
    setTimeout(function(){
        console.log(this);   //  輸出window對(duì)象
    }, 200);
}, false);

問(wèn)題5:下面代碼輸出什么,why

var john = { 
  firstName: "John" 
}

function func() { 
  alert( this.firstName ) 
}
func.call(john)    //  彈出John
  • func()函數(shù)通過(guò)call()函數(shù)調(diào)用,此時(shí)this為John對(duì)象,john.firstName存在,輸出"John"

問(wèn)題6: 以下代碼有什么問(wèn)題,如何修改

var module= {
  bind: function(){
    $btn.on('click', function(){
      console.log(this) // 這里的this指的是$btn
      this.showMsg();  //  $btn沒(méi)有showMsg的屬性,如果調(diào)用,這里會(huì)報(bào)錯(cuò)
    })
  },
  
  showMsg: function(){
    console.log('饑人谷');
  }
}
  • 應(yīng)該改成如下:
var module= {
  bind: function(){
    var self = this;  // 先在外部將this保存成變量,再在內(nèi)部調(diào)用這個(gè)變量
    $btn.on('click', function(){
      console.log(this);
      self.showMsg(); 
    })
  },

  showMsg: function(){
    console.log('饑人谷');
  }
}

這樣,再進(jìn)行測(cè)試,發(fā)現(xiàn)成功輸出饑人谷

修改之后測(cè)試.png

原型鏈相關(guān)問(wèn)題

問(wèn)題7:有如下代碼,解釋Person、 prototype、__proto__、p、constructor之間的關(guān)聯(lián)。

function Person(name){
    this.name = name;
}
Person.prototype.sayName = function(){
    console.log('My name is :' + this.name);
}
var p = new Person("若愚")
p.sayName();
  • People是一個(gè)構(gòu)建函數(shù),protoTypePeople的屬性(原型),即可以通過(guò)People.protoType的方式來(lái)獲取這個(gè)屬性,其類(lèi)型是一個(gè)對(duì)象。
  • pPeople構(gòu)建的實(shí)例,它有一個(gè)屬性__proto__,它的值引用了p的父類(lèi)PeopleprotoType屬性。
  • constructorprotoType的一個(gè)屬性,其值指向函數(shù)本身,例如:People.protoType.constructor就是People本身。

問(wèn)題8: 上例中,對(duì)對(duì)象 p可以這樣調(diào)用 p.toString()。toString是哪里來(lái)的? 畫(huà)出原型圖?并解釋什么是原型鏈。

question8.png
  • toString()實(shí)際上是Object的方法
    • 如上原型圖所示:對(duì)對(duì)象p調(diào)用p.toString()時(shí),JS先從其自身的方法中找toString()方法,沒(méi)有找到;
    • 然后通過(guò)__proto__屬性找其父元素PeopleprotoType屬性中有沒(méi)有toString()方法,依然沒(méi)找到;
    • 然后再通過(guò)其父元素PeopleprotoType屬性中的__proto__屬性即Object.protoType繼續(xù)尋找,在Object.protoType找到了toString()方法。
  • 每個(gè)對(duì)象都有一個(gè)隱藏的__proto__屬性,這個(gè)屬性就是對(duì)其父元素原型對(duì)象(protoType)的引用。
  • 由于原型對(duì)象本身也是對(duì)象,也有__proto__屬性,它的__proto__屬性又指向了其更高父元素原型對(duì)象。這樣就形成了一條鏈,這就是原型鏈

問(wèn)題9:對(duì)String做擴(kuò)展,實(shí)現(xiàn)如下方式獲取字符串中頻率最高的字符

// 答案
String.prototype.getMostOften = function(){
    var box = {},
        max = 0,
        maxKey = "";
    for (var i=0, word;i<this.length;i++) {
        word = this[i];
        if (box[word] === undefined) {
            box[word] = 1;
        } else {
            box[word] += 1;
        }
    }
    for (key in box) {
        if (box[key] > max) {
            max = box[key];
            maxKey = key;
        }
    }
    return maxKey
}



// 題目
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因?yàn)閐 出現(xiàn)了5次

問(wèn)題10: instanceOf有什么作用??jī)?nèi)部邏輯是如何實(shí)現(xiàn)的?

  • instanceof用來(lái)檢查一個(gè)對(duì)象是不是另一個(gè)構(gòu)造對(duì)象的實(shí)例。
  • 其內(nèi)部邏輯是測(cè)試一個(gè)對(duì)象在其原型鏈中是否存在一個(gè)構(gòu)造函數(shù)的 prototype 屬性。
  • 所以如果表達(dá)式obj instanceof Foo 返回true,則并不意味著該表達(dá)式會(huì)永遠(yuǎn)返回true,因?yàn)?code>Foo.prototype屬性的值有可能會(huì)改變,改變之后的值很有可能不存在于obj的原型鏈上,這時(shí)原表達(dá)式的值就會(huì)成為false

繼承相關(guān)問(wèn)題

問(wèn)題11:繼承有什么作用?

  • 繼承的主要作用有兩個(gè)
    • 繼承可以使子類(lèi)共享父類(lèi)的屬性和方法
    • 繼承可以覆蓋和擴(kuò)展父類(lèi)的屬性和方法

問(wèn)題12: 下面兩種寫(xiě)法有什么區(qū)別?

//方法1
function People(name, sex){
    this.name = name;
    this.sex = sex;
    this.printName = function(){
        console.log(this.name);
    }
}
var p1 = new People('饑人谷', 2)

//方法2
function Person(name, sex){
    this.name = name;
    this.sex = sex;
}

Person.prototype.printName = function(){
    console.log(this.name);
}
var p1 = new Person('若愚', 27);
  • 第一種方法將會(huì)把printName這個(gè)方法重新定義在每個(gè)構(gòu)建的對(duì)象上,這樣如果構(gòu)建的對(duì)象比較多,也將會(huì)有許多個(gè)printName函數(shù),將會(huì)對(duì)性能產(chǎn)生影響
  • 第二種方法會(huì)把printName這個(gè)方法定義到構(gòu)建函數(shù)的protoType上,這樣新構(gòu)建的函數(shù)將會(huì)通過(guò)原型鏈獲取到這個(gè)方法,節(jié)約了內(nèi)存
  • 推薦使用第二種方法

問(wèn)題13: Object.create 有什么作用?兼容性如何?

  • Object.create方法可以創(chuàng)建一個(gè)擁有指定原型和若干個(gè)指定屬性的對(duì)象。
  • 在繼承中,Object.create可以用于繼承屬性。
  • Object.create是在ES5中規(guī)定的,其兼容性見(jiàn)下圖:
Object.create-compatibilty.png

問(wèn)題14: hasOwnProperty有什么作用? 如何使用?

  • hasOwnProperty方法會(huì)返回一個(gè)布爾值,其用來(lái)判斷某個(gè)對(duì)象是否含有特定的自身屬性,該方法會(huì)忽略掉那些從原型鏈上繼承到的屬性。
  • 語(yǔ)法為obj.hasOwnProperty(prop),參數(shù)prop為要檢測(cè)的屬性

問(wèn)題15:如下代碼中call的作用是什么?

function Person(name, sex){
    this.name = name;
    this.sex = sex;
}
function Male(name, sex, age){
    Person.call(this, name, sex);    //這里的 call 有什么作用
    this.age = age;
}
  • 這里的call的作用是改變構(gòu)造函數(shù)People的作用域,這樣就可以讓PeopleMale的作用域中執(zhí)行,這樣People中的一些屬性賦值語(yǔ)句也會(huì)在Male中執(zhí)行。
  • 通過(guò)這種方式就實(shí)現(xiàn)了屬性的繼承。

問(wèn)題16: 補(bǔ)全代碼,實(shí)現(xiàn)繼承

function Person(name, sex){
    this.name = name;
    this.sex = sex;
}

Person.prototype.getName = function(){
    console.log(this.name);
};    

function Male(name, sex, age){
   Person.call(this, name, sex);
   this.age = age;
}

var _prototype = Object.create(Person.prototype);
_prototype.consturctor = Male;
Male.prototype = _prototype;

Male.prototype.getAge = function(){
    console.log(this.age);
};

var ruoyu = new Male('若愚', '男', 27);
ruoyu.getName();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容