JavaScript中級筆記(3)

來源:互聯網
上載者:User
接下來講解範圍。

          3,範圍
     所有的物件導向的語言都有某種形式的範圍,JavaScript也不例外。在JavaScript裡,範圍是由函數劃分的,而不是由塊(while,if之類的)來劃分的。      我們先來看一個簡單的範圍的例子。
<script type="text/javascript">
var foo = "a"; //設定全域變數foo
if(true){
   var foo = "b";//在if塊中,把foo的值改為b,注意:此時還在全域範圍中
}
alert(foo);
</script>

     在if塊中,雖然foo的值改為“b“,但還是在全域範圍中,所以輸出結果是“b“。      基於瀏覽器的JavaScript語言有一門有趣的特性是,所有屬於全域範圍的變數都是window對象的屬性。      看下面代碼:

<script type="text/javascript">
var foo = "a"; //設定全域變數foo
if(true){
   var foo = "b";//在if塊中,把foo的值改為b,注意:此時還在全域範圍中
}
alert(foo);
alert("window的屬性:"+window.foo);
alert(window.foo == foo);//true,證明全域變數和window屬性一致
</script>


     我們再上例的基礎上,再添加一個函數來修改foo的值,代碼如下:

<script type="text/javascript">
var foo = "a"; //設定全域變數foo
if(true){
   var foo = "b";//在if塊中,把foo的值改為b,注意:此時還在全域範圍中
}
alert(foo);

//建立一個會修改foo變數的函數
function change(){
   var foo = "c";//修改foo的值
   alert("函數內部的值為:"+foo); //代碼①
}
change();//然後調用時,foo只在函數範圍內起作用,所以下面輸出的foo還是“b”
alert("函數外部的值為:"+foo); //代碼②
</script>

     結果也許有點另你意外,不過結果肯定是正確的。代碼②的結果是輸出 "b",而不是"c"。原因就是範圍有關,雖然調用change()來改變foo的值,但是此時的改變只
在函數範圍內起作用,並不會改變全域範圍內的foo的值。
     如果想在change()函數內修改全域的foo的值,我們可以去掉變數的聲明,例如:

<script type="text/javascript">
var foo = "a"; //設定全域變數foo
if(true){
   var foo = "b";//在if塊中,把foo的值改為b,注意:此時還在全域範圍中
}
alert(foo);

//建立一個會修改foo變數的函數
function change(){
// var foo = "c";
   foo = "c";//修改foo的值,去掉var聲明,

   alert("函數內部的值為:"+foo);
}
change();
alert("函數外部的值為:"+foo);
</script>

     在JavaScript中,如果變數沒有顯式定義,它就是全域定義的。所以調用change()後,會修改全域foo的值。最終輸出"c" 。

     4,內容物件     
     在JavaScript中,代碼總是有一個內容物件,代碼處於該對象之內。內容物件是通過this變數來體現的。這個變數永遠指向當前代碼所處的對象中。      全域對象其實是window對象的屬性。      接下來,我們看一個內容物件的例子。
<script type="text/javascript">
//定義一個對象
var obj = {
show : function(){
   this.display = "show";
} ,
hide : function(){
   this.display = "hide";
}
} alert(obj.display);//此時為undefined
obj.show();//執行show函數後,將display屬性跟obj對象聯絡起來了
alert(obj.display);//"show"
</script>
     再此基礎上,我們再看一個例子:
<script type="text/javascript">
//定義一個對象
var obj = {
show : function(){
   this.display = "show";
} ,
hide : function(){
   this.display = "hide";
}
} alert(obj.display);//此時為undefined
obj.show(); //執行show函數後,將display屬性跟obj對象聯絡起來了
alert(obj.display);//"show" window.hide = obj.hide;//把window.hide指向obj.hide
window.hide();//執行。hide的內容物件是window對象了,所以this將指向window對象
alert(obj.display);//"show"。obj對象的display屬性值不變,因為hide的上下文已經改變為window對象了
alert(window.display);//"hide"。 window對象的display屬性被更新了

</script>

     本例中,我們把obj.hide變數的內容物件變為window對象時,代碼寫得並不好理解。幸運的是,JavaScript提供了一套更好的方法來解決。

    現在我們有請call和apply兩位先生上場,通過它們也可以完成同樣的功能。先看call:
<script type="text/javascript">
//定義一個對象
var obj = {
show : function(){
   this.display = "show";
} ,
hide : function(){
   this.display = "hide";
}
} alert(obj.display);//此時為undefined
obj.show(); //執行show函數後,將display屬性跟obj對象聯絡起來了
alert(obj.display);//"show" //window.hide = obj.hide;//把window.hide指向obj.hide
//window.hide();//執行。hide的內容物件是window對象了,所以this將指向window對象
obj.hide.call( window );

alert(obj.display);//"show"。obj對象的display屬性值不變,因為hide的上下文已經改變為window對象了
alert(window.display);//"hide"。 window對象的display屬性被更新了
</script>
     通過obj.hide.call(window),我們將此時的內容物件改為window對象。call方法的第一個參數就是內容物件。      call方法也可以傳遞更多的參數,如下所示:
<script type="text/javascript">
//定義一個對象
var obj = {
show : function(){
   this.display = "show";
} ,
hide : function(msg1,msg2){
   this.display = msg1+" , "+msg2;
}
} alert(obj.display);//此時為undefined
obj.show(); //執行show函數後,將display屬性跟obj對象聯絡起來了
alert(obj.display);//"show" //window.hide = obj.hide;//把window.hide指向obj.hide
//window.hide();//執行。hide的內容物件是window對象了,所以this將指向window對象
obj.hide.call( window , "a" , "b" ); //傳遞3個參數,第一個是內容物件,後面的是函數的參數
alert(obj.display);//"show"。obj對象的display屬性值不變,因為hide的上下文已經改變為window對象了
alert(window.display);//"hide"。 window對象的display屬性被更新了
</script>

另外apply方法跟call類型,它的第一個參數也是內容物件,不過後面的參數則是一個數組。如下所示:

<script type="text/javascript">
//定義一個對象
var obj = {
show : function(){
   this.display = "show";
} ,
hide : function(msg1,msg2){
   this.display = msg1+" , "+msg2;
}
} alert(obj.display);//此時為undefined
obj.show(); //執行show函數後,將display屬性跟obj對象聯絡起來了
alert(obj.display);//"show" //window.hide = obj.hide;//把window.hide指向obj.hide
//window.hide();//執行。hide的內容物件是window對象了,所以this將指向window對象
obj.hide.apply( window , ["a","b"] ); //後面的參數為數組
alert(obj.display);//"show"。obj對象的display屬性值不變,因為hide的上下文已經改變為window對象了
alert(window.display);//"hide"。 window對象的display屬性被更新了
</script>
     最後我們來看一個通過上下文,call和apply結合的例子。     

<html>
<head>
<title>demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
function changeColor(color){
this.style.color = color;
}
function setBodyColor(){
changeColor.apply( document.body , ["blue"]);
}
window.onload = function(){
//changeColor("red");//在window對象中調用此函數會失敗,因為window對象沒有style屬性
var div = document.getElementById("abc");
changeColor.call(div , "red");//把上下文改為div。從而this指向的是 id為abc的元素
//changeColor.apply(div , ["red"]);//把上下文改為div。從而this指向的是 id為abc的元素
setBodyColor();
}
</script>
</head>
<body>
<div id="abc">CssRain</div>
TestTest
</body>
</html>

     在setBodyColor函數中,apply的第二個參數是數組,而前面我們講過,arguments 也是一個偽數組,那麼它們2個能聯絡起來嗎?     把 changeColor.apply( document.body , ["blue"]); 改為 changeColor.apply( document.body , arguments );,     然後給setBodyColor();函數傳參數。如下代碼所示:

   <html>   <head>
   <title>demo</title>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <script type="text/javascript">
   function changeColor(color){
   this.style.color = color;
   }
   function setBodyColor(){
   changeColor.apply( document.body , arguments);
}window.onload = function(){
    //changeColor("red");//在window對象中調用此函數會失敗,因為window對象沒有style屬性
    var div = document.getElementById("abc");
   changeColor.call(div , "red");//把上下文改為div。從而this指向的是 id為abc的元素
    //changeColor.apply(div , ["red"]);//把上下文改為div。從而this指向的是 id為abc的元素
   setBodyColor("blue");
}
</script>
</head>
<body>
<div id="abc">CssRain</div>
TestTest
</body>
</html>
     通過這些例子,你也許對內容相關的概念比較熟悉了。上下文在物件導向的編程中非常重要。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.