This詳講

人生就像一列開往墳墓的列車,路途上會有很多站,很難有人至始至終陪你走完全程,當陪你的人要下車時,即便不舍,也要心存感激,然后揮手告別。---sunnyhuang

在es5很多新手可能對于this感覺到很迷惑,看見有些大神對this靈活運用,心里很是羨慕,不要緊,這篇文章讓你徹底明白什么是this

函數(shù)的四種調用

  1. func(p1,p2) 直接調用
  2. obj.child.method(p1,p2) 對象的方法調用
  3. func.call(null,p1,p2) 通過call調用
  4. func.apply(null,[p1,p2]) 通過apply調用

我們一般都使用的是第一種和第二種調用,但是正規(guī)的函數(shù)調用是第三種和第四種。
func.call(context,p1,p2) this就是這個context的值,后面的是傳入的參數(shù),在不嚴格模式下,context等于null或undefined的時候會自動指向為window對象,同時值為原始值(數(shù)字,字符串,布爾值)的 this 會指向該原始值的自動包裝對象。

面試題運用

你可能遇到過這樣的題目

var obj={
    sum: function(){
       console.log(this)
    }
}
var bar=obj.sum;
obj.sum()  //輸出的是obj
bar()   //輸出的確實window

我們不通過第一種或者第二種調用函數(shù),通過第三種來調用函數(shù)上述代碼的變換

obj.sum()  --->obj.sum.call(obj)   //obj就是context
bar()  ---->bar.call(undefined)   可以簡寫bar.call()   //window就是context   

數(shù)組的運用

猜猜如果數(shù)組中的元素調用函數(shù),this指向誰呢?
function fn(){console.log(this)}
function fn1(){console.log(this+"fn2")}
var arr=[fn,fn1]
arr[0]() >---你可以意淫成arr.0.call(arr)

小試牛刀

var a = {
    name:"zhang",
    sayName:function(){
        console.log("this.name="+this.name);
    }
};
var name = "ling";
function sayName(){
    var sss = a.sayName;
    sss(); //this.name = ?   >--sss.call(undefined)  window.name
    a.sayName(); //this.name = ?   >--a.sayname.call(a)  a.name
    (a.sayName)(); //this.name = ? >--只是對于a進行了一層包裝,a.sayname.call(a)   a.name
    (b = a.sayName)();//this.name = ?  >--先進行b的復制,然后再執(zhí)行 b()  b.call()  window.name
}
sayName();
// ling
// zhang
// zhang
// ling

變形

var name = "ling";
function sayName(){
    var a = {
        name:"zhang",
        sayName:getName
    };

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

    getName(); //this.name = ?  >--getName.call()   window.name
    a.sayName(); //this.name = ?  >--a.sayName.call(a)  a.name
    getName.call(a);//this.name = ?  它直接轉換了,所以是a.name
}
sayName();
//ling
// zhang
//zhang

繼續(xù)變形,我看你能翻出天

var name = "ling";
var obj = {
    name:"zhang",
    sayName:function(){
        console.log("this.name="+this.name);
    },
    callback:function(){
        var that = this;  //2. 所以這里的this值是obj  that=this
        return function(){
            var sayName = that.sayName; //3. 這里就相當于是obj.sayName
            that.sayName(); //this.name = ?  //4. obj.sayName.call(obj)   obj.name
            sayName();//this.name = ?   //  sayName.call()    window.name
        }
    }
}
obj.callback()()  //1. 首先里面有一個this被復制給that 先轉換這個obj.callback.call(obj)()
// zhang
//ling

讓我們更加加深轉換代碼

  1. fun()
  2. obj.child.call(obj)
  3. arr.push(1)
  4. arr.push.call(arr,3)
  5. obj1.obj2.sum()

仰天抬頭看看世界,思考1分鐘人生,然后看題

1. fun.call()
2. obj.child()
3. arr.push.call(arr,1)  //記住1是參數(shù)
4. arr.push(3)
5. obj1.obj2.sum.call(obj2)

挑戰(zhàn)升級

理解Array的原型調用
如果你是一個看mdn的小baby,就會在數(shù)組上面經(jīng)??吹紸rray函數(shù)的原型上面調用函數(shù)實現(xiàn)某種效果

1. 在es5的時候實現(xiàn)一個數(shù)組push另一個數(shù)組
var arr1=[1,2,3],arr2=[4,5,6]
Array.prototype.push.apply(arr1,arr2) //arr1=[1,2,3,4,5,6]

剛開始,由于自己沒有開發(fā)過api,我也不是怎么理解這個的原理,下面我來分解一下

  1. 如果我想給arr1后面添加一個數(shù)據(jù)arr1.push(1)
  2. 用我們剛剛的進行轉換 arr1.push.call(arr,1)>--變成apply arr1.push.apply(arr1,[1])
  3. 我們把[1]變成arr2 arr1.push.apply(arr1,arr2)
  4. 由于數(shù)組的提供的api,不可能每一個都是arr1,所以統(tǒng)一調用Array.prototype。我們把arr1換成Array.prototype

試試理解 Math.max.apply(null,[1,2,3])


ES6的擴展語句

arr1.push(...arr2)
Math.max(...arr1)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 工廠模式類似于現(xiàn)實生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實現(xiàn)同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 8,130評論 2 17
  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile麗語閱讀 4,098評論 0 6
  • 三、閉包和高階函數(shù) 3.1 閉包 3.1.1 變量的作用域 所謂變量的作用域,就是變量的有效范圍。通過作用域的劃分...
    梁同學de自言自語閱讀 1,551評論 0 6
  • 創(chuàng)建對象 對象是無序屬性的集合,其屬性可以包含基本值,對象或者函數(shù),即由若干個“鍵值對”(key-value)構成...
    LeoCong閱讀 215評論 0 0
  • 目標:js中this的指向? 問題的引出 指出this指向什么 js中函數(shù)的三種調用形式 func(p1, p2)...
    放風箏的小小馬閱讀 276評論 0 0

友情鏈接更多精彩內容