close
文章出處

看了湯姆大叔的“你真懂JavaScript嗎?”,里面有5道題目,我都一一作了,然后在chrome的控制臺里面運行了一遍,雖然只錯了一道,但還是細細讀了下答案,在此總結一下,看看是否對大家對這些JavaScript底層的原理都懂了。

題目一(所有全局變量都是window的屬性、變量聲明提前、變量賦值不會提前)

if (!("a" in window)) {
    var a = 1;
}
alert(a);

因為在JavaScript在變量聲明提前的特性,所以事實上上述代碼相當于下面所示:

        var a;
        if (!("a" in window)) {
            a = 1;
        }
        alert(a);

因為所有的全局變量都是window的屬性,所以不會進入循環體內也就不會執行a=1 這也就是為什么答案是undefined

題目二(函數聲明提前、函數表達式相當于變量賦值所以不會提前、函數聲明會覆蓋變量聲明,但不會覆蓋變量賦值)

var a = 1,
    b = function a(x) {
        x && a(--x);
    };
alert(a);

這個題目的答案是1。事實上上述代碼的相當于下而的代碼

var a = 1,
    b = function(x) {
        x && b(--x);
    };
alert(a);

原題目第二行代碼中,b和a同時指向一個地方也就是函數的入口,但是a和b唯一不同的地方在于函數定義結束也就是};后,a就引用不到了,也就是說a的作用域只在函數體內,而b的作用域卻在整個全局范圍內。看圖說話

這里面還有一個重要的概念就是:函數聲明會覆蓋變量聲明,但不會覆蓋變量賦值。看下面的例子:

function value(){
    return 1;
}
var value;
alert(typeof value);    //"function"

盡快變量聲明在下面定義,但是變量value依然是function,也就是說這種情況下,函數聲明的優先級高于變量聲明的優先級,但如果該變量value賦值了,那結果就完全不一樣了:

function value(){
    return 1;
}
var value = 1;
alert(typeof value);    //"number"

 

題目三(遇到同名的函數聲明,函數變量不會重新定義)

function a(x) {
    return x * 2;
}
var a;
alert(a);

相信你看懂了題目二的注釋之后,這題肯定會了,把答案貼一下。

題目四(callee和caller及函數參數的一些關系)

function b(x, y, a) {
    arguments[2] = 10;
    alert(a);
}
b(1, 2, 3);//結果是10

其實arguments跟數組類似,可以通過方括號語法訪問它的每一個元素,另外arguments和命名參數可以一起使用,它們是共享的,但是這個共享其實不是真正的共享一個內存地址,而是2個不同的內存地址,使用JavaScript引擎來保證2個值是隨時一樣的,所以修改了arguments的值同時也會體現在命名參數上,當然這也有一個前提,那就是這個索引值要小于你傳入的參數個數,也就是說如果你只傳入2個參數,而還繼續使用arguments[2]賦值的話,就會不一致,看如下代碼:

function b(x, y, a) {
    arguments[2] = 10;
    alert(a);
}
b(1, 2);//這時候因為沒傳遞第三個參數a,所以賦值10以后,alert(a)的結果依然是undefined,而不是10,但如下代碼彈出的結果依然是10,因為和a沒有關系。

 

function b(x, y, a) {
    arguments[2] = 10;
    alert(arguments[2]);
}
b(1, 2);//結果依然是10

不過在嚴格模式下是不允許修改arguments的值

嚴格模式對如何使用 arguments 對象做出了一些限制。首先,像前面例子中

arguments[2] = 10;

的賦值會變得無效。也就是說,即使把 arguments[2]設置為 10,y 的值仍然不會變成10。其次,重寫 arguments 的值會導致語法錯誤(代碼將不會執行)。

題目五(this的相關概念)

function a() {
    alert(this);
}
a.call(null);

 this說直白一點就是當前調用的對象,也就是說如果方法是某個對象的屬性的話,那在該方法內的this就指向這個對象,this指向的是運行時的當前對象。如果某方法是全局函數的話,那該方法內的this就指向window

call方法主要是用來改變作用域鏈的,call方法作為一個function執行代表該方法可以讓另外一個對象作為調用者來調用,call方法的第一個參數是對象調用者,隨后的其它參數是要傳給調用method的參數(如果聲明了的話),根據ECMAScript262規范規定:如果第一個參數傳入的對象調用者是null或者undefined的話,call方法將把全局對象(也就是window)作為this的值。所以,不管你什么時候傳入null,其this都是全局對象window。

所以這題目的答案是[object Window]


不含病毒。www.avast.com
arrow
arrow
    全站熱搜

    AutoPoster 發表在 痞客邦 留言(0) 人氣()