js – this , call , bind , apply

js – this , call , bind , apply

this 指向是誰,說白文就是
誰調用函數,this 指的就是誰

在 js 中,常見的涵式調用共有六種,各涵式的this指向也不同:

1.普通涵數 => this 指向 window

function fn(){
   console.log("普通涵數 this ==> ",this)
}
fn(); 

2.物件的方法 => this 指向 obj

 var obj = {
       sayHi:function(){
            console.log("物件涵數 this==>",this)
       }
 }
obj.sayHi();

3.構造涵數 => this 指向 andyLui 實例

function Star(){
     console.log("構造涵數this ==> ",this)
}
var andyLui = new Star();

4.綁定事件涵數 => this 指向 btn

var btn = document.querySelector('button')
btn.addEventListener('click',function(){
     console.log("綁定事件涵數this==> ",this)
})

5. 定時器函數 => this 指向 window

setTimeout(function(){
    console.log("定時器函數this==>",this)
},1000)

6. 立即執行函數 => this 指向 window

(function(){
   console.log("立即執行函數this==>",this)
})()

以上雖然得知當前 this 的指向,但this指向是可以改變的,向常用的就有 bind, apply, call 等方法。


call( )

call 可以調用函數,也可以改變 this 指向。

var o ={
    name:'andy'
}
function fn(a,b){
    console.log(this,a+b)
}

fn.call() 

當我們這時候直接寫 fn.call( ) 時, this 是指向 window,如果我們要指向 o 這物件就需要改成


fn.call(o,1,2) 

一般來說, call ( ) 會常用於繼承的情況,讓子類繼承父類的屬性。

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

function Son (name,age,sex){
    Father.call(this,name,age,sex)
}

var cow = new Son("牛牛",20,'boy')

apply( )

apply 和 call 一樣,也是用來改變函數內部 this 指向,但傳遞參數是用 陣列方式傳遞。

var o ={
    name:'andy'
}

function fn(arry){
    console.log(this)
    console.log(arry) // 'pink'
}

//call調用函數
fn.apply(o,['pink']) 

例如可以處理陣列相關最大值

var arr =[1,66,30,99,28]
var max = Math.max.apply(Math,arr)
console.log("最大值",max)

個人覺得 aplly 跟 call 有點像把別人既有功能拿來用。在傳參數中,第一個參數都是要把 this 只向誰(誰調用這個方法的人),像call中的例子,因為孩子要繼承或調用父類的屬性,所以 this 指向 Son。 則 call 的例子,是Math 要去調用 max 方法,找出陣列最大值,所以 this 會指向 Math。


bind( )

bind 可以改變函數內部 this 指向,但不會調用,當bind後,它會回傳一個已經改變this指向的新函數。

var o ={
   name:'andy'
}

function fn(a,b){
    console.log(this)
    console.log(a+b)
}

//bind
const f = fn.bind(o,1,2);
f()

bind 常見使用例子