首先,遇到這個問題是由定義函數引起的。
一下兩種函數的定義有什麼區別
//方法一
var foo = function(){
//code
}
//方法二
function foo(){
//code
}
最關鍵的區別在於JavaScript函數和變量聲明的“提前”行爲。
建議採用方法一。
1、使用匿名函數
var FUNCTION_NAME = function(){/*FUNCTION_BODY*/};
編譯後變量聲明FUNCTION_NAME會“被提前”,但是他的賦值(就是FUNCTION_BODY)不會被提前。
也就是說,匿名函數只有在被調用時才初始化。
2、如果使用
function FUNCTION_NAME(){/*FUNCTION_BODY*/};
編譯後函數聲明和他的賦值(FUNCTION_BODY)都會被提前。
也就是說,函數聲明過程在整個程序執行之前的預處理就完成了,即使在定義之前調用它也可以。
舉個栗子
function hereOrThere(){//function statement
return 'here';
}
alert(hereOrThere());//alerts 'there'
function hereOrThere(){
return 'there';
}
執行結果是alert(“there”)!
主要是JavaScript函數聲明的“提前”行爲,簡言之,就是JavaScript允許我們在變量和函數被聲明之前使用它。
也就是說上述代碼編譯之後相當於
function hereOrThere(){//function statement
return 'here';
}
function hereOrThere(){//聲明被提前了,這裏聲明和賦值在一起,所以一起唄提前了
return 'there';
}
alter(hereOrThere());//alerts 'there'
再舉個栗子
var hereOrThere = function(){//function expression
return 'here';
};
alert(hereOrThere());//alert 'here'
hereOrThere = function(){
return 'there';
}
編譯之後相當於:
var hereOrThere;//聲明提前了
hereOrThere = function(){//function expression
return 'here';
};
alert(hereOrThere());//alerts 'here'
hereOrThere = function(){
return 'there';
};
ok 這貌似好像和原型或者原型鏈有什麼關係,但是我是從這裏開始認識到這個問題的,但是還是不是很理解,留作以後仔細研究。
目前知道的:
原型和原型鏈是JS實現繼承的一種模型。
原型鏈的形成是靠__proto__
.
這個圖可以留作以後思考。
構造函數:Object(原生)/function F(){};(自定義)
實例:new Object(原生)/new F();(自定義)
函數的原型對象constructor默認指向函數本身,原型對象除了有原型屬性外,爲了實現繼承,還有一個原型鏈指針proto,該指針指向上一層的原型對象,而上一層的原型對象的結構依然類似,這樣利用proto一直指向Object的原型對象上,而Object的原型對象用Object.proto = null表示原型鏈的最頂端,如此變形成了javascript的原型鏈繼承,同時也解釋了爲什麼所有的javascript對象都具有Object的基本方法。