javascript-callee、caller和this理解

callee和caller屬性以及this關鍵字的理解

最近一段時間寫代碼,也開始注意一些以前不想動腦理解的基礎知識了。加油呀~~~

1. callee

  • callee是實參對象arguments的一個屬性(arguments.callee);
  • callee返回當前正在執(zhí)行的函數;
  • callee有利于做匿名函數的遞歸。

1.1 驗證arguments.callee

function getCallee() {

    return arguments.callee;
}
let callee = getCallee();
console.log(callee === getCallee); // true

1.2 利用arguments.callee實現(xiàn)遞歸完成階乘函數

// 常用方法
function factorial1(num) {

    return num > 1 ? num * factorial1(num - 1) : 1;
}
console.log("factorial1(5) = " + factorial1(5)); // 120

// 使用arguments.callee
function factorial2(num) {

    return num > 1 ? num * arguments.callee(num - 1) : 1; // 120
}
console.log("factorial2(5) = " + factorial2(5));

2. caller

  • caller是Function實例的一個屬性;
  • functionName.caller: functionName是當前正在執(zhí)行的函數;
  • caller返回一個對函數的引用,該函數調用了當前函數。如果該函數在頂層被調用則返回null。

2.1 使用caller的測試代碼

function testCaller(msg) {

    console.log(msg + testCaller.caller);
}
testCaller("頂層調用:"); // 頂層調用:null

function callCaller() {

    testCaller("callCaller調用:");
}
callCaller();
// ===打印結果===
/*callCaller調用:function callCaller() {

        testCaller("callCaller調用:");
}*/

3. this

理解this代表什么真的很重要。以下內容僅涉及在前端開發(fā)中this的調用方式,喜歡動腦的你們可以試一試拿這些應用場景和之前接觸的編程語言來做一個對比呀~

  • this是Javascript語言的一個關鍵字。它代表函數運行時,自動生成的一個內部對象,只能在函數內部使用。隨著函數使用場合的不同,this的值會發(fā)生變化。但是有一個總的原則,那就是this指的是,調用函數的那個對象(是執(zhí)行環(huán)境,而非聲明環(huán)境)。

3.1 標簽屬性注冊事件調用

<button id="button1" type="button" name="button1" onclick="btnClick1()">button1</button>
<button id="button2" type="button" name="button2" onclick="btnClick2(this)">button2</button>
<script>
    // 標簽屬性注冊事件調用
    function btnClick1() {

        console.log(this);
    }
    function btnClick2(dom) {

        console.log(this);
        console.log(dom);
    }
    var eleButton1= document.getElementById("button1");
    var eleButton2= document.getElementById("button2");
    eleButton1.onmouseover = btnClick1; // dom
    eleButton2.attachEvent("onmouseover", btnClick1); // window
    eleButton2.addEventListener("mouseover", btnClick1, false); // dom
</script>

注:button1 點擊的時候輸出:window對象、button2 點擊的時候輸出:window對象 和 當前dom元素。用attachEvent、addEventListener方法要先進行判斷哈,不要直接就寫了。

  • 通過標簽屬性注冊事件調用,方法體中的this值指向window對象;
  • js代碼中給dom元素綁定事件屬性,方法體中的this指向當前dom元素;
  • IE低版本中利用attachEvent給dom元素注冊事件,方法體中的this指向window對象;
  • 利用addEventListener給dom元素注冊事件,方法體中的this指向當前dom元素;
  • 最后,如果你利用jquery綁定事件,回調函數中的this值是當前dom元素。

3.2 普通函數調用

function fun1() {

    console.log("普通函數調用" + this);
}
fun1(); // 普通函數調用[object Window]
  • 直接調用普通函數時,this是指向window對象的;
  • 當沒有明確的執(zhí)行時的當前對象時,this指向全局對象window(非瀏覽器情況下(例如:nodejs)中全局變量并非window對象,而是叫“全局變量”(the global object)global)。

3.3 作為對象方法調用

var age = 10;
var tom = {
    age: 20,
    printAge: function () {

        console.log(this.age);
    }
};
tom.printAge(); // 20
  • 函數作為某個對象的方法調用,這時this就指這個上級對象。

3.4 作為構造函數調用-new

var name = "window";
function People(name) {

    this.name = name;
}
People.prototype.printName = function () {

    console.log(this.name);
};
var people1 = new People("tom");
console.log(name); // window
console.log(people1.name); // tom
people1.printName(); // tom
  • 所謂構造函數,就是通過這個函數生成一個新對象(object)。這時,this就指這個新對象。即new關鍵字后的構造函數中的this指向用該構造函數構造出來的新對象。

3.5 apply、call 調用

var color = "red";
var car = {
    color: "blue",
    printColor: function () {

        console.log(this.color);
    }
};
car.printColor(); // blue
car.printColor.call(); // red
car.printColor.call(this); // red
car.printColor.call(car); // blue
car.printColor.apply(); // red
car.printColor.apply(this); // red
car.printColor.apply(car); // blue

注:apply()、call()是函數對象的一個方法,作用是改變函數的調用對象,它的第一個參數就表示改變后的調用這個函數的對象。因此,this指的就是這第一個參數。apply()、call()的參數為空時,默認調用全局對象。

3.6 eval函數

var age = 10;
var tom = {
    age: 20,
    printAge: function () {

        eval("console.log(this.age)");
    }
};
tom.printAge(); // 20
  • eval函數執(zhí)行的時候,this綁定到當前作用域的對象上。

3.7 setTimeout、setInterval和匿名函數

var city = "四川";
var bob = {
    city: "北京",
    printCity: function () {

        var that = this; // 匿名函數中使用對象bob
        (function () {

            console.log("匿名函數:" + this.city); // 四川
            console.log("匿名函數-that:" + that.city); // 北京
        }());
        setTimeout(function () {

            console.log("setTimeout:" + this.city); // 四川
        }, 2000);
        setInterval(function () {

            console.log("setInterval:" + this.city); // 四川
        }, 5000)
    }
};
bob.printCity();
  • 在瀏覽器中setTimeout、setInterval和匿名函數執(zhí)行時的當前對象是全局對象window(瀏覽器中全局變量可以當成是window對象下的變量);

最后:this的應用場景有很多,在平時開發(fā)中一定要注意,避免入坑。

4.參考文章

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容