看了湯姆大叔的“你真懂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]
文章列表