函數
定義函數
- 創建一個函數需要用到關鍵字function,后面是一個函數名
- 為函數提供0或多個參數,使用參數向函數傳值
- 可以返回一個值作為調用這個函數的結果,這是可選的
- 編寫函數體,包含完成函數工作的所有代碼
JavaScript有兩種方式定義函數,第一種方式如下:
function add(x,y) {
return x + y;
}
注意,函數體內部的語句在執行時,一旦執行到return時,函數就執行完畢,并將結果返回。因此,函數內部通過運算可以實現非常復雜的邏輯。如果沒有return語句,函數執行完畢后也會返回結果,只是結果為undefined。
由于JavaScript函數也是一個對象,上述定義的add()函數實際上是一個函數對象,而函數名add可以視為指向該函數的變量。
因此,第二種定義函數的方式如下:
var add = function (x,y) {
return x + y;
};
這種方式下,function{....}
是一個匿名函數,它沒有函數名,但是這個匿名函數賦值給了變量add,所有通過變量add就可以調用該函數。
上述兩種定義是等價的,注意第二種方式按照完整語法需要在末尾加一個;號,表示賦值語句結束。
函數聲明可以出現在腳本中的任何位置。使用多個外部JavaScript文件時有一點要記住,如果不同文件中有兩個同名的函數,將使用瀏覽器最后看到的那個函數。
調用函數
調用函數時,按順序傳入參數即可:
var sum = add(1,2); //返回3
由于JavaScript允許任意參數而不影響調用,因此傳入的參數比定義的參數多也沒有問題,雖然函數內部并不需要這些參數:
var sum = add(1,2,3); //返回3
傳入的參數比定義的少也沒有問題:
var sum = add(); //返回NaN
此時,add的參數將受到undefined,計算結果為NaN
變量作用域
全局變量
如果一個變量在函數外聲明,這個變量就是全局變量。可以在JavaScript代碼中的任何地方訪問。
var x = 3; //全局變量
var y = 4;
var add = function (x,y) {
var z = 4; //局部變量
return x + y + z;
}
局部變量
如果一個變量在函數內聲明,這個變量就是局部變量。只能在函數體內部使用。
var x = 3; //全局變量
var y = 4;
var add = function (x,y) {
var z = 4; //局部變量
return x + y + z;
}
變量提升
JavaScript函數定義有個特點,它會先掃描整個函數體的語句,把所有聲明的變量提升到函數頂部
'use strict'
function foo() {
var x = "hello," + y;
alert(x);
y = "world";
}
foo();
雖然是strict模式,但語句var x = "hello," + y
并不報錯,原因是變量y在稍后說明了。但是alert顯示hello,undefined,說明變量y的值為undefined。這正是因為JavaScript引擎自動提升了變量y的聲明,但不會提升變量y的賦值。
function foo() {
var y; // 提升變量y的申明
var x = 'Hello, ' + y;
alert(x);
y = 'Bob';
}
由于JavaScript的這一特性,我們在函數內部定義變量時,請嚴格遵守“在函數內部首先聲明所有變量”這一規則。最常見的做法是用一個var聲明函數內部所用到的變量:
function foo() {
var
x = 1, // x初始化為1
y = x + 1, // y初始化為2
z, i; // z和i為undefined
// 其他語句:
for (i=0; i<100; i++) {
...
}
}
對象
普通創建對象
創建對象
已經有了一個包含一些屬性的對象。如何使用JavaScript創建這個對象呢?方法如下:
var fido = {
name: "Fido";
weight: 40;
breed: "Mixed";
loves: ["walks","fetching balls"]
};
訪問和操作對象
- 使用“點”記法訪問對象屬性
if (fido.weight > 25) {
alert("Wonderful");
} else {
alert("keep moving");
}
- 使用一個串結合[]記法訪問屬性
var breed = fido["breed"];
if (breed == "mixed") {
alert("Best in show");
}
- 改變屬性的值
fido.weight = 27; //改變Fido的重量
fido.loves.push("chewing bones"); //向它的loves數組增加一個新元素
- 枚舉對象的所有屬性
var prop;
for(prop in fido) {
alert("Fido has a" + prop + " property"); //每次循環迭代時,變量prop會得到下一個屬性名的相應串值
}
- 處理對象的數組
var likes = fido.loves;
var likesStr = "Fido likes";
for (var i = 0; i < likes.length; i++) {
likesStr += " " + likes[i];
}
- 向函數傳入一個對象
function bark(dog) {
dog.weight = 28; //會同時改變fido中的值
}
bark(fido);
注意:將一個對象賦值給變量時,這個變量會包含這個對象的一個引用,而不是對象的副本,可以把引用想成是對象的一個指針。所有對該變量中屬性的改變都會改變原對象的屬性。
上述代碼中,改變dog對象的weight屬性時,實際上是修改的原對象fido的屬性,而不是副本,所有不僅函數體內的dog對象發生了改變,函數體外的fido對象也發生了改變。
給對象增加方法
var fido = {
name: "Fido";
weight: 40;
breed: "Mixed";
loves: ["walks","fetching balls"]
bark: function() {
alert("Woof Woof");
}
};
fido.bark(); //調用方法
構造函數創建對象
構造函數
function Dog(name,breed,weight) {
this.name = name;
this.breed = breed;
this.weight = weight;
this.bark = function() {
if (this.weight) {
alert(this.name + " say Woof!");
}
};
}
注意這個語法和對象的語法有所不同。這些是語句,所有需要一個“;”結束各語句。this用于指示對象中的屬性,它就代表了新創建的實例對象。
創建對象
var fido = new Dog("Fido","Mixed",38); //new關鍵字創建一個對象
var tiny = new Dog("Tiny","Chawalla",18);
fido.bark();
tiny.bark();
prototype屬性創建對象
prototype屬性包含一個對象,所有實例對象需要共享的屬性和方法,都放在這個對象里面;那些不需要共享的屬性和方法,就放在構造函數里面。
實例對象一旦創建,將自動引用prototype對象的屬性和方法。也就是說,實例對象的屬性和方法分為兩種,一種是本地的,一種是引用的:
function DOG(name){
this.name = name;
}
DOG.prototype = { species : '犬科' };
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');
alert(dogA.species); // 犬科
alert(dogB.species); // 犬科
現在,species屬性放在prototype對象中,兩個實例對象共享的,只要修改了prototype對象,就會同時影響到兩個實例對象。
DOG.prototype.species = '貓科';
alert(dogA.species); // 貓科
alert(dogB.species); // 貓科
綜上所述,由于所有實例對象共享同一個prototype對象,那么兇外界看起來,prototype對象就好像是實例對象的原型,而實例對象則好像繼承了prototype對象一樣。
window對象
window對象表示你的JavaScript程序的全局環境,同時還表示應用的主窗口,因此,包含很多核心的屬性和方法,主要有:
|windwo||
|---|---|---
|location|屬性|包含頁面的URL
|status|屬性|包含將在瀏覽器狀態區顯示一個字符串
|onload|屬性|頁面完全加載后調用的函數
|document|屬性|包含DOM
|----|----|
|alert|方法|顯示一個提醒
|prompt|方法|類似于alert,不過會從用戶的到信息
|open|方法|打開一個新的瀏覽器窗口
|close|方法|關閉窗口
|setTimeout|方法|指定的時間間隔后調用一個處理程序
|setInterval|方法|以一個指定間隔反復調用一個處理程序
window是個全局對象,所有即使沒有在前面加上window,window的屬性或方法名也能順利解析。
document對象
document實際上是window對象的一個屬性,主要用于訪問DOM。
元素對象
元素對象就是通過getElementById方法返回的對象。
結尾
window.onload = init();表示希望調用函數init
window.onload = init; 表示把init這個函數值賦給onload屬性。