ECMAScript基礎

ECMAScript語法

  • 區(qū)分大小寫
  • 變量是弱類型的,與 Java 和 C 不同,定義變量時只用var運算符,可以將它初始化為任意值。
  • 與Java不同的還有變量可以存放不同類型的值。這是弱類型變量的優(yōu)勢。例如,可以把變量初始化為字符串類型的值,之后把它設置為數(shù)字值,如下所示:
var test = "hi";
alert(test);
test = 55;          // 可由字符串直接轉換成數(shù)字
alert(test);
  • 每行結尾的分號可有可無
  • 有兩種類型的注釋:1) 單行注釋以雙斜杠開頭(//) 2)多行注釋以單斜杠和星號開頭(/),以星號和單斜杠結尾(/)

ECMAScript變量

聲明變量

ECMAScript 中的變量是用 var 運算符(variable 的縮寫)加變量名定義的。例如:

var test = "hi";

命名變量

變量名需要遵守兩條簡單的規(guī)則:

  • 第一個字符必須是字母、下劃線(_)或美元符號($)
  • 余下的字符可以是下劃線、美元符號或任何字母或數(shù)字字符

命名規(guī)則

  • Camel 標記法
    首字母是小寫的,接下來的字母都以大寫字符開頭。例如:
var myTestValue = 0, mySecondValue = "hi";
  • Pascal 標記法
    首字母是大寫的,接下來的字母都以大寫字符開頭。例如:
var MyTestValue = 0, MySecondValue = "hi";
  • 匈牙利類型標記法
    在以 Pascal 標記法命名的變量前附加一個小寫字母(或小寫字母序列),說明該變量的類型。例如,i 表示整數(shù),s 表示字符串,如下所示:
var iMyTestValue = 0, sMySecondValue = "hi";

推薦使用匈牙利類型標記法。

變量聲明不是必須的

ECMAScript 另一個有趣的方面(也是與大多數(shù)程序設計語言的主要區(qū)別),是在使用變量之前不必聲明。例如:

var sTest = "hello ";
sTest2    = sTest + "world";  // 變量聲明不是必須的
alert(sTest2);

ECMAScript 的解釋程序遇到未聲明過的標識符時,用該變量名創(chuàng)建一個全局變量,并將其初始化為指定的值。
這是該語言的便利之處,不過如果不能緊密跟蹤變量,這樣做也很危險。最好的習慣是像使用其他程序設計語言一樣,總是聲明所有變量。

在 ECMAScript 中,變量可以存在兩種類型的值,即原始值和引用值。

原始值(primitive type)

  • 存儲在棧(stack)中的簡單數(shù)據(jù)段,也就是說,它們的值直接存儲在變量訪問的位置。
  • 原始類型有5種:Undefined、Null、Boolean、Number和String型。由于這些原始類型占據(jù)的空間是固定的,所以可將他們存儲在較小的內(nèi)存區(qū)域(棧)中。這樣存儲便于迅速查尋變量的值。
  • 在許多語言中,字符串都被看作引用類型,而非原始類型,因為字符串的長度是可變的。ECMAScript 打破了這一傳統(tǒng)。
    <br />

引用值

  • 存儲在堆(heap)中的對象,也就是說,存儲在變量處的值是一個指針(point),指向存儲對象的內(nèi)存處。
  • 由于引用值的大小會改變,所以不能把它放在棧中,否則會降低變量查尋的速度。相反,放在變量的??臻g中的值是該對象存儲在堆中的地址。地址的大小是固定的,所以把它存儲在棧中對變量性能無任何負面影響。如下圖所示:


    原始值與引用值

    <br />

原始類型

typeof 運算符

對變量或值調(diào)用 typeof 運算符將返回下列值(注意是小寫)之一:

  • undefined - 如果變量是 Undefined 類型的
  • boolean - 如果變量是 Boolean 類型的
  • number - 如果變量是 Number 類型的
  • string - 如果變量是 String 類型的
  • object - 如果變量是一種引用類型或Null類型
    注釋:您也許會問,為什么 typeof 運算符對于 null 值會返回 "Object"。這實際上是 JavaScript 最初實現(xiàn)中的一個錯誤,然后被 ECMAScript 沿用了。現(xiàn)在,null 被認為是對象的占位符,從而解釋了這一矛盾,但從技術上來說,它仍然是原始值。
    <br />

Undefined類型

Undefined 類型只有一個值,即 undefined(注意小寫)。當聲明的變量未初始化時,該變量的默認值是 undefined。

var oTemp;
alert(typeof oTemp);        // 輸出 "undefined"
alert(oTemp == undefined);  // 輸出 "true"

alert(typeof oTemp2);       // 輸出 "undefined"

如果對 oTemp2 使用除 typeof 之外的其他運算符的話,會引起錯誤,因為其他運算符只能用于已聲明的變量上。
例如,下面的代碼將引發(fā)錯誤:

var oTemp;
alert(oTemp2 == undefined);

當函數(shù)無明確返回值時,返回的也是值 "undefined",如下所示:

function testFunc() {
}

alert(testFunc() == undefined);  // 輸出 "true"

<br />

Null類型

另一種只有一個值的類型是 Null,它只有一個專用值 null(注意小寫),值 undefined 實際上是從值 null 派生來的,因此 ECMAScript 把它們定義為相等的。

alert(null == undefined);  //輸出 "true"

盡管這兩個值相等,但它們的含義不同。undefined是聲明了變量但未對其初始化時賦予該變量的值,null則用于表示尚未存在的對象。如果函數(shù)或方法要返回的是對象,那么找不到該對象時,返回的通常是 null。
<br />

Boolean類型

Boolean 類型是 ECMAScript 中最常用的類型之一。它有兩個值 true 和 false。
即使 false 不等于 0,0 也可以在必要時被轉換成 false,這樣在 Boolean 語句中使用兩者都是安全的。

var bTest = false;
alert(typeof bTest);  // 輸出"boolean"

<br />

Number類型

ECMA-262 中定義的最特殊的類型是 Number 類型。這種類型既可以表示 32 位的整數(shù),還可以表示 64 位的浮點數(shù)。
對于浮點字面量的有趣之處在于,用它進行計算前,真正存儲的是字符串。
ECMAScript 默認把具有 6 個或 6 個以上前導 0 的浮點數(shù)轉換成科學計數(shù)法。
Number類型定義了幾個特殊值:

  • Number.MAX_VALUE
  • Number.MIN_VALUE
  • NaN(Not a Number)
    當計算生成的數(shù)大于 Number.MAX_VALUE 時,它將被賦予值 Number.POSITIVE_INFINITY,意味著不再有數(shù)字值。同樣,生成的數(shù)值小于 Number.MIN_VALUE 的計算也會被賦予值 Number.NEGATIVE_INFINITY,也意味著不再有數(shù)字值。如果計算返回的是無窮大值,那么生成的結果不能再用于其他計算。
    與無窮大一樣,NaN 也不能用于算術計算。NaN 的另一個奇特之處在于,它與自身不相等,這意味著下面的代碼將返回 false:
alert(NaN == NaN);     // 輸出 "false"

出于這個原因,不推薦使用 NaN 值本身。函數(shù) isNaN() 會做得相當好:

alert(isNaN("blue"));  // 輸出 "true"
alert(isNaN("666"));   // 輸出 "false"

<br />

String類型

String 類型的獨特之處在于,它是唯一沒有固定大小的原始類型??梢杂米址鎯?0 或更多的 Unicode 字符,有 16 位整數(shù)表示。
字符串字面量是由雙引號(")或單引號(')聲明的。而Java則是用雙引號聲明字符串,用單引號聲明字符。但是由于ECMAScript沒有字符類型,所以可使用這兩種表示法中的任何一種。

var sColor1 = "red";    // 使用雙引號定義字符串
var sColor2 = 'red';    // 使用單引號定義字符串
alert(typeof sColor1);  // 輸出"string"
alert(typeof sColor2);  // 輸出"string"

<br />

類型轉換

轉換成字符串

ECMAScript 的 Boolean、Number和String的原始值(下面會介紹引用值)的有趣之處在于它們是偽對象,這意味著它們實際上具有屬性和方法。
這3種主要的原始類型都有toString()方法,可以把它們的值轉換成字符串。
提示:您也許會問,“字符串還有toString()方法嗎,這不是多余嗎?”是的,的確如此,不過ECMAScript定義所有對象都有toString()方法,無論它是偽對象,還是真對象。因為 String 類型屬于偽對象,所以它一定有toString()方法。
Boolean 類型的 toString() 方法只是輸出 "true" 或 "false",結果由變量的值決定:

var bFound = false;
alert(bFound.toString());   //輸出 "false"

Number 類型的 toString() 方法比較特殊,它有兩種模式,即默認模式和基模式。
在默認模式中,無論最初采用什么表示法聲明數(shù)字,Number 類型的 toString() 方法返回的都是數(shù)字的十進制表示。

var iNum1 = 10;
var iNum2 = 10.0;
alert(iNum1.toString());    //輸出 "10"
alert(iNum2.toString());    //輸出 "10"

采用 Number 類型的 toString() 方法的基模式,可以用不同的基輸出數(shù)字,例如二進制的基是 2,八進制的基是 8,十六進制的基是 16。

var iNum = 10;
alert(iNum.toString(2));    //輸出 "1010"
alert(iNum.toString(8));    //輸出 "12"
alert(iNum.toString(16));   //輸出 "A"

<br />

轉換成數(shù)字

ECMAScript 提供了兩種把非數(shù)字的原始值轉換成數(shù)字的方法,即 parseInt() 和 parseFloat()。

parseInt()方法

從位置 0 開始查看每個字符,直到找到第一個非法的字符為止,然后把該字符之前的字符串轉換成整數(shù)。 8進制的前導符"0"和16進制的"0x"被認為是合法的字符。

  • 一般轉換規(guī)則:
var iNum1 = parseInt("123");        // 10進制,返回 123
var iNum1 = parseInt("010");        // 8進制,返回 8
var iNum1 = parseInt("0xA");        // 16進制,返回 10
var iNum1 = parseInt("56.9");       // 浮點數(shù),返回 56
var iNum1 = parseInt("12345red");   // 數(shù)字與字符組合,返回 12345
var iNum1 = parseInt("red");        // 字符串,返回 NaN

parseInt() 方法還有基模式,可以把二進制、八進制、十六進制或其他任何進制的字符串轉換成整數(shù)。

var iNum1 = parseInt("10", 2);  // 返回 2
var iNum2 = parseInt("10", 8);  // 返回 8
var iNum3 = parseInt("10", 10); // 返回 10

parseFloat()方法

parseFloat() 方法與 parseInt() 方法的處理方式相似,從位置 0 開始查看每個字符,直到找到第一個非有效的字符為止,然后把該字符之前的字符串轉換成整數(shù)。
不過,對于這個方法來說,第一個出現(xiàn)的小數(shù)點是有效字符。如果有兩個小數(shù)點,第二個小數(shù)點將被看作無效的。parseFloat() 會把這個小數(shù)點之前的字符轉換成數(shù)字。這意味著字符串 "11.22.33" 將被解析成 11.22。
使用 parseFloat() 方法的另一不同之處在于,字符串必須以十進制形式表示浮點數(shù),而不是用八進制或十六進制。該方法會忽略前導 0,所以八進制數(shù) 0102 將被解析為 102。對于十六進制數(shù) 0xA,該方法將返回 0,因為在浮點數(shù)中,x 不是有效字符。

var fNum3 = parseFloat("11.2");     // 返回 11.2
var fNum1 = parseFloat("12345red"); // 返回 12345
var fNum5 = parseFloat("0102");     // 返回 102
var fNum2 = parseFloat("0xA");      // 返回 0
var fNum4 = parseFloat("11.22.33"); // 返回 11.22
var fNum1 = parseFloat("red");      // 返回 NaN

<br />

強類型轉換(type casting)

ECMAScript 中可用的 3 種強制類型轉換如下:

  • Boolean(value) - 把給定的值轉換成 Boolean 型;
  • Number(value) - 把給定的值轉換成數(shù)字(可以是整數(shù)或浮點數(shù));
  • String(value) - 把給定的值轉換成字符串;

Boolean()函數(shù)

當要轉換的值是至少有一個字符的字符串、非 0 數(shù)字或對象時,Boolean() 函數(shù)將返回 true。如果該值是空字符串、數(shù)字 0、undefined 或 null,它將返回 false。

var b1 = Boolean("");           // false - 空字符串
var b2 = Boolean("hello");      // true -  非空字符串

var b1 = Boolean(0);            // false - 零
var b1 = Boolean(50);           // true -  非零數(shù)字

var b1 = Boolean(null);         // false - null
var b1 = Boolean(undefined);    // false - undefined
var b1 = Boolean(new object()); // true -  對象

<br />

Number()函數(shù)

Number() 函數(shù)的強制類型轉換與 parseInt() 和 parseFloat() 方法的處理方式相似,只是它轉換的是整個值,而不是部分值。
parseInt() 和 parseFloat() 方法只轉換第一個無效字符之前的字符串,因此 "1.2.3" 將分別被轉換為 "1" 和 "1.2"。
用 Number() 進行強制類型轉換,"1.2.3" 將返回 NaN,因為整個字符串值不能轉換成數(shù)字。如果字符串值能被完整地轉換,Number() 將判斷是調(diào)用 parseInt() 方法還是 parseFloat() 方法。

var b1 = Number("12");          // 12
var b2 = Number("1.2");         // 1.2
var b2 = Number("1.2.3");       // NaN

var b1 = Number(false);         // 0
var b1 = Number(true);          // 1

var b1 = Number(null);          // 0,注意與undefined的區(qū)別
var b1 = Number(undefined);     // NaN
var b1 = Boolean(new object()); // NaN

<br />

String()函數(shù)

最后一種強制類型轉換方法 String() 是最簡單的,因為它可把任何值轉換成字符串。
要執(zhí)行這種強制類型轉換,只需要調(diào)用作為參數(shù)傳遞進來的值的 toString() 方法。
強制轉換成字符串和調(diào)用 toString() 方法的唯一不同之處在于,對 null 和 undefined 值強制類型轉換可以生成字符串而不引發(fā)錯誤:

var s1 = String(null);      // String()方法可正常轉換,返回"null"
var s2 = String(undefined); // String()方法可正常轉換,返回"undefined"

var oNull = null;
var s3 = oNull.toString();  // toString()方法會引發(fā)錯誤

<br />

引用類型

引用類型通常叫做類(class)。對應的對象即是引用值。
對象是由 new 運算符加上要實例化的對象的名字創(chuàng)建的。

var o = new Object(); // 創(chuàng)建一個對象(引用值)

<br />

Object對象

與Java中的java.lang.Object相似,ECMAScript中的所有對象都由這個對象繼承而來,Object對象中的所有屬性和方法都會出現(xiàn)在其他對象中。
Object 對象具有下列屬性:

  • constructor: 對創(chuàng)建對象的函數(shù)的引用(指針)。對于 Object 對象,該指針指向原始的 Object() 函數(shù)。
  • Prototype: 對該對象的對象原型的引用。對于所有的對象,它默認返回 Object 對象的一個實例。

Object 對象還具有幾個方法:

  • hasOwnProperty(property): 判斷對象是否有某個特定的屬性。必須用字符串指定該屬性。(例如,o.hasOwnProperty("name"))
  • IsPrototypeOf(object): 判斷該對象是否為另一個對象的原型。
  • PropertyIsEnumerable: 判斷給定的屬性是否可以用 for...in 語句進行枚舉。
  • ToString(): 返回對象的原始字符串表示。對于 Object 對象,ECMA-262 沒有定義這個值,所以不同的 ECMAScript 實現(xiàn)具有不同的值.
  • ValueOf(): 返回最適合該對象的原始值。對于許多對象,該方法返回的值都與 ToString() 的返回值相同。
    <br />

Boolean對象

Boolean對象是Boolean原始類型的引用類型。
要創(chuàng)建Boolean對象,只需要傳遞Boolean值作為參數(shù):

var oFalseObject = new Boolean(false);
var bResult = oFalseObject && true;     // 輸出 true !!!

在 Boolean 表達式中,所有對象都會被自動轉換為 true,所以 oFalseObject 的值是 true。然后 true 再與 true 進行 AND 操作,結果為 true。
注意:雖然你應該了解 Boolean 對象的可用性,不過最好還是使用Boolean原始值,避免發(fā)生這一節(jié)提到的問題。
<br />

Number對象

Number 對象是Number原始類型的引用類型。
要得到數(shù)字對象的 Number 原始值,只需要使用 valueOf() 方法:

var oNumberObject = new Number(68);
var iNumber = oNumberObject.valueOf();  // 返回Number的原始值

除了從 Object 對象繼承的標準方法外,Number 對象還有幾個處理數(shù)值的專用方法。

toFixed()方法

方法返回的是具有指定位數(shù)小數(shù)的數(shù)字的字符串表示。

var oNumberObject = new Number(68);
alert(oNumberObject.toFixed(2));        // 輸出 "68.00"

<br />

toExponential()方法

方法返回的是用科學計數(shù)法表示的數(shù)字的字符串形式。

var oNumberObject = new Number(68);
alert(oNumberObject.toExponential(1));  // 輸出 "6.8e+1"

<br />

toPrecision()方法

方法根據(jù)最有意義的形式來返回數(shù)字的預定形式或指數(shù)形式。它有一個參數(shù),即用于表示數(shù)的數(shù)字總數(shù)(不包括指數(shù))。

var oNumberObject = new Number(68);
alert(oNumberObject.toPrecision(1));  // 用1位數(shù)字表示數(shù)字68,輸出 "7e+1"
var oNumberObject = new Number(68);
alert(oNumberObject.toPrecision(2));  // 用2位數(shù)字表示數(shù)字68,輸出 "68"
var oNumberObject = new Number(68);
alert(oNumberObject.toPrecision(3));  // 用3位數(shù)字表示數(shù)字68,輸出 "68.0"

toFixed()、toExponential() 和 toPrecision() 方法都會進行舍入操作,以便用正確的小數(shù)位數(shù)正確地表示一個數(shù)。
提示:與Boolean對象相似,Number對象也很重要,不過應該少用這種對象,以避免潛在的問題。只要可能,都使用數(shù)字的原始表示法。
<br />

String對象

String 對象是String原始類型的引用類型。

length屬性(是屬性不是方法!)

它是字符串中的字符個數(shù)

var oStringObject = new String("hello world");
alert(oStringObject.length);                    // 輸出 "11"

注意,即使字符串包含雙字節(jié)的字符,每個字符也只算一個字符。
<br />

slice() & substring()

與 concat() 方法一樣,slice() 和 substring() 方法都 不改變String對象自身的值。只返回原始的String值。
這兩種方法返回的都是要處理的字符串的子串,都接受一個或兩個參數(shù)。第一個參數(shù)是要獲取的子串的起始位置,第二個參數(shù)(如果使用的話)是要獲取子串終止前的位置(也就是說,獲取終止位置處的字符不包括在返回的值內(nèi))。如果省略第二個參數(shù),終止位就默認為字符串的長度。

var oStringObject = new String("hello world");
alert(oStringObject.slice("3"));                // 輸出 "lo world"
alert(oStringObject.substring("3"));            // 輸出 "lo world"
alert(oStringObject.slice("3", "7"));           // 輸出 "lo w"
alert(oStringObject.substring("3", "7"));       // 輸出 "lo w"

為什么有兩個功能完全相同的方法呢?事實上,這兩個方法并不完全相同,不過只在參數(shù)為負數(shù)時,它們處理參數(shù)的方式才稍有不同。

var oStringObject = new String("hello world");
alert(oStringObject.slice("-3"));               // 輸出 "rld"
alert(oStringObject.substring("-3"));           // 輸出 "hello world"

alert(oStringObject.slice("3, -4"));            // 輸出 "lo w"
alert(oStringObject.substring("3, -4"));        // 輸出 "hel"

slice方法接收負值時,將其理解為倒著數(shù)的字符索引;而substring方法將負值直接解析成0(即第1個字符的索引)。
使用參數(shù) 3 和 -4 時,slice() 將被轉換成 slice(3, 7),返回 "lo w"。而 substring() 方法則將兩個參數(shù)解釋為 substring(3, 0),實際上即 substring(0, 3),因為 substring() 總把較小的數(shù)字作為起始位,較大的數(shù)字作為終止位。因此,substring("3, -4") 返回的是 "hel"。
<br />

instanceof運算符

在使用 typeof 運算符時采用引用類型存儲值會出現(xiàn)一個問題,無論引用的是什么類型的對象,它都返回 "object"。
instanceof 運算符與 typeof 運算符相似,用于識別正在處理的對象的類型。與 typeof 方法不同的是,instanceof 方法要求開發(fā)者明確地確認對象為某特定類型。例如:

var oStringObject = new String("hello world");
alert(oStringObject instanceof String);         // 輸出 "true"

<br />

更多請參考:W3School

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容