this_原型鏈_繼承

this

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

  • call 和 apply 都是為了改變某個(gè)函數(shù)運(yùn)行時(shí)的上下(context)而存在的,換句話說,就是為了改變函數(shù)體內(nèi)部 this 的指向
    第一個(gè)參數(shù)都是希望設(shè)置的this對(duì)象,不同之處在于call方法接收參數(shù)列表,而apply接收參數(shù)數(shù)組
    func.call(this, arg1, arg2); func.apply(this, [arg1, arg2])

  • bind
    bind()方法會(huì)創(chuàng)建一個(gè)新函數(shù),稱為綁定函數(shù),當(dāng)調(diào)用這個(gè)綁定函數(shù)時(shí),綁定函數(shù)會(huì)以創(chuàng)建它時(shí)傳入 bind()方法的第一個(gè)參數(shù)作為 this,傳入 bind() 方法的第二個(gè)以及以后的參數(shù)加上綁定函數(shù)運(yùn)行時(shí)本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù)

var foo = {
    bar : 1,
    eventBind: function(){
        var _this = this;
        $('.someClass').on('click',function(event) {
            /* Act on the event */
            console.log(_this.bar);     //1
        });
    }
}

區(qū)別是:當(dāng)你希望改變上下文環(huán)境之后并非立即執(zhí)行,而是回調(diào)執(zhí)行的時(shí)候,使用 bind() 方法。而 apply/call 則會(huì)立即執(zhí)行函數(shù)。

總結(jié)一下:
apply 、 call 、bind 三者都是用來改變函數(shù)的this對(duì)象的指向的;
apply 、 call 、bind 三者第一個(gè)參數(shù)都是this要指向的對(duì)象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后續(xù)參數(shù)傳參;
bind 是返回對(duì)應(yīng)函數(shù),便于稍后調(diào)用;apply 、call 則是立即調(diào)用 。
參考

問題2: 以下代碼輸出什么?

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

問題3: 下面代碼輸出什么,為什么

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

問題4:下面代碼輸出什么

document.addEventListener('click', function(e){
    console.log(this);//document
    setTimeout(function(){
        console.log(this);//window:setTimeout里的this指向window
    }, 200);
}, false);

問題5:下面代碼輸出什么,為什么

var john = { 
  firstName: "John" 
}

function func() { 
  alert( this.firstName )
}
func.call(john)//John因?yàn)閒unc.call(john)的this就是第一個(gè)參數(shù)john

問題6: 以下代碼有什么問題,如何修改

var module= {
  bind: function(){
    $btn.on('click', function(){
      console.log(this) //this指$btn
      this.showMsg();
    })
  },
   
  showMsg: function(){
    console.log('hunger');
  }
}
問題
//在事件處理程序中this代表事件源DOM對(duì)象,所以該處的this指向$btn
//this.showMsg() 同理這里的this指向$btn,所以這里會(huì)出錯(cuò),因?yàn)?btn中沒有showMsg()方法應(yīng)該為如下
修改后:
var module= {
  bind: function(){
    var that = this;//引用this
    $btn.on('click', function(){
      console.log(that) 
      that.showMsg();//this為module
    })
  },
  showMsg: function(){
    console.log('hunger');
  }
}

原型鏈相關(guā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();

通過函數(shù)定義類Person,類自動(dòng)獲得屬性prototype,p是Person類的實(shí)例,有一個(gè)內(nèi)部屬性_proto_,
他指向類的prototype,p._proto_.constructor指向構(gòu)造函數(shù)Person。

8.上例中

1.對(duì)象 p可以這樣調(diào)用p.toString(),toString是哪里來

image.png

2.畫出原型圖

image.png

3.解釋原型鏈

首先來說說prototype屬性:不像每個(gè)對(duì)象都有proto屬性來標(biāo)識(shí)自己所繼承的原型,只有函數(shù)才有prototype屬性。
JS不像其它面向?qū)ο蟮恼Z言,它沒有類(class,ES6引進(jìn)了這個(gè)關(guān)鍵字)的概念。JS通過函數(shù)來模擬類。
當(dāng)你創(chuàng)建函數(shù)時(shí),JS會(huì)為這個(gè)函數(shù)自動(dòng)添加prototype屬性,值是空對(duì)象。而一旦你把這個(gè)函數(shù)當(dāng)作構(gòu)造函數(shù)(constructor)調(diào)用(即通過new關(guān)鍵字調(diào)用),那么JS就會(huì)幫你創(chuàng)建該構(gòu)造函數(shù)的實(shí)例,實(shí)例繼承構(gòu)造函數(shù)prototype的所有屬性和方法(實(shí)例通過設(shè)置自己的proto指向承構(gòu)造函數(shù)的prototype來實(shí)現(xiàn)這種繼承)。

JS正是通過proto和prototype的合作實(shí)現(xiàn)了原型鏈,以及對(duì)象的繼承。

構(gòu)造函數(shù),通過prototype來存儲(chǔ)要共享的屬性和方法,也可以設(shè)置prototype指向現(xiàn)存的對(duì)象來繼承該對(duì)象。

對(duì)象的proto指向自己構(gòu)造函數(shù)的prototype。obj.proto.proto...的原型鏈由此產(chǎn)生
two = new Object()中Object是構(gòu)造函數(shù),所以two.proto就是Object.prototype。ES規(guī)范定義對(duì)象字面量的原型就是Object.prototype。

當(dāng)訪問一個(gè)對(duì)象的某個(gè)屬性時(shí),會(huì)先在這個(gè)對(duì)象本身屬性上查找,如果沒有找到,則會(huì)去它的proto隱式原型上查找,即它的構(gòu)造函數(shù)的prototype,如果還沒有找到就會(huì)再在構(gòu)造函數(shù)的prototype的proto中查找,這樣一層一層向上查找就會(huì)形成一個(gè)鏈?zhǔn)浇Y(jié)構(gòu),我們稱為原型鏈。

我們知道JS是單繼承的,Object.prototype是原型鏈的頂端,所有對(duì)象從它繼承了包括toString等等方法和屬性。

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

法1:遍歷
String.prototype.getMostOften = function(){
            var arr = [];
            for(var i=0;i<this.length;i++){
                if(arr[this[i]]){
                    ++arr[this[i]];
                }else{
                    arr[this[i]] = 1;//必須在這里賦值為1
                }
            }

            var count = 0;
            var maxKey;
            for(var key in arr){
                if(arr[key]>count){
                    count = arr[key];//數(shù)字
                    maxKey = key;//a,b..
                }
            }
            var maxCount = count;
            return maxKey+':因?yàn)?+maxKey+'  出現(xiàn)了'+maxCount+'次';

        }
  var str = 'ahbbccdeddddfg';
  var ch = str.getMostOften();
  console.log(ch); //d , 因?yàn)閐 出現(xiàn)了5次
檢查元素__console.log
法2:正則
 String.prototype.getMostOften= function(str){
        return str.split('').sort().join('').match(/(\S)\1*/g).sort(function(a,b){
            return b.length - a.length;
        })[0][0];
};
    var str = 'ahbbccdeddddfg';
    var ch = str.getMostOften(str);
    var length = str.split('').sort().join('').match(/(\S)\1*/g).sort(function(a,b){
            return b.length - a.length;
        })[0].length;
    console.log(ch+':因?yàn)?+ch+'出現(xiàn)了'+length+'次'); //d , 因?yàn)閐 出現(xiàn)了5次

sort() 方法用于對(duì)數(shù)組的元素進(jìn)行排序,是按照字符編碼的順序進(jìn)行排序
\S  匹配任何非空白字符
\1 指定第一個(gè)子匹配項(xiàng)
*   匹配前面的子表達(dá)式零次或多次

console.log

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

  • instanceof用于判斷某個(gè)變量是否是某個(gè)對(duì)象的實(shí)例,返回值為true或false

  • instanceof
    通過探測(cè)obj.proto.proto... === Constructor.prototype來驗(yàn)證obj是否是Constructor的實(shí)例。
    :對(duì)象的proto屬性,一直往下查proto屬性是不是等于構(gòu)造函數(shù)的prototype屬性

繼承相關(guān)問題

問題11:繼承有什么作用?

  • 繼承是指一個(gè)對(duì)象直接使用另一對(duì)象的屬性和方法??梢蕴岣邚?fù)用性,省代碼
  • 作用:繼承劃分了類的層次性,父類代表的是更一般、更泛化的類,而子類則是更為具體、更為細(xì)化

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

//方法1
function People(name, sex){
    this.name = name;
    this.sex = sex;
    this.printName = function(){
        console.log(this.name);
    }
}
var p1 = new People('hunger', 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);
方法一
方法二
  • 方法一中:printName 方法直接寫在函數(shù)Person中,當(dāng)創(chuàng)建Person的實(shí)例時(shí),每個(gè)實(shí)例都有自己的printName 方法方法二中:printName 方法是寫在Person.prototype中,當(dāng)創(chuàng)建Person的實(shí)例時(shí),每個(gè)實(shí)例中沒有自己的PrintName方法,當(dāng)實(shí)例調(diào)用PrintName時(shí),無法在自己體內(nèi)找到,所以會(huì)通過proto去原型里面找,也就是Person.prototype當(dāng)中去找。所以第二種方法中,PrintName是所有實(shí)例公用的。
  • 作用
    第二種在原型里面找方法:不用自己再開辟內(nèi)存空間去創(chuàng)建一個(gè)方法

問題13: Object.create 有什么作用?兼容性如何?

  • 使用 Object.create 創(chuàng)建對(duì)象
    ECMAScript 5 中引入了一個(gè)新方法:Object.create()可以調(diào)用這個(gè)方法來創(chuàng)建一個(gè)新對(duì)象。新對(duì)象的原型就是調(diào)用 create
    方法時(shí)傳入的第一個(gè)參數(shù)
  • 兼容性
    這是ES5才有的方法對(duì)于低版本瀏覽器兼容效果不理想

問題14: hasOwnProperty有什么作用? 如何使用?

  • 檢測(cè)對(duì)象的屬性是定義在自身上還是在原型鏈上,有必要使用** [hasOwnProperty] **方法,所有繼承自 Object.proptotype 的對(duì)象都包含這個(gè)方法。會(huì)返回一個(gè)布爾值
    [hasOwnProperty]是 JavaScript 中唯一一個(gè)只涉及對(duì)象自身屬性而不會(huì)遍歷原型鏈的方法。
image.png

問題15:如下代碼中call的作用是什么?

function Person(name, sex){
    this.name = name;
    this.sex = sex;
}
function Male(name, sex, age){
    Person.call(this, name, sex);   
    //這里的 call作用:改變作用域,可以引用構(gòu)造函數(shù),使Male實(shí)例可以訪問PersonPerson的屬性
    this.age = age;
}

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

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

Male.prototype=Object.create(Person.prototype)
//or

// var Temp = function(){}
// Temp.prototype = Person.prototype;
// Male.prototype = new Temp();
// Male.prototype.construction = Male;

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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 1: apply、call 、bind有什么作用,什么區(qū)別 call 和 apply 都是為了改變某個(gè)函數(shù)運(yùn)行時(shí)的...
    高進(jìn)哥哥閱讀 352評(píng)論 0 0
  • 1:apply、call 、bind有什么作用,什么區(qū)別 call 和 apply 都是為了改變某個(gè)函數(shù)運(yùn)行時(shí)的上...
    進(jìn)擊的前端_風(fēng)笑影閱讀 312評(píng)論 0 0
  • 1. this2.原型鏈-instanceof實(shí)現(xiàn)3.繼承的實(shí)現(xiàn) ** this 相關(guān)問題 ** ** 1、 ap...
    饑人谷_阿靖閱讀 413評(píng)論 0 0
  • 1. apply、call 、bind有什么作用,什么區(qū)別? call ,apply的作用:調(diào)用一個(gè)函數(shù),傳入函數(shù)...
    Rising_suns閱讀 434評(píng)論 0 0
  • this 相關(guān)問題 apply、call 、bind有什么作用,什么區(qū)別? apply語法格式:function....
    小囧兔閱讀 339評(píng)論 0 0

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