你自認為理解了JavaScript?


關於Dmitry Baranovskiy 的博客中一篇文章(http://dmitry.baranovskiy.com/post/91403200),其中有五段小代碼,用來測試是否理解 JavaScript 的核心,閉包和作用域,  該文章也在csdn論壇上受到過關注和討論, 集思廣益,下面結合自己的理解,做了如下小結。

1

if (!("a" in window)) {
    var a = 1;
}
console.log(a);

程序會首先解析所有聲明的函數,其次是var聲明的變量,因為javascript沒有塊的概念,所以if(){...}中,var聲明了 a = 1, a是依然屬於全局變量。

執行等價於:

var a; //全局
if (!("a" in window)) {
    a = 1;
}
console.log (a);

(1)開始時,聲明了變量a,但並沒有賦值,所以a = undefined ,  而undefined 存在於window中,所以(’a’ in window)返回true,  取反為false, 這樣就不會執行大括號里面的 “a=1” 的語句。

(2) console.log(a); //undefined

2

var a = 1,
    b = function a (x) {
        x && a (--x);
    };
console.log (a);

可以用一個var,來聲明多個變量,中間用多個逗號分開,執行等價於:

var a = 1;
var b = function a(x){
    x && a(--x);
}
console.log(a);

(1) 函數表達式類似於局部變量,不會被全局作用域訪問到,所以這里的函數 function a 是局部變量,外部無法訪問,因此全局a還是1;

(2) console.log(a); //1

3

function a (x) {
    return x * 2;
}
var a;
console.log(a);

javascript永遠是先解析聲明函數,再解析變量, 執行順序如下:
(1) 解析函數a;
(2) 聲明變量var a; 因為a此時並沒有被賦值,所以它為 undefined, 還是指向原來的值,即函數 function a;
(3) console.log(a); // function a

4

function b (x, y, a) {
    arguments[2] = 10;
    console.log (a); 
}
b(1, 2, 3);

函數內部,可以引用一個類數組的對象arguments,它並不是真正的數組,代表了函數實際接受參數的集合,可以通過下標對相應參數進行訪問,
如果修改了此對象的屬性,如arguments[index],則被傳進來的第index (如果有的話,下標從0開始) 變量的值也會被修改。
執行順序:

(1) 聲明一個函數b;
(2) 執行函數b(1,2,3);因為這里arguments[2]與變量a引用的是同一個值,所以當arguments[2]改變時,a也隨之改變。
(3) console.log(a) // 10;

5

function a () {
  console.log(this); 
}
a.call (null);

call 調用一個對象的一個方法,以另一個對象替換當前對象。 

格式如 call(thisObj, arg1,arg2...argN);

在函數體外部調用call()方法,如果傳入null,則默認轉成window,如果不傳也是一樣,即函數中的this指向window。
console.log(this) // window;

function a () {
    console.log (this === window);
}
console.log(this === window); // true
a.call (); // true
a.call (null); // true
a.call (this); // true
a.call (window); // true
a(); // true


function fo(){
    console.log(a); 
}
function foo(){
    var a = 2;
    fo();
}
foo();

先執行 foo 函數, fo 雖然在foo調用,但是 fo函數是聲明在全局作用域下的,所以fo中引用的a,是指向全局的window,而全局作用域下的a 並未聲明,雖然在 foo 下,聲明了var a=2,但它作為局部變量,無法被函數外的作用域所調用。
console.log(a) // a is not defined;

如果將以上代碼寫成:

function foo(){
    var a = 2;
    function fo(){
        console.log(a);
    }
    fo();
}
foo();

因為這時候,函數fo是聲明在foo函數體內的,屬於foo的內部函數,作用域鏈的訪問順序是由內向外的,a在fo里搜索不到,就會到上一級函數foo中 尋找,這里找到var a = 2 后返回結果。

console.log(a) // 2;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM