javascript筆記
//定義一個對象
var obj = new Object();
//動態創建屬性name
obj.name = "an object";
//動態創建屬性sayHi
obj.sayHi = function(){
return "Hi";
}
obj.sayHi();
在JavaScript中,包含三種基本的數據類型,字符串(String),數值(Number),布爾值(boolean),下面是一些簡單的例子:
var str = "Hello, world";//字符串
var i = 10;//整型數
var f = 2.3;//浮點數
var b = true;//布爾值
我們可以分別查看變量的值及變量的類型:
print(str);
print(i);
print(f);
print(b);
print(typeof str);
print(typeof i);
print(typeof f);
print(typeof b);
注意,在此處使用的print()函數為rhino解釋器的頂層對象的方法,可以用來打印字符串,通常情況下,在客戶端,程序員多使用alert()進行類似的動作,alert()是瀏覽器中JavaScript解釋器的頂層對象(window)的一個方法。
Hello, world
10
2.3
true
string
number
number
Boolean
在JavaScript中,所有的數字,不論是整型浮點,都屬于“數字”基本類型。typeof是一個一元的操作符.
對象類型不是對象本身,而是指一種類型,我們在第三章會對對象進行詳細的討論,此處的對象包括,對象(屬性的集合,即鍵值的散列表),數組(有序的列表),函數(包含可執行的代碼)。
對象類型是一種復合的數據類型,其基本元素由基本數據類型組成,當然不限于基本類型,比如對象類型中的值可以是其他的對象類型實例,我們通過例子來說明:
var str = "Hello, world";
var obj = new Object();
obj.str = str;
obj.num = 2.3;
var array = new Array("foo", "bar", "zoo");
var func = function(){
print("I am a function here");
}
可以看到,對象具有屬性,如obj.str, obj.num,這些屬性的值可以是基本類型,事實上還可以更復雜,我們來看看他們的類型:
print(typeof obj);
print(typeof array);
print(typeof func);
//將打印出
object
object
function
var str = "JavaScript Kernal";
print(str.length);//打印17
對象轉換為基本類型則是通過這樣的方式:通過調用對象的valueOf()方法來取得對象的值,如果和上下文的類型匹配,則使用該值。如果valueOf取不到值的話,則需要調用對象的toString()方法,而如果上下文為數值型,則又需要將此字符串轉換為數值。
valueOf()的作用是,將一個對象的值轉換成一種合乎上下文需求的基本類型,toString()則名副其實,可以打印出對象對應的字符串,當然前提是你已經“重載”了Object的toString()方法。
事實上,這種轉換規則會導致很多的問題,比如,所有的非空對象,在布爾值環境下,都會被轉成true,
var x = 3;
var y = x + "2";// => 32
var z = x + 2;// => 5
if(datamodel.item){
//do something...
}else{
datamodel.item = new Item();
}
這種寫法事實上具有更深層次的含義:
應該注意到,datamodel.item是一個對象(字符串,數字等),而if需要一個boolean型的表達式,所以這里進行了類型轉換。在JavaScript中,如果上下文需要boolean型的值,則引擎會自動將對象轉換為boolean類型。轉換規則為,如果該對象非空,則轉換為true,否則為false.因此我們可以采取這種簡寫的形式。
function handleMessage(message, handle){
if(typeof handle == "function"){
return handle(message);
}else{
throw new Error("the 2nd argument should be a function");
}
}
但是,typeof并不總是有效的,比如下面這種情況:
var obj = {};
var array = ["one", "two", "three", "four"];
print(typeof obj);//object
print(typeof array); //object
運行結果顯示,對象obj和數組array的typeof值均為”object”,這樣我們就無法準確判斷了,這時候,可以通過調用instanceof來進行進一步的判斷:
print(obj instanceof Array);//false
print(array instanceof Array);//true
第一行代碼返回false,第二行則返回true。因此,我們可以將typeof操作符和instanceof操作符結合起來進行判斷。
[]可以作用于對象,一般而言,對象中的屬性的值是通過點(.)運算符來取值,如:
var object = {
field : "self",
printInfo : function(){
print(this.field);
}
}
object.field;
object.printInfo();
但是考慮到這樣一種情況,我們在遍歷一個對象的時候,對其中的屬性的鍵(key)是一無所知的,我們怎么通過點(.)來訪問呢?這時候我們就可以使用[]運算符:
for(var key in object){
print(key + ":" + object[key]);
}
運行結果如下:
field:slef
printInfo:function (){
print(this.field);
}
點運算符的左邊為一個對象(屬性的集合),右邊為屬性名,應該注意的是右邊的值除了作為左邊的對象的屬性外,同時還可能是它自己的右邊的值的對象:
var object = {
field : "self",
printInfo : function(){
print(this.field);
},
outter:{
inner : "inner text",
printInnerText : function(){
print(this.inner);
}
}
}
object.outter.printInnerText();
這個例子中,outter作為object的屬性,同時又是printInnerText()的對象。
但是點(.)操作符并不總是可用的,考慮這樣一種情況,如果一個對象的屬性本身就包含點(.)的鍵(self.ref),點操作符就無能為力了:
var ref = {
id : "reference1",
func : function(){
return this.id;
}
};
var obj = {
id : "object1",
"self.ref" : ref
};
當我們嘗試訪問obj的”self.ref”這個屬性的時候:obj.self.ref,解釋器會以為obj中有個名為self的屬性,而self對象又有個ref的屬性,這樣會發生不可預知的錯誤,一個好的解決方法是使用中括號([])運算符來訪問:
print(obj["self.ref"].func());
運算符==讀作相等,而運算符===則讀作等同。這兩種運算符操作都是在JavaScript代碼中經常見到的,但是意義則不完全相同,簡而言之,相等操作符會對兩邊的操作數做類型轉換,而等同則不會。我們還是通過例子來說明:
print(1 == true);
print(1 === true);
print("" == false);
print("" === false);
print(null == undefined);
print(null === undefined);
運行結果如下:
true
false
true
false
true
false
相等和等同運算符的規則分別如下:
相等運算符
如果操作數具有相同的類型,則判斷其等同性,如果兩個操作數的值相等,則返回true(相等),否則返回false(不相等).
如果操作數的類型不同,則按照這樣的情況來判斷:
l null和undefined相等
l 其中一個是數字,另一個是字符串,則將字符串轉換為數字,在做比較
l 其中一個是true,先轉換成1(false則轉換為0)在做比較
l 如果一個值是對象,另一個是數字/字符串,則將對象轉換為原始值(通過toString()或者valueOf()方法)
l 其他情況,則直接返回false
等同運算符
如果操作數的類型不同,則不進行值的判斷,直接返回false
如果操作數的類型相同,分下列情況來判斷:
l 都是數字的情況,如果值相同,則兩者等同(有一個例外,就是NaN,NaN與其本身也不相等),否則不等同
l 都是字符串的情況,與其他程序設計語言一樣,如果串的值不等,則不等同,否則等同
l 都是布爾值,且值均為true/false,則等同,否則不等同
l 如果兩個操作數引用同一個對象(數組,函數),則兩者完全等同,否則不等同
l 如果兩個操作數均為null/undefined,則等同,否則不等同
//聲明一個對象
var jack = new Object();
jack.name = "jack";
jack.age = 26;
jack.birthday = new Date(1984, 4, 5);
//聲明另一個對象
var address = new Object();
address.street = "Huang Quan Road";
address.xno = "135";
//將addr屬性賦值為對象address
jack.addr = address;
JSON的應用場景是:當一個函數擁有多個返回值時,在傳統的面向對象語言中,我們需要組織一個對象,然后返回,而JavaScript則完全不需要這么麻煩,比如:
function point(left, top){
this.left = left;
this.top = top;
//handle the left and top
return {x: this.left, y:this.top};
}
直接動態的構建一個新的匿名對象返回即可:
var pos = point(3, 4);
//pos.x = 3;
//pos.y = 4;
使用JSON返回對象,這個對象可以有任意復雜的結構,甚至可以包括函數對象。
在實際的編程中,我們通常需要遍歷一個JavaScript對象,事先我們對對象的內容一無所知。怎么做呢?JavaScript提供了for..in形式的語法糖:
for(var item in json){
//item為鍵
//json[item]為值
}
函數在JavaScript中可以:
Ø 被賦值給一個變量
Ø 被賦值為對象的屬性
Ø 作為參數被傳入別的函數
Ø 作為函數的結果被返回
Ø 用字面量來創建
在JavaScript中,函數的參數是比較有意思的,比如,你可以將任意多的參數傳遞給一個函數,即使這個函數聲明時并未制定形式參數。
事實上,JavaScript在處理函數的參數時,與其他編譯型的語言不一樣,解釋器傳遞給函數的是一個類似于數組的內部值,叫arguments。
function sum(){
var result = 0;
for(var i = 0, len = arguments.length; i < len; i++){
var current = arguments[i];
if(isNaN(current)){
throw new Error("not a number exception");
}else{
result += current;
}
}
return result;
}
print(sum(10, 20, 30, 40, 50));
print(sum(4, 8, 15, 16, 23, 42));//《迷失》上那串神奇的數字
print(sum("new"));
函數sum沒有顯式的形參,而我們又可以動態的傳遞給其任意多的參數,那么,如何在sum函數中如何引用這些參數呢?這里就需要用到arguments這個偽數組了,運行結果如下:
150
108
Error: not a number exception
賦值給一個變量:
//聲明一個函數,接受兩個參數,返回其和
function add(x, y){
return x + y;
}
var a = 0;
a = add;//將函數賦值給一個變量
var b = a(2, 3);//調用這個新的函數a
print(b);
這段代碼會打印”5”,因為賦值之后,變量a引用函數add,也就是說,a的值是一個函數對象(一個可執行代碼塊),因此可以使用a(2, 3)這樣的語句來進行求和操作。
賦值為對象的屬性:
var obj = {
id : "obj1"
}
obj.func = add;//賦值為obj對象的屬性
obj.func(2, 3);//返回5
事實上,這個例子與上個例子的本質上是一樣的,第一個例子中的a變量,事實上是全局對象(如果在客戶端環境中,表示為window對象)的一個屬性。而第二個例子則為obj對象,由于我們很少直接的引用全局對象,就分開來描述。
作為參數傳遞:
//高級打印函數的第二個版本
function adPrint2(str, handler){
print(handler(str));
}
//將字符串轉換為大寫形式,并返回
function up(str){
return str.toUpperCase();
}
//將字符串轉換為小寫形式,并返回
function low(str){
return str.toLowerCase();
}
adPrint2("Hello, world", up);
adPrint2("Hello, world", low);
運行此片段,可以得到這樣的結果:
HELLO, WORLD
hello, world
var array = new Array(1, 2, 3, 4, 5);
print(array.length); //得到數組長度
另一個與其他語言的數組不同的是,字符串也可以作為數組的下標,事實上,在JavaScript的數組中,字符串型下標和數字型的下標會被作為兩個截然不同的方式來處理,一方面,如果是數字作為下標,則與其他程序設計語言中的數組一樣,可以通過index來進行訪問,而使用字符串作為下標,就會采用訪問JavaScript對象的屬性的方式進行,畢竟JavaScript內置的Array也是從Object上繼承下來的。比如:
var stack = new Array();
stack['first'] = 3.1415926;
stack['second'] = "okay then.";
stack['third'] = new Date();
for(var item in stack){
print(typeof stack[item]);
}
運行結果為:
number
string
object
向數組中添加元素:
var array = [];
array.push(1);
array.push(2);
array.push(3);
array.push("four");
array.push("five");
array.push(3.1415926);
前面提到過,JavaScript的數組有列表的性質,因此可以向其中push不同類型的元素,接上例:
var len = array.length;
for(var i = 0; i < len; i++){
print(typeof array[i]);
}
結果為:
number
number
number
string
string
number
彈出數組中的元素:
for(var i = 0; i < len; i++){
print(array.pop());
}
print(array.length);
運行結果如下,注意最后一個0是指array的長度為0,因為這時數組的內容已經全部彈出:
3.1415926
five
four
3
2
1
0
join,連接數組元素為一個字符串:
array = ["one", "two", "three", "four", "five"];
var str1 = array.join(",");
var str2 = array.join("|");
print(str1);
print(str2);
運行結果如下:
one,two,three,four,five
one|two|three|four|five
連接多個數組為一個數組:
var another = ["this", "is", "another", "array"];
var another2 = ["yet", "another", "array"];
var bigArray = array.concat(another, another2);
結果為:
one,two,three,four,five,this,is,another,array,yet,another,array
從數組中取出一定數量的元素,不影響數組本身:
print(bigArray.slice(5,9));
結果為:
this,is,another,array
slice方法的第一個參數為起始位置,第二個參數為終止位置,操作不影響數組本身。下面我們來看splice方法,雖然這兩個方法的拼寫非常相似,但是功用則完全不同,事實上,splice是一個相當難用的方法:
bigArray.splice(5, 2);
bigArray.splice(5, 0, "very", "new", "item", "here");
第一行代碼表示,從bigArray數組中,從第5個元素起,刪除2個元素;而第二行代碼表示,從第5個元素起,刪除0個元素,并把隨后的所有參數插入到從第5個開始的位置,則操作結果為:
one,two,three,four,five,very,new,item,here,another,array,yet,another,array
我們再來討論下數組的排序,JavaScript的數組的排序函數sort將數組按字母順序排序,排序過程會影響源數組,比如:
var array = ["Cisio", "Borland", "Apple", "Dell"];
print(array);
array.sort();
print(array);
執行結果為:
Cisio,Borland,Apple,Dell
Apple,Borland,Cisio,Dell
這種字母序的排序方式會造成一些非你所預期的小bug,比如:
var array = [10, 23, 44, 58, 106, 235];
array.sort();
print(array);
得到的結果為:
10,106,23,235,44,58
可以看到,sort不關注數組中的內容是數字還是字母,它僅僅是按照字母的字典序來進行排序,對于這種情況,JavaScript提供了另一種途徑,通過給sort函數傳遞一個函數對象,按照這個函數提供的規則對數組進行排序。
function sorter(a, b){
return a - b;
}
var array = [10, 23, 44, 58, 106, 235];
array.sort(sorter);
print(array);
函數sorter接受兩個參數,返回一個數值,如果這個值大于0,則說明第一個參數大于第二個參數,如果返回值為0,說明兩個參數相等,返回值小于0,則第一個參數小于第二個參數,sort根據這個返回值來進行最終的排序:
10,23,44,58,106,235
當然,也可以簡寫成這樣:
array.sort(function(a, b){return a - b;});//正序
array.sort(function(a, b){return b - a;});//逆序
郵箱地址正則var emailval = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/;
emailval.test("kmustlinux@hotmail.com");//true