javascript-callee、caller和this理解

callee和caller屬性以及this關(guān)鍵字的理解

最近一段時(shí)間寫代碼,也開始注意一些以前不想動(dòng)腦理解的基礎(chǔ)知識了。加油呀~~~

1. callee

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

1.1 驗(yàn)證arguments.callee

function getCallee() {

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

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

// 常用方法
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實(shí)例的一個(gè)屬性;
  • functionName.caller: functionName是當(dāng)前正在執(zhí)行的函數(shù);
  • caller返回一個(gè)對函數(shù)的引用,該函數(shù)調(diào)用了當(dāng)前函數(shù)。如果該函數(shù)在頂層被調(diào)用則返回null。

2.1 使用caller的測試代碼

function testCaller(msg) {

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

function callCaller() {

    testCaller("callCaller調(diào)用:");
}
callCaller();
// ===打印結(jié)果===
/*callCaller調(diào)用:function callCaller() {

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

3. this

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

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

3.1 標(biāo)簽屬性注冊事件調(diào)用

<button id="button1" type="button" name="button1" onclick="btnClick1()">button1</button>
<button id="button2" type="button" name="button2" onclick="btnClick2(this)">button2</button>
<script>
    // 標(biāo)簽屬性注冊事件調(diào)用
    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 點(diǎn)擊的時(shí)候輸出:window對象、button2 點(diǎn)擊的時(shí)候輸出:window對象 和 當(dāng)前dom元素。用attachEvent、addEventListener方法要先進(jìn)行判斷哈,不要直接就寫了。

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

3.2 普通函數(shù)調(diào)用

function fun1() {

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

3.3 作為對象方法調(diào)用

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

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

3.4 作為構(gòu)造函數(shù)調(diào)用-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
  • 所謂構(gòu)造函數(shù),就是通過這個(gè)函數(shù)生成一個(gè)新對象(object)。這時(shí),this就指這個(gè)新對象。即new關(guān)鍵字后的構(gòu)造函數(shù)中的this指向用該構(gòu)造函數(shù)構(gòu)造出來的新對象。

3.5 apply、call 調(diào)用

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()是函數(shù)對象的一個(gè)方法,作用是改變函數(shù)的調(diào)用對象,它的第一個(gè)參數(shù)就表示改變后的調(diào)用這個(gè)函數(shù)的對象。因此,this指的就是這第一個(gè)參數(shù)。apply()、call()的參數(shù)為空時(shí),默認(rèn)調(diào)用全局對象。

3.6 eval函數(shù)

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

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

3.7 setTimeout、setInterval和匿名函數(shù)

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

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

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

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

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

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

4.參考文章

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容