this_原型鏈_繼承

由于運(yùn)行期綁定的特性,JavaScript 中的 this 含義非常多,它可以是全局對(duì)象、當(dāng)前對(duì)象或者任意對(duì)象,這完全取決于函數(shù)的調(diào)用方式。
隨著函數(shù)使用場(chǎng)合的不同,this的值會(huì)發(fā)生變化。但是有一個(gè)總的原則,<strong>那就是this指的是,調(diào)用函數(shù)的那個(gè)對(duì)象。</strong>

什么是this?

方老師講的很好,這邊我就不重復(fù)了
https://zhuanlan.zhihu.com/p/23804247?refer=study-fe

什么是apply,call?

語(yǔ)法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])

定義:參數(shù) thisObj 可選項(xiàng)。將被用作當(dāng)前對(duì)象的對(duì)象。 arg1, arg2, , argN 可選項(xiàng)。將被傳遞方法參數(shù)序列。

說(shuō)明 :
call 方法可以用來(lái)代替另一個(gè)對(duì)象調(diào)用一個(gè)方法。call 方法可將一個(gè)函數(shù)的對(duì)象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對(duì)象。
  如果沒(méi)有提供 thisObj 參數(shù),那么 Global 對(duì)象被用作thisObj。說(shuō)明白一點(diǎn)其實(shí)就是更改對(duì)象的內(nèi)部指針,即改變對(duì)象的this指向的內(nèi)容。這在面向?qū)ο蟮膉s編程過(guò)程中有時(shí)是很有用的。

語(yǔ)法:apply([thisObj[,argArray]])
定義:應(yīng)用某一對(duì)象的一個(gè)方法,用另一個(gè)對(duì)象替換當(dāng)前對(duì)象。
說(shuō)明:
  如果 argArray 不是一個(gè)有效的數(shù)組或者不是 arguments 對(duì)象,那么將導(dǎo)致一個(gè) TypeError。
  如果沒(méi)有提供 argArray 和 thisObj 任何一個(gè)參數(shù),那么 Global 對(duì)象將被用作 thisObj, 并且無(wú)法被傳遞任何參數(shù)。

下面是測(cè)試this熟悉程度的題目:

var john = { 
  firstName: "John" 
}
function func() { 
  alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi() //輸出John: hi! this是用john這個(gè)對(duì)象調(diào)用的,所以this===johN.firstName

func() 
function func() { 
  alert(this)  //直接調(diào)用函數(shù),obj為window對(duì)象
}
document.addEventListener('click', function(e){
    console.log(this); //document調(diào)用addEventListener方法,所以this的obj為document
    setTimeout(function(){
        console.log(this); //setTimeout內(nèi)調(diào)用匿名函數(shù),obj為window
    }, 200);
}, false);
var john = { 
  firstName: "John" 
}

function func() { 
  alert( this.firstName )
}
func.call(john) //將func中的this對(duì)象設(shè)置為john
var module= {
  bind: function(){
    $btn.on('click', function(){
      console.log(this) //this指向$btn的原生DOM
      this.showMsg();
    })
  },
  
  showMsg: function(){
    console.log('饑人谷');
  }
}
原型鏈相關(guān)問(wèn)題

1.有如下代碼,解釋Person、 prototype、proto、p、constructor之間的關(guān)聯(lián)。
Person是原型,P是Person的實(shí)例,Person的prototype定義了sayName 方法,P根據(jù)proto原型鏈查找sayName方法,Person的prototype方法上constructor指向了Person的地址

function Person(name){
    this.name = name;
}
Person.prototype.sayName = function(){
    console.log('My name is :' + this.name);
}
var p = new Person("若愚")
p.sayName();
  1. 上例中,對(duì)對(duì)象 p可以這樣調(diào)用 p.toString()。toString是哪里來(lái)的? 畫(huà)出原型圖?并解釋什么是原型鏈。
Paste_Image.png

通過(guò)原型鏈查到object原型,里面有toString()方法

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

<script>
String.prototype.getMostOften = function() {
     var obj = {},tmp = [0];
     for (var i = 0; i < this.length; i++) {
        if(obj[this[i]]){
            obj[this[i]]++
        }
        else if(!obj[this[i]]){
            obj[this[i]]=1;
        }
     }
    for(var key in obj){
        if(obj[key]>tmp[0]){
            tmp[0]=obj[key];
            tmp.key=key;
        }
    }
    return('出現(xiàn)最多的是:'+tmp.key+' num: '+tmp);
   };
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因?yàn)閐 出現(xiàn)了5次
</script>

4.instanceOf有什么作用??jī)?nèi)部邏輯是如何實(shí)現(xiàn)的?
判斷一個(gè)實(shí)例的原型是誰(shuí)

function instanceOf(obj,fn){
  var oldpro = obj.__proto__;
  while(oldpro){
    if(oldpro === fn.prototype){
        return true;
    }else{
        oldpro = oldpro.__proto__;
    }
  }
  return false;
}
繼承相關(guān)問(wèn)題:

1.什么是繼承?繼承有什么用?
概念:繼承是指一個(gè)對(duì)象直接使用另一個(gè)對(duì)象的屬性和方法。
作用:繼承劃分了類的層次性,父類代表的是更一般、更泛化的類,而子類則是更為具體、更為細(xì)化;
繼承是實(shí)現(xiàn)代碼重用、擴(kuò)展軟件功能的重要手段,子類中與父類完全相同的屬性和方法不必重寫(xiě),只需寫(xiě)出新增或改寫(xiě)的內(nèi)容,這就是說(shuō)子類可以復(fù)用父類的內(nèi)容,不必一切從零開(kāi)始。

2.下面兩種寫(xiě)法有什么區(qū)別?

//方法1,直接在原型中寫(xiě)入方法,在創(chuàng)建P1實(shí)例的時(shí)候相當(dāng)于又重新拷貝了一個(gè)printName方法
function People(name, sex){
    this.name = name;
    this.sex = sex;
    this.printName = function(){
        console.log(this.name);
    }
}
var p1 = new People('饑人谷', 2)

//方法2,通過(guò)原型鏈創(chuàng)建方法,創(chuàng)建P1實(shí)例的時(shí)候相當(dāng)于借用原型的printName方法
function Person(name, sex){
    this.name = name;
    this.sex = sex;
}

Person.prototype.printName = function(){
    console.log(this.name);
}
var p1 = new Person('若愚', 27);

3.Object.create 有什么作用?兼容性如何?
Object.create創(chuàng)建一個(gè)具有指定原型且可選擇性地包含指定屬性的對(duì)象??梢酝ㄟ^(guò)Object.create()方法實(shí)現(xiàn)類式繼承,如:

Male.prototype = Object.create(Person.prototype);

通過(guò)Object.create()clone了一個(gè)新的prototype,使Male.prototype指向這個(gè)新的prototype,而不是直接將Person.prototype賦值給它,這樣做可以避免當(dāng)我修改Male.prototype的時(shí)候不會(huì)將它的父類Person.prototype也修改了。

4.hasOwnProperty有什么作用? 如何使用?
hasOwnPerperty是Object.prototype的一個(gè)方法,可以判斷一個(gè)對(duì)象是否包含自定義屬性而不是原型鏈上的屬性,hasOwnProperty是JavaScript中唯一一個(gè)處理屬性但是不查找原型鏈的函數(shù)。

5.如下代碼中call的作用是什么?

function Person(name, sex){
    this.name = name;
    this.sex = sex;
}
function Male(name, sex, age){
    Person.call(this, name, sex);    //修改this指向的對(duì)象,借用Person的name和sex屬性
    this.age = age;
}

6.補(bǔ)全代碼,實(shí)現(xiàn)繼承

function Person(name, sex){
    this.name = name;
    this.sex = sex;
    this.printName=function(){
        console.log('Hello, '+name);
    }
}

Person.prototype.getName = function(){
    console.log('my name is ' + this.name)
};    

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

Male.prototype= Object.create(Person.prototype);

function inherit(superType, subType){   //添加constructor地址,指向Male
    var _prototype  = Object.create(superType.prototype);
    _prototype.constructor = subType;
    subType.prototype = _prototype;
}
inherit(Person, Male);

Male.prototype.getAge = function(){
    console.log('my age is ' + this.age)
};

var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
ruoyu.getName();
ruoyu.getAge();

這道題目能很好的去理解原型鏈,this,和繼承

Paste_Image.png
最后編輯于
?著作權(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)容