1. 作用域

作用域是一個變量或函數(shù)存在的范圍。在JavaScript中,有四種作用域:全局作用域、函數(shù)作用域、塊級作用域(if語句塊)以及對象屬性作用域。了解這些作用域有助于我們正確地聲明和使用變量。

全局作用域:在函數(shù)外部聲明的變量具有全局作用域。這意味著它們可以在整個程序中訪問。例如:

scriptvar globalVar = "I am global!";

函數(shù)作用域:在函數(shù)內(nèi)部聲明的變量具有函數(shù)作用域。這意味著它們只能在該函數(shù)內(nèi)部訪問。例如:

function myFunction() {
    var functionVar = "I am in a function!";
}

塊級作用域(if語句塊):在if語句塊內(nèi)部聲明的變量具有塊級作用域。這意味著它們只能在該if語句塊內(nèi)部訪問。例如:

if (true) {
    var blockScopeVar = "I am in a block scope!";
}

對象屬性作用域:在對象內(nèi)部聲明的變量具有對象屬性作用域。這意味著它們只能在該對象內(nèi)部訪問。例如:

var obj = {
    prop: "I am an object property!"
};

2. 閉包

閉包是指一個函數(shù)能夠記住并訪問其詞法環(huán)境(即包含該函數(shù)的作用域)。這使得我們可以使用閉包來創(chuàng)建私有變量和函數(shù)。例如:

function outer() {
    var outerVar = "I am in the outer function!";
    function inner() {
        console.log(outerVar); // 輸出 "I am in the outer function!"
    }
    return inner; // 返回 inner函數(shù)的引用
}
var innerFunc = outer(); // innerFunc現(xiàn)在引用inner函數(shù)
innerFunc(); // 輸出 "I am in the outer function!"

在這個例子中,"inner"函數(shù)可以訪問其詞法環(huán)境中的"outerVar"變量。這就是閉包的作用。通過將"inner"函數(shù)作為返回值,我們可以在其他地方再次獲取到這個對"outerVar"的引用,從而實現(xiàn)數(shù)據(jù)的持久化存儲。

3. this指向

在JavaScript中,"this"關(guān)鍵字指向當(dāng)前執(zhí)行上下文中的對象。根據(jù)不同的執(zhí)行上下文,"this"可能指向全局對象(在瀏覽器中為window對象)、調(diào)用方法的對象或者undefined。為了避免因為"this"指向問題導(dǎo)致的錯誤,我們可以使用以下幾種方法來確保正確的"this"指向:

箭頭函數(shù):"箭頭函數(shù)沒有自己的"this",它會捕獲其所在上下文中的"this"值。這使得在回調(diào)函數(shù)和類方法中使用箭頭函數(shù)成為了一個好主意。例如:

someObject.someMethod = function() {
    setTimeout(() => console.log(this), 1000); // this指向someObject,而不是全局對象window或undefined
};

確保在非嚴(yán)格模式下使用非嚴(yán)格模式下的this值:如果需要在嚴(yán)格模式下使用非嚴(yán)格模式的this值,可以通過調(diào)用Function構(gòu)造函數(shù)來實現(xiàn):"new Function('return this;')()"。但是這種做法并不推薦,因為它可能導(dǎo)致代碼難以理解和維護(hù)。例如:

function getThisValue() {
    return new Function('return this;')(); // 在嚴(yán)格模式下返回undefined,而非嚴(yán)格模式下返回當(dāng)前對象(someObject)的引用
}
console.log(getThisValue()); // undefined (在嚴(yán)格模式下)或 someObject (在非嚴(yán)格模式下)

使用call、apply或bind方法顯式地設(shè)置"this"值:"call"、"apply"和"bind"方法可以讓我們在調(diào)用函數(shù)時指定一個特定的對象作為"this"值。例如:

function greet() {
    console.log(this.name + " says hello!"); // 如果未提供參數(shù),則this指向全局對象window,否則指向傳遞給call方法的對象(如someObject)
}
greet.call(someObject); // someObject.name應(yīng)該存在且不為空字符串,否則會拋出TypeError異常