成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

《 JavaScript程序設(shè)計(jì)》—— 第四章 表達(dá)式語句

solocoder / 3542人閱讀

摘要:每個(gè)候選項(xiàng)都是大括號中的語句序列。短路運(yùn)算符有一個(gè)很重要的功能它們并不真的需要布爾值操作數(shù),注意換句話說,不會(huì)將數(shù)字轉(zhuǎn)換為布爾值。練習(xí)對表達(dá)式求值。首先對求值,轉(zhuǎn)換為繼續(xù)對右邊表達(dá)式求值,為,造成短路,不對進(jìn)行計(jì)算,返回對表達(dá)式求值。

4.1 聲明語句

聲明語句也叫變量語句,這種語句會(huì)創(chuàng)建新變量??梢栽诼暶髯兞繒r(shí)給出初始值,如果沒有明確給出,變量的值就是undefined。

        var count = 0;
        var dogs = ["Sparky","Spot","Spike"];
        var response;
        var melta = {latitude:35.8,longitude:14.6};
        var finished = false;
        var winner = null;

這段腳本明確給出了幾個(gè)變量的初始值,事實(shí)上,除response之外都有了初始值。這時(shí)候,變量response的值就是undefined
可以在一個(gè)語句中聲明多個(gè)變量,可以給部分變量賦初始值。

        var start = 0,finish = 72,input,output = [];

這個(gè)語句會(huì)將input初始化為undefined值。

4.2 表達(dá)式語句

表達(dá)式語句對表達(dá)式求值但,忽略得到的值。這聽起來有點(diǎn)傻,因?yàn)榭梢跃帉懗鲱愃朴谙旅娴臒o用腳本;

        2+2;                    // 計(jì)算2+2,僅此而已
        "hello";                // 也有效,但完全沒用
        Math.sqrt(100);         // 完成計(jì)算,也僅此而已
        "a".toLowerCase();      // 得到一個(gè)新字符串,但忽略它

但是可以借助表達(dá)式的副作用來創(chuàng)建有用的語句,所謂"副作用",就是一些操作,可以生成可見結(jié)果、改變變量或?qū)ο髮傩灾斜4娴闹?,或者修改對象的結(jié)構(gòu)等。之前的delete運(yùn)算符與alert和賦值一樣,都會(huì)產(chǎn)生副作用

        var x = 2;                // 聲明x,初始化為2
        alert(x);                // 顯示2
        alert(10*x);            // 顯示20
        var y;                    // 聲明y,但不明確賦值
        alert(y);                // 顯示undefined

記住,變量聲明和賦值就是簡單地把一個(gè)值放到一個(gè)變量里,僅此而已。除此之外,沒有任何其他后果,比如不會(huì)設(shè)定變量與變量之間的關(guān)系。在前面的腳本中,聲明var z = y不會(huì)讓z和y成為同一個(gè)變量,也不會(huì)要求它們在之后始保存相同的值。這個(gè)語句意思僅僅是"新建一個(gè)變量z,讓它的初始值等于y的當(dāng)前值"。之后再給y重新賦一個(gè)新值時(shí),z的值不會(huì)變。

4.3 條件執(zhí)行

JavaScript提供了一些語句和幾個(gè)運(yùn)算符,可以讓我們編寫的腳本在特定條件下執(zhí)行一操作,在不同條件下則執(zhí)行另一組操作。

4.3.1 if語句

if語句會(huì)根據(jù)你提供的條件,最多執(zhí)行許多候選操作中的一種。這個(gè)語句的最一般形式是有一個(gè)if部分,0個(gè)或多個(gè)else if部分,還可根據(jù)需要帶有else部分。每個(gè)候選項(xiàng)都是大括號中的語句序列。這些條件會(huì)自上而下一次評估。只要一個(gè)條件為真,就會(huì)執(zhí)行它對應(yīng)的候選操作,然后結(jié)束整個(gè)if語句。

        var score = Math.round(Math.random()*100);
        if (score>=90) {
            grade = "A";
        } else if (score>=80) {
            grade = "B";
        } else if (score>=70) {
            grade = "C";
        } else if (score>=60) {
            grade = "D";
        } else {
            grade = "F";
        };
        alert(score+" is a "+grade)

下圖用一種UMKL(Unified Modeling Language,統(tǒng)一建模語言)活動(dòng)圖解讀了上述語句。UML是一種非常流行的軟件系統(tǒng)可視化語言。這張圖傳達(dá)的事實(shí)就是:會(huì)逐個(gè)檢測每個(gè)條件,一旦發(fā)現(xiàn)一個(gè)條件成立,就不再進(jìn)行測試。

練習(xí)

編寫一個(gè)if語句,當(dāng)變量s沒有包含長度為16的字符串時(shí),提示一條消息(注意,這個(gè)語句沒有else ifelse部分)

        var s = prompt("Enter a something");
        if (s.length!==16) {
            alert("string length isn"t 16")
        };

編寫一個(gè)if語句,檢查變量x的值,(1)如果x>0,則將它加到數(shù)組變量values的末尾;(2)如果x<0,則將它加到values的前面;(3)如果x===0,則遞增變量zeroCount;(4)柔則,什么也不做。

        var values = [];
        var zeroCount = 0;
        var x = Number(prompt("Enter a number"));
        if (x>0) {
            values.push(x);
        } else if (x<0) {
            values.unshift(x);
        } else if (x===0) {
            zeroCount++;
        };
4.3.2 ?:條件表達(dá)式

有時(shí)你可能更喜歡使用條件表達(dá)式,而不是if語句。條件表達(dá)式就是"x?y:z",當(dāng)x為真時(shí),表達(dá)式的結(jié)果為y,當(dāng)x為假時(shí),表達(dá)式的結(jié)果為z。

        if (latitude>=0) {
            hemisphere = "north";
        } else {
            hemisphere = "south";
        }
        // 寫為:
        hemisphere = (latitude>=0) ? "north" : "south";

條件表達(dá)式有時(shí)會(huì)用在構(gòu)建字符串的表達(dá)式中,如下(這里的present假定是一個(gè)保存布爾值的變量:)

        var notice = "She is "+(present? "" : "n"t")+" here.";
4.3.3 switch語句

另一種條件語句 —— switch語句,將一個(gè)值一系列case進(jìn)行比較,知道找出一個(gè)與它的值相等(===)的case,然后從該處開始執(zhí)行語句??梢愿鶕?jù)需要包含一個(gè)default case,它會(huì)匹配所有值。

        switch (direction.toLowerCase()){
            case "north" : row -= 1;
                break;
            case "south" : row += 1;
                break;
            case "east"  : column += 1;
                break;
            case "west"  : column -= 1;
                break;
            default: alert("Illegal direction");
        }

break語句會(huì)終止整個(gè)switch語句。每種case都以一個(gè)break結(jié)束,這是一種很好的做法否則,執(zhí)行會(huì)"直落"到下一個(gè)case(不會(huì)再與剩下的case表達(dá)式進(jìn)行比較)。例如,上面的腳本我們省略了break,而且方向是"east",會(huì)發(fā)生什么情況呢?column中的值會(huì)被遞增,然后遞減,然后彈出一個(gè)提示框,告訴你"east"不是一個(gè)合法方向。

有時(shí),"直落"正是我們想要的。假定在一群參加競賽的人中,每個(gè)人都獲得一個(gè)證書,但達(dá)到一級獎(jiǎng)勵(lì)的人還會(huì)得到一個(gè)背包,達(dá)到二級獎(jiǎng)勵(lì)的人還會(huì)得到一次滑雪度假,而達(dá)到三級獎(jiǎng)勵(lì)的人還會(huì)獎(jiǎng)勵(lì)一倆汽車。這種情況就可以使用沒有break語句的編碼。

        /*
         * 這個(gè)腳本會(huì)為一個(gè)給定獎(jiǎng)勵(lì)級別生別一組獎(jiǎng)勵(lì)
         * 每個(gè)獎(jiǎng)勵(lì)級別的參賽者會(huì)得到該級獎(jiǎng)勵(lì)和所有
         * 低級獎(jiǎng)勵(lì)。它使用了一種很丑陋的switch語句
         * 形式,其中的各個(gè)case之間沒有相互距離。
        */
        
        var level = +prompt("Enter your prize level,1-3");
        var prizes = [];
        switch (level){
            case 3 : prizes.push("car");
            case 2 : prizes.push("ski vacation");
            case 1 : prizes.push("backpack");
            default: prizes.push("certificate");
        }
        alert(prizes);

一個(gè)具有直落效果的switch語句的活動(dòng)圖

像這樣的計(jì)算很少會(huì)在現(xiàn)實(shí)中發(fā)生所以一般來說,還是避免使用那些不以break(或其他某一中斷語句)結(jié)束的case,以防與switch更常見的形式混淆。事實(shí)上,之前介紹的JSLint代碼質(zhì)量檢查工具就是將"直落"看作錯(cuò)誤!我們總能為直落switch找出替代方法。

4.3.4 用查詢避免條件代碼

來看一種情景,至少對于許多程序員新手來說,這種情景似乎是需要使用if語句,?:運(yùn)算符或者switch語句。假定有一個(gè)變量state,保存德國一個(gè)州名,我們希望將這個(gè)州的首府名賦值給變量capital,如果不能識別州名,則為其賦值undefined。

        // 丑陋的代碼 —— 不要使用這一代碼
        if (state === "Baden-Wurttemberg") {
            capital = "Strttgart";
        } else if (state = "Bayern") {
            capital = "Munchen";
        } else if (state = "Berlin") {
            capital = "Berlin";
        } else if (state = "Potsdam") {
            capital = "Potsdam";
        } else if (state = "Bremen") {
            capital = "Bremen";
        } else if (state = "Hamburg") {
            capital = "Hessen";
        } else {
            capital = undefined;
        }

此代碼對每個(gè)州都重復(fù)兩段內(nèi)容:state ===capital = 。switch語句可以消除前者,但必須為每個(gè)州都增加一個(gè)break —— 沒有實(shí)質(zhì)性的改進(jìn)。

        // 丑陋的代碼 —— 不要使用這一代碼
        switch (state){
            case "Baden-Wurttemberg" : capital = "Stuttgart";
                break;
            case "Bayern" : capital = "Munchen";
                break;
            case "Berlin" : capital = "Berlin";
                break;
            case "Brandenburg" : capital = "Potsdam";
                break;
            case "Bremen" : capital = "Bremen";
                break;
            case "Hamburg" : capital = "Hambrug";
                break;
            case "Hessen" : capital = "Wiesbaden"
                break;
            default:capital = undefined;
        }

我們將在第三次嘗試中使用的條件表達(dá)式可以消除賦值的重復(fù)作用,但無法消除相等檢測中的重復(fù)。

    capital = 
          (state === "Baden-Wurttemberg") ? "Stuttgart"
        : (state === "Bayern") ? "Munchen"
        : (state === "Berlin") ? "Berlin"
        : (state === "Brandenburg") ? "Potsdam"
        : (state === "Bremen") ? "Bremen"
        : (state === "Hamburg") ? "Hamburg"
        : (state === "Hessen") ? "Wiesbaden"
        : undefined;

我們不能將所有重復(fù)片段排除在外,這一定意味著存在一種更好的方法來查找首府,事實(shí)上也的確存在。如果剔除了所有關(guān)于測試與賦值的內(nèi)容,還剩下什么呢?就是州和首府!我們并不需要什么精確的計(jì)算來將州和首府關(guān)聯(lián)在一起,可以在數(shù)據(jù)而非代碼中定義這種關(guān)系。我們所需要的就是一個(gè)簡單對象。

        var CAPITALS = {
            "Baden-Wurttemberg" : "Stuttgart",
            "Bayern" : "Munchen",
            "Brandenburg" : "Potsdam",
            "Bremen" : "Bremen",
            "Hamburg" : "Hamburg",
            "Hessen" : "Wiesbaden"
        };

現(xiàn)在,只需寫出:

        capital = CAPITALS[state];

就能獲得變量state中所包含州的首府??梢哉J(rèn)為這一代碼是在一個(gè)由州及首府組成的表格中查詢首府。在這樣使用一個(gè)對象時(shí),就說它是一個(gè)查詢表、一個(gè)詞典、一個(gè)映射、一個(gè)關(guān)聯(lián)數(shù)組、或一個(gè)數(shù)列。查詢表通常是將鍵映射到值key = value)。這里的州是鍵,首府是值。在適用時(shí),查詢代碼要優(yōu)于條件代碼,原因有如下幾個(gè)。

沒有冗余的代碼片段,是腳本更短、更易于理解。

州和首府的顯示位置緊挨在一起,更容易"看出"它們之間的關(guān)聯(lián)。

代碼(查詢)和數(shù)據(jù)(查詢表)在本質(zhì)上是不同的東西,不應(yīng)當(dāng)混放在一起。

JavaScript引擎執(zhí)行查詢的速度要遠(yuǎn)快與條件代碼。

還有一個(gè)例子,我們使用詞典來關(guān)聯(lián)手機(jī)鍵盤上的數(shù)字和字母。
為了將帶有字母的電話號碼轉(zhuǎn)換為號碼,我們可以使用:

        var LETTER_TO_NUMBER = {
            A:2,
            B:2,
            C:2,
            D:3,
            E:3,
            F:3,
            G:4,
            H:4,
            I:4,
            J:5,
            K:5,
            L:5,
            M:6,
            N:6,
            O:6,
            P:7,
            Q:7,
            R:7,
            S:7,
            T:8,
            U:8,
            V:8,
            W:9,
            X:9,
            Y:9,
            Z:9
        };

比如LETTER TO NUMBER["C"] === 2。能不能在另一個(gè)方向上使用這個(gè)映射呢?單個(gè)數(shù)字可以映射為多個(gè)字母,所以我們將使用字符串:

        var NUMBER_TO_LETTER = {
            2:"ABC",
            3:"DEF",
            4:"GHI",
            5:"JKL",
            6:"MNO",
            7:"PQRS",
            8:"TUV",
            9:"WXYZ"
        };

這里,我們說:“給定一個(gè)數(shù)字n,NUMBER TO LETTER[n]”的值是一個(gè)字符串,其中包含了與鍵盤上的n相關(guān)聯(lián)的所有字母(而且也只有這些字母)?!痹诤罄m(xù)介紹處理整個(gè)手機(jī)號碼腳本時(shí)間,將會(huì)用到這些詞典中的第一個(gè)。

練習(xí)

用你自己的語言,說明可以用查詢代替條件代碼結(jié)構(gòu)的情景(為之前的分?jǐn)?shù)與成績示例使用查詢策略)

    var score = {
    100:"A",
    99:"A",
    98:"A",
    80:"B",
    85:"B",
    89:"B",
};
alert(score[100])

情景:查詢電話歸屬地、郵編。元素周期表......

假定你注意到某一代碼中存在表達(dá)式CAPITALS[Saarland]。幾乎可以肯定它有什么錯(cuò)誤?

可能存在語法錯(cuò)誤,方括號運(yùn)算符中如果不是變量,必須用引號括起

4.3.5 短路執(zhí)行

之前的布爾值一章中,如果x和y都是布爾值,則AND-ALSO和OR-ELSE運(yùn)算符具有以下特性:

當(dāng)且僅當(dāng)xy為真(或均為假)時(shí),x || y為真

當(dāng)且僅當(dāng)xy均為真時(shí),x && y為真

        if (t<0 && t>100) {
            /**執(zhí)行某些操作**/
        }
        // 與下面代碼的含義完全相同
        if (t<0) {
            if (t>100) {
                /**執(zhí)行某些操作**/
            }
        }

如果第一部分的求值已經(jīng)獲得了足夠多的信息,那就講第二部分的求值短路,也就是跳過。
我們現(xiàn)在明白AND-ALSO和OR-ELSE名字的緣由了。

x and also y就是說:若(if)x為真,則(then)(且僅在此時(shí))去查看y是否也(also)為真。

x or else y 就是說:若(if)x為真,那很好;否則(else)必須去查看y是否為真。

第二部分根據(jù)條件決定是否求值。

短路運(yùn)算符有一個(gè)很重要的功能:它們并不真的需要布爾值操作數(shù),注意:
        alert(27 && 52);        // 52
        alert(0 && 52);            // 0
        alert(27 || 52);        // 27
        alert(0 || 52);            // 52

換句話說,JavaScript不會(huì)將數(shù)字轉(zhuǎn)換為布爾值。

為計(jì)算x && y的值,JavaScript首先對x求值。如果x為假(false或可以轉(zhuǎn)換為false),則整個(gè)表達(dá)式得出x的值(不再計(jì)算y。否則整個(gè)表達(dá)式得出y的值。

為計(jì)算x || y的值,JavaScript首先對x求值。如果x為真(true或可以轉(zhuǎn)換為true),則整個(gè)表達(dá)式得出x的值(不再計(jì)算y。否則,整個(gè)表達(dá)式得出y的值。

利用這一行為,可以編寫一些小巧的代碼。假定有一個(gè)變量favoriteColor,我們知道,如果你有最喜歡的顏色,這個(gè)變量就包含了這種顏色的名稱,如果沒有最愛的顏色,那它的值就是undefined。如果有喜歡的顏色,就用這種顏色為汽車噴漆,如果沒有,則噴為黑色;

        car.color = favoriteColor || "black";

這一行代碼是有效的,因?yàn)?b>favoriteColor中包含了一個(gè)非空字符串,它為真,所以會(huì)為其指定car的顏色。如果favoriteColorundefined為假),則根據(jù)定義,||表達(dá)式的值就是它的第二個(gè)(右側(cè))操作數(shù),也就是黑色。

練習(xí)

對表達(dá)式 3 && "xyz" || null求值。

首先對3 && "xyz"求值,3轉(zhuǎn)換為true,繼續(xù)對右邊表達(dá)式求值,為true,造成 ||短路,不對null進(jìn)行計(jì)算,返回"xyz"

對表達(dá)式3 && "" || null求值。

首先對3 && ""求值計(jì)算,空字符串轉(zhuǎn)換為false,而因||需要,繼續(xù)對右邊表達(dá)式求值,返回null

判斷正誤:對于變量xy,x && y總是等同于x ? y : x

正確

首先對x求值,判斷是否短路,x為真,求值yx為假,那只有x已求值

判斷正誤:對于變量xyx || y總是等同于x ? x : y、

正確

首先對x求值,判斷是否短路,x為真,短路并返回,x為假,繼續(xù)求值y

4.4 迭代

上一節(jié)研究了不同情況下做不同事情的方法?,F(xiàn)在來看一遍又一遍地重復(fù)同一事情的方法。

4.4.1 whiledo-while語句

JavaScript的while語句會(huì)在條件為真時(shí)重復(fù)執(zhí)行代碼。下面的例子要求用戶輸入一個(gè)恰有五個(gè)字符的字符串,并一直詢問,知道用戶遵守指令為止。當(dāng)用戶輸入不滿足要求時(shí),腳本會(huì)計(jì)算嘗試次數(shù)(并重復(fù)提示)。只有在輸入了可接受的字符串時(shí),while語句才會(huì)結(jié)束。

        var numberOfTries = 1;
        while (prompt("Enter a 5-charater string").length !== 5){
            numberOfTries += 1;
        }
        if (numberOfTries>1) {
            alert("Took you "+numberOfTries+" tries to get this right");
        }

while語句的一般形式為:

while (test) { stmts }

首先執(zhí)行第一個(gè)test,如果它為真,則執(zhí)行循環(huán)體,重復(fù)整個(gè)語句。這就是說,條件測試出現(xiàn)在循環(huán)體之前,循環(huán)體可能一次也不會(huì)執(zhí)行。而在do-while語句中國,循環(huán)體至少會(huì)執(zhí)行一次。一般形式為:

do {stmts} while (test)

可以用do-while語句重寫以上腳本:

        var numberOfTries = 0;
        do {
            var input = prompt("Enter a 5-character string");
            numberOfTries++;
        } while (input.length!==5);
        if (numberOfTries>1) {
            alert("Took you "+numberOfTries+" tries to get this right");
        }

4.2.2 for語句

第二種循環(huán) —— for語句,也就是在條件為真時(shí)一直循環(huán),但它通常用于迭代遍歷一個(gè)固定的項(xiàng)目集,比如一個(gè)數(shù)值范圍、一個(gè)字符串中的字符、一個(gè)數(shù)組的索引、一個(gè)對象鏈,等等。這個(gè)語句一般形式是:

        for (init ; test ; each) {stmts}

JavaScript引擎首先運(yùn)行init代碼,然后,只要test為真,則運(yùn)行循環(huán)體,然后運(yùn)行each。init部分通常會(huì)聲明一或多個(gè)變量(但并非總是如此)。

        // 顯示4,6,8,10,...,20為偶數(shù)
        for (var Number=4;Number<=20;Number+=2) {
            alert(Number+" is even ")
        }

這里number被初始化為4,而且因?yàn)樗∮诘扔?0,所以將提示"4 is even",然后將number直接設(shè)置為6,接下來將顯示"6 is even",number變?yōu)?。最后顯示20,因?yàn)樽詈髇umber將跳到22,條件為false。
在處理數(shù)組時(shí)會(huì)使用for語句。下面例子中,處理一個(gè)單詞列表,也就是字符串words[0]、words[1]、words[2],等等。如何"逐步遍歷"這個(gè)列表呢?可以創(chuàng)建一個(gè)變量i,它會(huì)在每次的迭代中遞增1.

        // 顯示一個(gè)字符串,又每個(gè)數(shù)組項(xiàng)目的首個(gè)字母組成
        var words = ["as","far","as","i","know"];
        var result = "";
        for (var i=0;i

下面是一個(gè)另一個(gè)與數(shù)組有關(guān)的例子,它演示了一種常見模式,用于檢查每個(gè)數(shù)組元素,看它是否滿足某一條件。 // 顯示一個(gè)數(shù)組中的0的個(gè)數(shù)

        var a = [7,3,0,0,9,-5,2,1,0,1,7];
        var numberOfZeros = 0;
        for (var i=0,n=a.length;i

注意這個(gè)示例還演示了如何在for循環(huán)的初始化部分聲明兩個(gè)變量。將n初始化為數(shù)組的長度,循環(huán)終止檢測變得簡單一點(diǎn)。
除了迭代數(shù)值范圍和數(shù)組元素之外,for語句還經(jīng)常用于迭代一個(gè)字符串中的各個(gè)字符。

如果字符是數(shù)字,則直接"將它傳送"給結(jié)果字符串

如果字符在A~Z之間,則查找對應(yīng)的手機(jī)鍵盤數(shù)字,并傳送該數(shù)字。

如果字符是其他內(nèi)容,則忽略它。

        var LETTER_TO_NUMBER = {A:2,B:2,C:2,D:3,E:3,F:3,G:4,H:4,I:4,J:5,K:5,L:5,M:6,N:6,O:6,P:7,Q:7,R:7,S:7,T:8,U:8,V:8,W:9,X:9,Y:9,Z:9};
        var phoneText = prompt("Enter a phone number (letters permitted)").toUpperCase(); 
        var result = "";
        for (var i=0;i

在迭代另一類序列時(shí)也經(jīng)??吹絝or循環(huán):對象的鏈接結(jié)構(gòu)

        var scores = {
            score:29,
            next:{
                score:99,
                next:{
                    score:47,
                    next:null
                }
            }
        };
        var total = 0;
        for (var p=scores;p!=null;p=p.next) {
            total += p.score;
        };
        alert(total);
      
變量p引用了對象scores,并將p.score屬性運(yùn)算后賦值給變量total,并且每次執(zhí)行完代碼塊后,p引用的對象的屬性變?yōu)?b>p.next.score,下一次就是p.netx.next.scorescores.next.scorescores.next.next.score

下一個(gè)例子,演示嵌套循環(huán)。

    var SIZE = 9    ;            
        document.write("")
        for (var i=1;i<=SIZE;i++) {
            document.write("")
            for (var j=1;j<=SIZE;j++) {
                document.write("");
            }
            document.write("")    
        }
        document.write("
"+i*j+"
")

練習(xí)

編寫一個(gè)for語句,顯示10,然后顯示9,以此類推,知道最后顯示0。

   for (var i=10;i>=0;i--) {
         console.log(i);
   }

    var i = 10;
    while (i!==-1){
        console.log(i);
        i--;
    }

編寫一個(gè)小腳本,計(jì)算從1至20(含)的整數(shù)乘積值。使用for語句。

        for (var i=1,n=1;i<21;i++) {
        n *= i;
        console.log(n);
        };    
                    

4.4.3 for-in語句

JavaScript包含一個(gè)迭代對象屬性名的語句。這門語言將這一操作稱為屬性名的枚舉。

    var dog = {
            name:"Lisichka",
            breed:"G-SHEP",
            birthday:"2011-12-01"
        };
        for (var p in dog) {
            alert(p)
        }
     // name breed birthday

這個(gè)腳本將生成三條提示:一個(gè)給出name,一個(gè)給出breed,一個(gè)給出birthday。這些屬性的出現(xiàn)順序是任意的。試試另一個(gè)對象:

        var colors = ["red","amber","green"];    
        for (var c in colors) {
            alert(c)
        }
        // 0 1 2

枚舉是對屬性名進(jìn)行的,不是針對值。變量colors引用的對象的屬性名是0、1、2和length。但是,在運(yùn)行這一代碼時(shí),你只會(huì)看到顯示了0,1,2。為什么沒有l(wèi)ength?
其實(shí),一個(gè)對象的每個(gè)屬性,除了擁有值以外,還有幾個(gè)特性(attribute)。

        // 特性                      在為真時(shí)的含義
        
        writable                    屬性的值可以修改
        enumerable                  這個(gè)屬性將出現(xiàn)在屬性的for-in枚舉中
        configurable                可以從其對象中刪除這個(gè)屬性,它的特性值是可以改變的

湊巧,數(shù)組的length屬性的enumerable特性被設(shè)置為false。由前面的例子知道,它的writable特性為true。

練習(xí)

修改與狗有關(guān)的小腳本,提示以下內(nèi)容:必須用for-in語句生成這些提示,并用object[property]符號提示屬性值。

    var dog = {name:"Lisichka",breed:"G-SHEP",birthday:"2011-12-01"};
    for (var i in dog) {
        document.write("The dog"s "+i+" is "+dog[i]+"
") } // dog[property]注意property是字符串類型,而不是變量。

4.5中斷

通常,語句都是按順序一次執(zhí)行一條。條件語句和迭代語句會(huì)稍微偏離這種有時(shí)被稱作直線式代碼的形式,但這種偏離是語句結(jié)構(gòu)本身決定的,很容易識別。但還四種語句的結(jié)構(gòu)化不是這么強(qiáng),他們對控制流的效果是中斷性的。有這些:

break,立即放棄執(zhí)行當(dāng)前正在執(zhí)行的switch或迭代語句;

continue,立即放棄一個(gè)迭代語句中當(dāng)前迭代的剩余部分;

return,立即放棄當(dāng)前執(zhí)行的函數(shù);

thorw,將在后面介紹;

4.5.1 breakcontinue

break語句將立即終止整個(gè)循環(huán)。在搜索數(shù)組(或?qū)ο箧湥?,這一語句特別有用,它會(huì)在你找到正在查找的內(nèi)容之后立即終止搜索。

        // 查找第一個(gè)偶數(shù)的索引位置
        for (var i=0;i

continue語句立即開始循環(huán)的下一次迭代,而不在完成當(dāng)前迭代。當(dāng)循環(huán)中的一些(而非全部)迭代生成有用信息時(shí),這一語句非常有用。continue語句就是說“嗨,這次迭代里沒有什么要做的事情了,我馬上要開始下一次迭代了”。

        // 計(jì)算一個(gè)數(shù)組中所有正數(shù)值之和
        var array = [-1,3,12,3,-23,-23,-2,0,1,-12];    
            if (array[i]<=0) {
                continue;    //    跳過非正數(shù)
            }
            sum += array[i];
        }
        alert("Sumof positives is "+sum)
這里接一個(gè)鏈接開源中國問題,是一個(gè)社友提的一個(gè)問題。

剛好我在MDN里找到了一些文檔MDN-JS-break語句

那位社友的問題在于,在while循環(huán)中,當(dāng)i=4時(shí),就continue跳過了自增操作,按照MDN的說法,它將回到條件繼續(xù)執(zhí)行,這便成了一個(gè)死循環(huán)。而在for循環(huán)就直接each更新表達(dá)式了。

接下來寫一個(gè)腳本:用戶輸入一個(gè)數(shù)字,判斷是否為質(zhì)數(shù)。

        var SmallLest = 2;
        var BigGest = 9E15;
        var n = prompt("輸入一個(gè)數(shù)字");
        
        var condition = isNaN(n) || n % 1 !== 0 || n < SmallLest || n > BigGest;
        if (condition) {
            alert("只能判斷2~9e15之間的整數(shù)");
        } else {
            var foundDivisor = "是";     // default,是質(zhì)數(shù)
            for (var k = 2,last = Math.sqrt(n);k <= last;k++) {
                if (n%k === 0) {        // 2 ~ Math.sqrt(n)之間任何一個(gè)數(shù)可以整除n,則不是質(zhì)數(shù)
                    foundDivisor = "不是";    
                    break;
                }
            }
        }
        alert(n+" 是否為質(zhì)數(shù)? "+" : "+foundDivisor);

最后一個(gè)關(guān)于break和continue的示例要研究一個(gè)問題:如何中斷外層循環(huán)?一種方法是對循環(huán)進(jìn)行標(biāo)記,然后在break語句中提及這個(gè)標(biāo)記。假定有一個(gè)對象紀(jì)錄了一組人選擇的彩票信息。

        var picks = {
            Alice:[4,52,9,1,30,2],
            Boris:[14,9,3,6,22,40],
            Chi:[51,53,48,21,17,8],
            Dinh:[1,2,3,4,5,6],
        };

另外,假定我們希望知道是否有人選擇了數(shù)字53。可以依次查看每個(gè)人選擇的數(shù)字,但只要找到53,就希望停止整個(gè)搜索,而不只是終止對當(dāng)前人員選擇數(shù)字的掃描。

        var picks = {
            Alice:[4,52,9,1,30,2],
            Boris:[14,9,3,6,22,40],
            Chi:[51,53,48,21,17,8],
            Dinh:[1,2,3,4,5,6],
        };
        var found = false;
        Search:for (var person in picks) {
            var choices = picks[person];
            for (var i=0;i
練習(xí)

重寫計(jì)算數(shù)組例子,改為使用break語句。

    // continue重寫:計(jì)算一個(gè)數(shù)組所有正數(shù)值之和
    var num = [1,3,4,-2,-12,-3,0,-3,-1];
    var sum = 0;
    for (var i=0;i

4.5.2 異常 有時(shí),運(yùn)行腳本會(huì)出現(xiàn)一些問題,可能是因?yàn)?strong>編碼錯(cuò)誤導(dǎo)致,如希望用乘法時(shí)卻編寫了加法。在這些情況下,腳本會(huì)一直運(yùn)行,但可能會(huì)給出錯(cuò)誤的結(jié)果。我們說這種腳本帶有bug。如果幸運(yùn)(居然叫幸運(yùn) - -)的話,還是能看到輸出結(jié)果,并會(huì)想到“這個(gè)結(jié)果不可能正確”,然后再去復(fù)查腳本,糾正錯(cuò)誤。 但有時(shí)運(yùn)行腳本,js遇到一個(gè)不能執(zhí)行的語句,或者不能求值的表達(dá)式。這是,腳本就不能繼續(xù)運(yùn)行了。引擎會(huì)拋出一個(gè)異常。如果沒有捕獲這個(gè)異常,腳本會(huì)立即停止運(yùn)行。我們稱之為崩潰
        alert("Welcome to my script");
        var message = printer+1;
        alert("The script is now ending")

在腳本運(yùn)行時(shí),出現(xiàn)第一次提示,但由于第二條語句需要一個(gè)未聲明變量printer的值,所以引擎會(huì)拋出異常。因?yàn)檫@一異常未被捕獲,所以整個(gè)腳本都將被放棄,最后一條提示永遠(yuǎn)不會(huì)被執(zhí)行。
除了使用未聲明變量這種情況外,還有哪些錯(cuò)誤會(huì)被看作錯(cuò)誤,并導(dǎo)致JavaScript拋出異常呢?

將數(shù)組長度設(shè)置為負(fù)值(RangeError

null值中讀取屬性(TypeError),因?yàn)橹挥袑ο髶碛袑傩?,JavaScript不能將null轉(zhuǎn)換為對象

執(zhí)行不合乎JavaScript語法的代碼,或?qū)ζ淝笾担?b>SyntaxError

        var a = [10,20,30];
        a.length = -5;            // "Uncaught RangeError: Invalid array length"
        
        var a = null;
        alert(a[3]);              // "Uncaught TypeError: Cannot read property "3" of null"

        alert(3/-)                // "Uncaught SyntaxError: Unexpected token )"

我們可以使用JavaScript的throw語句在自己的代碼中顯式的拋出異常??梢話伋鲎约合胍娜魏沃?;在下面的例子中,將拋出一個(gè)字符串:

        alert("Welcome to my script")
        throw "Ha ha ha";                // "Uncaught Ha ha ha"
        alert("You will never see this message")

我們提到,未捕獲的異常會(huì)導(dǎo)致腳本崩潰。要捕獲異常,可以使用try-catch語句。

        try {
            // 這是一個(gè)人為設(shè)計(jì)的示例,只說明了一個(gè)點(diǎn)
            alert("Welcome to my script");
            throw "Ha ha ha";
            alert("You will never see this script");
        } catch(e) {        
            alert("Caught : "+e);
        }

catch子句將一個(gè)變量(在本例中是e,這是一個(gè)相當(dāng)常見的選擇)初始化(或理解為將拋出的值賦值給e?)為被拋出的值。在實(shí)踐中,許多JavaScript程序員都需要拋出帶有各種屬性的對象,用以提供一些信息,用以提供一些信息,來為其描述拋出此異常的問題。例如:

        throw {reason:"class full",limit:20,date:"2012-12-22"}    
        // "Uncaught #"

異常為特定的編程問題提供了非常自然的解決方案。只要你意識到,利用你當(dāng)前擁有的數(shù)據(jù),一個(gè)計(jì)算不能正常進(jìn)行,那就應(yīng)該拋出異常。
和大多數(shù)程序設(shè)計(jì)特性一樣,異常也可能被濫用。下面這個(gè)腳本要求用戶從三扇分別標(biāo)有1,2,3的門中選擇一扇,并贏得藏在這扇門之后的獎(jiǎng)勵(lì)。

        // 如果沒有異常這將是更好的一個(gè)腳本
        try{
            var PRIZES = ["a new car","a broken stapler","a refrigerator"];
            var door = prompt("Enter a door number(1,2,or3)");
            var prize = PRIZES[door-1];
            alert("You have won "+prize.toUpperCase()+"!!");
        }catch(e){
            alert("Sorry, no such door.")
        }

如果用戶輸入除1,2,3之外的任何值,prize的值都將是undefined,對undefined調(diào)用toUpperCase將會(huì)拋出一個(gè)異常。這個(gè)異常被捕獲,并報(bào)告一條錯(cuò)誤。這一點(diǎn)很難通過研究代碼來發(fā)現(xiàn),因此,我們說這一腳本的邏輯有些費(fèi)解。他依賴于我們調(diào)用toUpperCase這一事實(shí),它與輸入無效門牌號的"問題"沒有什么關(guān)系!我們最后用一個(gè)簡單的if語句立即核實(shí)輸入。

練習(xí)

在JavaScript中除以零是否會(huì)拋出異常?

正數(shù)除0結(jié)果為Infinity,負(fù)數(shù)除0為-Infinity,0除以0為NaN。

重寫關(guān)于三個(gè)獎(jiǎng)勵(lì)的例子,不使用異常

    var PRIZES = ["a new car","a broken stapler","a refrigerator"];
    var door = prompt("Enter a door number(1,2,or3)");
    if (door==1 || door==2 || door==3) {
        alert("You have won "+PRIZES[door-1]+"!!");
    } else {
        alert("Please Input number 1,2or3")
    }
    

4.6 應(yīng)該避免的編碼風(fēng)格

我們已經(jīng)給出了以下一般形式的if、while、do-while、forfor-in語句

        if (test) { stmts }
        if (test) { stmts } else { stmts }
        if (test) { stmts } else if (test) { stmts }
        if (test) { stmts } else if (test) { stmts } else { stmts }
        
        while (test) { stmts }
        do { stmts } while (test);
        for (init;test;each) { stmts }
        for (var variable in object) { stmts } 

但事實(shí)上,上面使用語句序列(放在大括號)的位置,JavaScript都允許使用單個(gè)語句,下面這種寫法完全合法;

        if (count === 0) break;            
        
        // 或者
        
        if (count === 0)
            break;
            
        // 但不一定是最好的
        if (count === 0) {
            break;
        }

技術(shù)角度來說,任何一個(gè)放在大括號中的語句序列,其本身就是單條語句,成為塊語句。因此,在任何需要使用單條語句的地方都可以使用塊語句,但在實(shí)踐中,如果只是為了使用塊語句而使用塊語句,看起來會(huì)很傻。下面的腳本雖然有點(diǎn)傻,確實(shí)合法的;

        {{{{alert("Hello");}}}}
強(qiáng)烈建議遵循現(xiàn)在編碼約定,僅在if語句和迭代語句中使用塊語句。我們還強(qiáng)烈建議,應(yīng)當(dāng)始終使用塊語句來構(gòu)建這兩種語句,哪怕簡短形式可以減少鍵入工作。主要理由如下:

如果代碼中有些語句使用大括號,有些不使用,視覺上還會(huì)顯得有些不協(xié)調(diào)。當(dāng)在同一條if語句中,有些候選項(xiàng)帶有大括號,而另一些沒有時(shí),看起來尤其糟糕。缺乏一致性會(huì)讓代碼顯得不平衡、不整潔、需要花費(fèi)大量不必要的精力來領(lǐng)會(huì)其意圖。

如果缺少大括號,在修改代碼時(shí)更容易引入錯(cuò)誤。這里有一個(gè)示范。

        // 下面的腳本顯示數(shù)字0至9的平方
        for (var i=0;i<=10;i++) {
            alert(i+" squared is "+(i*i))
        };

程序員決定向循環(huán)體中添加一條語句,定義一個(gè)新變量,用來保存計(jì)算所得的平方,但卻忘了添加大括號

        for (var i=0;i<10;i++)
            var square = i * i;
            alert(i+" squared is "+square);

因?yàn)閒or循環(huán)體總是跟在控制表達(dá)式(放在小括號)之后的單條語句,所以這個(gè)腳本聲明了變量square,并重復(fù)為它賦值,最后一次為81.在for語句完成之后將出現(xiàn)提示。這時(shí),i的值為10,所以整個(gè)腳本給出單條提示:10 squared is 81,如果養(yǎng)成了符合語句中使用大括號的習(xí)慣,就永遠(yuǎn)不會(huì)犯這樣的錯(cuò)誤。

僅在if語句和迭代語句中使用塊語句,而且在這兩種語句中也總要使用塊語句

4.6.2 隱式分號

官方的JavaScript定義聲明,以下語句應(yīng)當(dāng)以分號(;)結(jié)束:變量聲明語句、表達(dá)式語句(包括賦值)、do-while語句、continue語句、break、return語句和throw語句。
但是這門語言的設(shè)計(jì)者允許程序員根據(jù)自己的一元省略語句末尾的分號,依靠JavaScript引擎來指出哪個(gè)地方應(yīng)當(dāng)有分號。遺憾的是,這一規(guī)則降低了我們將長語句分跨在多行代碼的靈活性。關(guān)于處理缺失分號的技巧細(xì)節(jié),可在官文中找到。

4.6.3 隱式聲明

當(dāng)你嘗試使用一個(gè)尚未聲明的變量時(shí),JavaScript引擎會(huì)拋出一個(gè)異常。但是,如果嘗試為一個(gè)未聲明的變量賦值,JavaScript會(huì)自動(dòng)為你聲明這個(gè)變量。

        // 假定變量next_song從來沒有聲明過
        next_song = "Purple Haze";

這個(gè)腳本不會(huì)拋出異常!許多人可能會(huì)說它應(yīng)該拋出異常的,許多專家認(rèn)為這個(gè)隱式聲明是語言設(shè)計(jì)缺陷。在賦值中意外地錯(cuò)誤拼寫一個(gè)變量名,會(huì)導(dǎo)致一個(gè)新變量的聲明,它不同與你本來想要賦值的變量。這個(gè)腳本將一直運(yùn)行,只到發(fā)生了某些“跑偏道路”的事情,是錯(cuò)誤很難查找。如果引擎在賦值時(shí)拋出異常,哪會(huì)更好一些,因?yàn)檫@個(gè)錯(cuò)誤的偵測就很容易了。
千萬不要依賴這一“功能“,JSLint很明智的將它的應(yīng)用報(bào)告為錯(cuò)誤。

4.6.4 遞增和遞減運(yùn)算符 這里可能用到優(yōu)先級表文檔:MDNJavaScript運(yùn)算符優(yōu)先級
        var x = 5;
        x++;                // x:6
        var y = x++;        // y:6 x:7    等號右結(jié)合
        var z = ++x;        // x:8 z:8
        var w = ++y + z++;    // y:7,w:15,z:9

等號結(jié)合性為右結(jié)合,故對=右側(cè)開始計(jì)算,最后賦值給變量x。x:5

后置遞增,先計(jì)算x(使用x),最后再進(jìn)行自增。x:6

出現(xiàn)的符號:=、后置++,后置自增無結(jié)合性,則先賦值(使用x)y:6,后自增x:7

出現(xiàn)的符號:=、++前置,兩者結(jié)合性都是右結(jié)合,則先自增x:8,后賦值z:8

出現(xiàn)的符號:=、前置++、+、后置++,加括號應(yīng)該是:(var w = ((++y) + z))++,先對前置自增運(yùn)算y:7,然先使用zy相加w:15,賦值給變量w,最后z才自增。所以y:7,w:15,z:9

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/91673.html

相關(guān)文章

  • JavaScript程序設(shè)計(jì)》—— 第四 達(dá)式語句章總結(jié)及練習(xí)

    摘要:語句包含聲明語句表達(dá)式語句條件語句循環(huán)語句和中斷語句我們可以將表達(dá)式的求值結(jié)果存儲在變量中,在將來提取它們。變量在使用之前應(yīng)當(dāng)聲明。程序員可以用語句顯式拋出異常。程序員需要保護(hù)自己總是明確使用分號來終結(jié)聲明語句。 主要總結(jié): 一個(gè)腳本就是一個(gè)語句序列,其中每條語句都會(huì)生成某一操作。JavaScript語句包含:聲明語句、表達(dá)式語句、條件語句、循環(huán)語句和中斷語句 我們可以將表達(dá)式的求...

    kaka 評論0 收藏0
  • 《你不知道的JavaScript》 (中) 閱讀摘要

    摘要:這時(shí)候控制臺看到的是對象的快照,然而點(diǎn)開看詳情的話是這段代碼在運(yùn)行的時(shí)候,瀏覽器可能會(huì)認(rèn)為需要把控制臺延遲到后臺,這種情況下,等到瀏覽器控制臺輸出對象內(nèi)容時(shí),可能已經(jīng)運(yùn)行,因此會(huì)在點(diǎn)開的時(shí)候顯示,這是的異步化造成的。 本書屬于基礎(chǔ)類書籍,會(huì)有比較多的基礎(chǔ)知識,所以這里僅記錄平常不怎么容易注意到的知識點(diǎn),不會(huì)全記,供大家和自己翻閱; 上中下三本的讀書筆記: 《你不知道的JavaScri...

    stackvoid 評論0 收藏0
  • 編寫javascript模板引擎的幾個(gè)步驟

    摘要:先推薦一個(gè)我自己寫的模板引擎,項(xiàng)目地址。下面就是總結(jié)的編寫模板引擎的幾個(gè)步驟例如一個(gè)模板為最終會(huì)編譯成為一個(gè)函數(shù)可以觀察到模板中的所有的變量名都被指定成了參數(shù)對象的屬性,并且該函數(shù)自始至終只做了一件事,就是構(gòu)建字符串,并將其返回。 showImg(https://segmentfault.com/img/remote/1460000007498588?w=300&h=113); 先推薦...

    xiaoxiaozi 評論0 收藏0
  • JavaScript 語言精粹》 讀書筆記 - 函數(shù)(二)

    摘要:對象被傳遞到從句中被捕獲。一些語言提供了尾遞歸優(yōu)化。這意味著如果一個(gè)函數(shù)返回自身遞歸調(diào)用的結(jié)果,那么調(diào)用的過程會(huì)被替換為一個(gè)循環(huán),可以顯著提高速度。構(gòu)建一個(gè)帶尾遞歸的函數(shù)。語言精粹讀書筆記函數(shù) 第四章 函數(shù) Functions (二) 參數(shù) arguments arguments數(shù)組: 函數(shù)可以通過此參數(shù)訪問所有它被調(diào)用時(shí)傳遞給它的參數(shù)列表,包括哪些沒有被分配給函數(shù)聲明時(shí)定義的形式參數(shù)...

    lufficc 評論0 收藏0
  • Javascript高級程序設(shè)計(jì) (第三版)》第四 變量、作用域和內(nèi)存問題

    摘要:在中雖然對象通過標(biāo)記清除的方式進(jìn)行垃圾收,但與對象卻是通過引用計(jì)數(shù)回收垃圾的,也就是說只要涉及及就會(huì)出現(xiàn)循環(huán)引用問題。如果垃圾收集例程回收的內(nèi)存分配量低于,則變量字面量和或數(shù)組元素的臨界值就會(huì)加倍。 只挑本人重要的寫(有夾雜其他補(bǔ)充) 基本類型和引用類型的值 描述:基本類型值指的是簡單的數(shù)據(jù)段,而引用類型值指那些可能由多個(gè)值構(gòu)成的對象。 動(dòng)態(tài)的屬性 引用類型的值,我們可以為其添加屬性和...

    szysky 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<