this_原型鏈_繼承

問題1: apply剖淀、call 肿男、bind有什么作用介汹,什么區(qū)別

apply和call就是為了改變函數(shù)內(nèi)部this的指向;

如果使用apply或call方法舶沛,那么this指向他們的第一個(gè)參數(shù)嘹承,apply的第二個(gè)參數(shù)是一個(gè)參數(shù)數(shù)組,call的第二個(gè)及其以后的參數(shù)都是數(shù)組里面的元素冠王,就是說要全部列舉出來赶撰;bind與apply、call最大的區(qū)別就是:bind不會(huì)立即調(diào)用,其他兩個(gè)會(huì)立即調(diào)用
舉例:

var info = 'tom';
function foo(){   
  //this指向window 
  var info = 'jerry';
  console.log(this.info);   //tom
  console.log(this===window)  //true
}
foo(); 
var obj = {
      info:'spike'
}
foo.call(obj);    //這里foo函數(shù)里面的this就指向了obj
foo.apply(obj);//輸出
var arr = [123,34,5,23,3434,23];
//方法一
var arr1 = arr.sort(function(a,b){
  return b-a;
});
console.log(arr1[0]);
//方法二
var max = Math.max.apply(null,arr)   //借用別的對(duì)象的方法
console.log(max);
2.獲取數(shù)組中的最大值和最小值,利用他們擴(kuò)充作用域擁有Math的min和max方法凭舶;
由于沒有什么對(duì)象調(diào)用這個(gè)方法,所以第一個(gè)參數(shù)可以寫作null或者本身瘤载;
var  numbers = [5, 458 , 120 , -215 ]; 
var  maxInNumbers = Math.max.apply(Math, numbers),   //458
       maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); 
驗(yàn)證是否是數(shù)組(前提是toString()方法沒有被重寫過)
function   isArray(obj){ 
    return Object.prototype.toString.call(obj) === '[object Array]' ;
}

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

func() 
function func() { 
  alert(this)
}
輸出為window對(duì)象卖擅。由于func是在全局作用域下被調(diào)用

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

document.addEventListener('click', function(e){
    console.log(this);//document鸣奔,是DOM對(duì)象本身,
    setTimeout(function(){
        console.log(this);//window惩阶,這是由于setTimeout函數(shù)是掛在window
對(duì)象下的
    }, 200);
}, false);

問題5:下面代碼輸出什么挎狸,why

var john = { 
  firstName: "John" 
}

function func() { 
  alert( this.firstName )
}
func();//輸出undefined,因?yàn)槿窒略L問不到firstname

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

var module= {
  bind: function(){
    $btn.on('click', function(){
      console.log(this) //this指的是btn
      this.showMsg();
    })
  },
  
  showMsg: function(){
    console.log('饑人谷');
  }
}
bind屬性中断楷,this.showMsg()語句的this指的是$btn锨匆,是無法調(diào)用showMsg()的,
此時(shí)需要保存事件綁定函數(shù)外部的this冬筒,修改如下
var module= { 
 bind: function(){ 
     var cur = this//這里的this指的是module,先把它保存起來以后用
     $btn.on('click', function(){ 
         console.log(this) //this指的是btn
         cur.showMsg(); 這里就可以名正言順調(diào)用自己的方法了相當(dāng)于module.showMsg
     }) 
 },
 showMsg: function(){ 
     console.log('饑人谷'); 
 }
}

補(bǔ)充類似題目

1

var o = {
foo:'bar',
func: function(){
  console.log(this)
}
}
var a = o.func;
a();//打印出來的this變成了全局對(duì)象window恐锣,不再是o
在瀏覽器中輸入a,返回的是一個(gè)函數(shù)舞痰,當(dāng)再次調(diào)用a土榴,就是相當(dāng)于在全局作用域下調(diào)用函數(shù)

2
Paste_Image.png

先打印的是person的name2,然后是全局name1
假如最后添加兩行代碼响牛,var a=person.say; a()
意思是先把函數(shù)賦給a玷禽,則a就是一個(gè)函數(shù)了赫段,在調(diào)用a相當(dāng)于在全局下調(diào)用

 var myobject={
        foo:"bar",
        func:function () {
            var self=this;
            console.log(this.foo);//bar無疑問
            (function() {
                console.log(this)//window,立即執(zhí)行函數(shù)有自己的作用域
                console.log(this.foo)//理所當(dāng)然undefined
                console.log(self.foo);//還為bar
            })();

        }
    }
    myobject.func();
   假如變形把最后一行改為var f=myobject.func;
                    f()矢赁,則this指的就是window瑞佩,根本拿不到foo的值,全是undefined

var name='name1';
    function say() {
        console.log(name);
    }

    var person={
        name:'name2',
        say:say
    }
    person.say();
    say();//注意與上題的不同坯台,這里的打印出來的name都是全局name!!!!!
var user='jrg';
var box={
    user:'hh',
    getuser:function () {
       var self=this;
        return function () {
            return self.user
        }
    }
}
console.log(box.getuser()())
非常具有迷惑性一個(gè)題目,首先把box.getuser打印出來就一目了然了瘫寝,是打印hh,因?yàn)橛衯ar self=this;所以無論怎么變形都是打印hh,box.getuser().call(box)這個(gè)也是打印相同結(jié)果
function func1() {
     var n=99;
     nadd=function () {
         console.log(this)
         this.n+=1;
         console.log(this.n)
     }
     function func2() {
         console.log(n)
     }
     return func2;
 }
 var result=func1();
    result();
    nadd();NAN,這個(gè)函數(shù)能訪問到有點(diǎn)不懂
    result();

var obj={
    name:'obj',
    close:function () {
        this.name="close";
        return function () {
            return this.name;
        }
    }
}
console.log(obj.close().call(obj))不call的話輸出為空蜒蕾,加了輸出為close,obj的name已經(jīng)改變

原型鏈相關(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();
  • Person是構(gòu)造函數(shù)褒纲,也是一個(gè)對(duì)象准夷,這個(gè)對(duì)象里面存在一個(gè)prototype屬性,而構(gòu)造函數(shù)內(nèi)部定義了實(shí)例的屬性和方法莺掠,這些屬性和方法是屬于該類的所有實(shí)例的特征衫嵌;
  • p是通過構(gòu)造函數(shù)Person構(gòu)造出來的實(shí)例,也是擁有proto屬性彻秆。所以p.proto === Person.prototype;
  • prototype是構(gòu)造函數(shù)內(nèi)部的原型對(duì)象楔绞,所以擁有contructor和proto屬性,其中contructor屬性指向構(gòu)造函數(shù)Person唇兑,proto指向該對(duì)象的原型酒朵,即
Person.prototype.__proto__ === Object.prototype;
Person.prototype.constructor == Person

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

  • p.toString()方法是繼承構(gòu)造函數(shù)Object的原型對(duì)象里定義的toString方法,首先p會(huì)找自己的toString方法帕棉,如果沒有找到针肥,會(huì)沿著proto屬性繼續(xù)到構(gòu)造函數(shù)Person的prototype里找toString方法,如果還未找到香伴,再繼續(xù)往Person.prototype的proto即Object.prototype找toString方法慰枕,最后找到toString()方法。
  • 原型鏈:由于原型對(duì)象本身也是對(duì)象即纲,而每個(gè)javascript對(duì)象都有一個(gè)原型對(duì)象具帮,每個(gè)對(duì)象都有一個(gè)隱藏的proto屬性,原型對(duì)象也有自己的原型,而它自己的原型對(duì)象又可以有自己的原型蜂厅,這樣就組成了一條鏈匪凡,這個(gè)就是原型鏈。在訪問對(duì)象的屬性時(shí)掘猿,如果在對(duì)象本身中沒有找到病游,則會(huì)去原型鏈中查找,如果找到稠通,直接返回值衬衬,如果整個(gè)鏈都遍歷且沒有找到屬性,則返回undefined改橘。原型鏈一般實(shí)現(xiàn)為一個(gè)鏈表滋尉,這樣就可以按照一定的順序來查找。
Paste_Image.png

補(bǔ)充:

var a={n:4399}
var b=function () {
    this.n=9999
}
var c=function () {
    var n=8888
}
b.prototype=a;
c.prototype=a;
var d=new b();
    var e=new c()
    a.n++;
    console.log(d.n)9999自己的
    console.log(e.n)4400a的
這個(gè)實(shí)在理解不了飞主。狮惜。。
 var F=function () {
     
 }
 Object.prototype.a=function () {
     
 }
 Function.prototype.b=function () {
     
 }
 var f=new F();
F能拿到b碌识,f拿不到因?yàn)樗约菏菍?duì)象

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

String.prototype.getMostOften = function() {
     var obj = {};
     for (var i = 0; i < this.length; i++) {
       if(!obj[this[i]]) {
         obj[this.charAt(i)] = 1;
       }else if(obj[this[i]]) {
         obj[this.charAt(i)]++;
       }
     }
     console.log(obj);
     var val = '';
     var num = 0;
     for(var key in obj) {
       if (obj[key] > num) {
         num = obj[key];
         val = key
       }
     }

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

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

簡單來記就是如果實(shí)例的_proto不等于構(gòu)造函數(shù)的prototype就去實(shí)例的
_proto_._proto_去找
function instanceOf(obj,Func){
    var __proto__=obj.__proto__;
    do{
      if(__proto__===Func.prototype) {
        return true;
      } 
      if(!__proto__) return false;
    }
    while(__proto__=__proto__.__proto__);
    return false;
  }

繼承相關(guān)問題

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

JavaScript 對(duì)象有一個(gè)指向一個(gè)原型對(duì)象的鏈耽梅。當(dāng)試圖訪問一個(gè)對(duì)象的屬性時(shí),它不僅僅在該對(duì)象上搜尋胖烛,還會(huì)搜尋該對(duì)象的原型眼姐,以及該對(duì)象的原型的原型,依此層層向上搜索佩番,直到找到一個(gè)名字匹配的屬性或到達(dá)原型鏈的末尾众旗。這就意味著,JS對(duì)象可以使用所有其原型的所有方法趟畏,如果我們?cè)谠蜕咸砑有碌姆椒ü逼纾敲磳?shí)例也會(huì)擁有該方法,能夠大大減少冗余代碼

問題12: 下面兩種寫法有什么區(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);

區(qū)別:同樣都是創(chuàng)建printName方法赋秀,方法1的printName方法是在函數(shù)Person實(shí)例對(duì)象里的利朵,方法2是在Person的prototype對(duì)象上的。當(dāng)再創(chuàng)建一個(gè)Person實(shí)例對(duì)象的時(shí)候猎莲,方法1又將會(huì)再創(chuàng)建一個(gè)printName方法绍弟,占用新的內(nèi)存,而方法2將一個(gè)公用的printName方法寫在原型上著洼,當(dāng)對(duì)象要使用該方法只需到原型鏈里調(diào)用就可以了樟遣,達(dá)到節(jié)省內(nèi)存的效果

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

  • 作用:創(chuàng)建一個(gè)擁有指定原型和若干個(gè)指定屬性的對(duì)象豹悬。
  • 兼容性:

-使用:

function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function(){
console.log(this.name);
}
function Male(name, age, sex){
Person.call(this, name, age);
this.sex = sex;
}
// Male.prototype = new Person(); //該方法同下葵陵,代替不兼容Object.create()的使用場(chǎng)景
Male.prototype = Object.create(Person.prototype);
Male.prototype.constructor = Male;
Male.prototype.sayAge = function(){
  console.log(this.age);
};
var p1 = new Male('hunger', 20, 'nan');
p1.sayName();//hunger
p1.sayAge();//20

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

function Person(name,age) {
    this.name = name;
    this.age = age;
  }
  Person.prototype.printName = function() {
    console.log(this.name);
  }
  function people(name) {
    this.name = name;
  }
  people.prototype = Object.create(Person.prototype);
  var p = new people('John');
  console.log(p.hasOwnProperty('printName'));//false也就是說必須是自己的脱篙,
從原型繼承過來的不算

問題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;
}
Male中的call,指定了其執(zhí)行環(huán)境在Person下伤柄。換句話說涡尘,實(shí)現(xiàn)了從People的繼承

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

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

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

  Male.prototype = Object.create(Person.prototype);
  Male.prototype.constructor = Male;
  Male.prototype.getAge = function(){
      return this.age;
  };

  var ruoyu = new Male('若愚', '男', 27);
  ruoyu.printName();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末响迂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子细疚,更是在濱河造成了極大的恐慌蔗彤,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疯兼,死亡現(xiàn)場(chǎng)離奇詭異然遏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吧彪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門待侵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人姨裸,你說我怎么就攤上這事秧倾。” “怎么了傀缩?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵那先,是天一觀的道長。 經(jīng)常有香客問我赡艰,道長售淡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任慷垮,我火速辦了婚禮揖闸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘料身。我一直安慰自己汤纸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布惯驼。 她就那樣靜靜地躺著蹲嚣,像睡著了一般递瑰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隙畜,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天抖部,我揣著相機(jī)與錄音,去河邊找鬼议惰。 笑死慎颗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的言询。 我是一名探鬼主播俯萎,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼运杭!你這毒婦竟也來了夫啊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤辆憔,失蹤者是張志新(化名)和其女友劉穎撇眯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虱咧,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡熊榛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了腕巡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玄坦。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绘沉,靈堂內(nèi)的尸體忽然破棺而出煎楣,到底是詐尸還是另有隱情,我是刑警寧澤车伞,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布转质,位于F島的核電站,受9級(jí)特大地震影響帖世,放射性物質(zhì)發(fā)生泄漏休蟹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一日矫、第九天 我趴在偏房一處隱蔽的房頂上張望赂弓。 院中可真熱鬧,春花似錦哪轿、人聲如沸盈魁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杨耙。三九已至赤套,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間珊膜,已是汗流浹背容握。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留车柠,地道東北人剔氏。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像竹祷,于是被迫代替她去往敵國和親谈跛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容