目錄
1.this究竟是什么
2.綁定this的方法
3.caller、arguments和callee
1.this究竟是什么
this總是指向一個調用當前屬性或方法所在的對象,它在不同的運行環境(屬性和方法的調用者)指向的環境(對象)不同,也就是說this的指向是動態的,但是無論this的指向是誰,只要清楚屬性和方法的調用者是誰那么this就指向誰。
//在瀏覽器全局環境下,即window對象下
var print = function(){
console.log(this)
}
print()//this指向Window,因為這是Window對象調用了print方法
//在特定對象的環境下
var o = {
print: function(){
console.log(this)
}
}
o.print()//this指向o,因為這是o對象調用print方法
2.綁定this的方法
this的動態切換,固然為JavaScript創造了巨大的靈活性,但有時,需要把this固定下來,避免出現意想不到的情況。JavaScript提供了call、apply、bind這三個方法,來切換/固定this的指向。
- function.prototype.call()
函數實例的call方法可以指定函數內部this的指向,即函數執行時所在的作用域
var obj = {};
var fn = function(){
return this
}
fn() === this // true
fn.call(obj) === obj // true
fn()執行時所在的作用域是全局環境,所以this是window,而fn.call(obj)則是在對象obj環境下執行的,所以此時的this指向obj。
fn.call(null) === this
fn.call(undefined) === this
fn.call === this
call方法內部的參數如果為空、null和undefined,則默認傳入全局對象。
var obj = {};
var add = function(x,y){
return x+y
}
add.call(obj,2,3)
call方法還可以接受多個參數。call的第一個參數就是this所要指向的那個對象,后面的參數則是函數調用時所需的參數。
-
function.prototype.apply()
apply方法的作用與call方法類似,也是改變this指向,然后再調用該函數。唯一的區別就是,它接收一個數組作為函數執行時的參數。
function fn(x,y){
return x+y
}
fn.call(null,1,1)//2
fn.apply(null,[1,1])//2
fn函數本來接受兩個參數,使用apply方法以后,就變成可以接受一個數組作為參數。
【注】
結合apply和數組,我們可以寫一個小代碼找出數組最大或最小元素;
var arr = [3,5,7,10,2,8];
//未利用apply方法
var min = arr[0];
for (var i = 0;i<arr.length;i++){
if(arr[i]< min){
min = arr[i]
}
}
console.log(min)//2
//使用apply方法
Math.min.apply(null,arr)//2
-
function.prototype.bind()
bind方法用于將函數體內的this綁定到某個對象,然后返回一個新函數,原理和call方法類似。
3.caller、callee和arguments
-
caller
當函數outer調用函數inner時,被調用的函數inner會自動生成一個caller屬性,指向調用它的函數對象。
如果該函數未被調用或是不是被其他函數調用,則caller為null。
function outer(){
console.log(outer.caller);
function inner(){
console.log(inner.caller);
};
inner()
}
outer()
//null
//function outer(){}
- arguments
在函數被調用時,會在該函數內部生成一個名為arguments的類數組的隱藏對象,可以使用[]運算符獲取函數調用時傳遞的實參,只有函數被調用時,arguments對象才會創建。
function fn(a,b){
console.log(arguments);
}
fn(1,2)//[1,2]
-
callee
當函數被調用時,它的arguments.callee對象就會指向自身,由于arguments在函數被調用時才有效,因此arguments.callee在函數未調用時是不存在的。
function fn(){
console.log(arguments.callee());
}
fn()//fn(){}
【注】
本次筆記整理自阮一峰JavaScript標準參考教程和饑人谷筆記