Javascript基础知识篇(6): 高质量开发准则(上)

  很多从事web开发的项目都离不开Javascript,我个人也在目前的公司中用到了很多,但是感觉还不是很到位,尤其是对Javascript的开发规范上。可能有些朋友要说,我实现一个简单的的功能(如两个数相加),需要遵守什么规范吗?我回答:需要。还有的会问:我的项目进度非常紧张,我有必要按照你说的规范一步一步来吗?我还是回答:需要。为什么呢?我认为与其在项目开发完毕的维护过程中,反复的调试还不如提前遵守开发规范,养成良好的编码习惯。结合我个人一直以来的职业习惯,我总结了以下几点,作为抛砖引玉。保持一致的编码风格具体做法:

(1).函数都必须拥有函数名(匿名函数除外),并以tab作为函数内容的缩进,函数体应包含在{}中(最好前{在函数名后)。

function sayHello() {//注意大括号的位置

    alert("Hello, Miracle");

    return true;

}

(2).函数体即使只有一句话(switch除外),也建议用{}封闭起来。这样有利于以后需求变更和维护,以防止新手忘记添加{}。

if(x == y) {

    alert("We have a match!");

} else {

    alert("We have a problem!");

}
switch (prompt("What is your favorite fruit?", "banana")) {

    case "banana":

        alert("Well done. Bananas are full of potassium.");

        break;

    case "mango":

        alert("Exotic and tasty!");

        break;

    default:

        alert("That's not to my taste, but keep it up to get your 5 days.");

        break;

}

(3).注重大小写。一般准则如下:

a.大多数的变量和函数均以小写开头,采用驼峰法进行书写。

b.构造函数和类(实质是函数)均以大写开头。

c.所有的常量都是由大写组成并以"_"相连。

// Calendar构造函数

var Calendar = function() {

    // 大写标识常量

    var DAYS_IN_ONE_WEEK = 7;

    // 小写代表函数及变量

    var count;

    function add() {

    }

    // 变量及函数遵守驼峰法书写

    var currentDate;

    function updateCurrentDate() {

    }

}

(4).使用有描述语义的变量,避免使用"魔幻数"(即变量直接由一些常量数字计算而成)。

// currentDate代表"当前日期",userName代表"用户名"

var currentDate;

function setCurrentDate() {

}

var userName;

function updateUserName() {

}

// daysInAYear和seatsOnThePlane均为"魔幻数"

var daysInAYear = 52 * 7; 

var seatsOnThePlane = 25 * 6; 

//改进方案

var WEEKS_IN_A_YEAR = 52;

var DAYS_IN_A_WEEK = 7;

var daysInAYear = WEEKS_IN_A_YEAR * DAYS_IN_A_WEEK; 

var SEAT_ROWS_ON_PLANE = 25;

var SEATS_PER_ROW = 6;

var seatsOnThePlane = SEAT_ROWS_ON_PLANE * SEATS_PER_ROW;

(5).函数功能尽量单一,不要融入太多"复杂"逻辑,尽量按职责拆分成对应的子函数。

// 反馈用户对水果的爱好程度

function feedbackOnUsersFavoriteFruit() {

    // 用户喜欢的水果

    var favoriteFruit = prompt("What is your favorite fruit?", "None");

    var score = 0;

    // 根据喜欢的水果计算得分

    switch (favoriteFruit.toLowerCase()) {

        case "banana":

            score = 6;

            break;

        case "apple":

            score = 4;

            break;

        default:

            break;

    }

    //根据分数来统计结果

    if (score > 5) {

        alert("You picked one of my favorites too!");

    } else if (score > 0) {

        alert("Credit for choosing a fruit, at least!");

    } else {

        alert("Not sure about your choice of fruit!");

    }

}

从上面的函数我们看出:包含获取喜欢水果和计算得分两项职责(实际项目中很可能是多项职责),我们在这里加以拆分。

// 用户喜欢的水果

function getFavoriteFruit() {

    return prompt("What is your favorite fruit?", "None");

}

// 根据喜欢的水果计算得分

function getFruitScore(fruit) {

    var score = 0;

    switch (fruit.toLowerCase()) {

        case "banana":

            score = 6;

            break;

        case "apple":

            score = 4;

            break;

        default:

            break;

    }

    return score;

}

//根据分数来统计结果

function getMessageByScore(score) {

    var message = "";

    if (score > 5) {

        message = "You picked one of my favorites too!";

    } else if (score > 0) {

        message = "Credit for choosing a fruit, at least!";

    } else {

        message = "Not sure about your choice of fruit!";

    }

    return message;

}

//最开始的函数

function feedbackOnUsersFavoriteFruit() { 

    var favoriteFruit = getFavoriteFruit();

    var score = getFruitScore(favoriteFruit);

    alert(getMessageByScore(score));

}

(6).习惯利用scriptDoc为函数添加注释。包含项目文件描述(包含功能、作者及版本等),函数功能描述(包含参数,返回值,示例程序)。

/**

* @projectDescription 该文件用于日期对象操作

*

* @author Miracle He [email protected]

* @version 1.0

*/



/** 传入一个数并计算它的平方并返回四舍五入后的整数结果

*

* Examples:

* square(2.5); => 6

* square(2); => 4

* @param {Float} 传入计算的数

* @return {Integer} 返回四舍五入后的整数结果

*/

function square(number) {

    return Math.round(number * number);

}

(7).习惯使用"//TODO:[功能描述]"标记未完成的功能。以便于团队其他成员进行添加。

function checkPasswordStrength(password) {

    // TODO: 请完成密码强度检查

    return true;

}

(8).避免编写解决"不存在"问题的代码。即在项目开发中仅仅只编写与你问题相关的代码,而不是刻意添加与问题不相关的代码。如果你认为所做的代码能达到通用的层次,则建议将它封装到工具类中,而不是散列到各个业务文件中。这样可以更好的维护代码和提高重用性。举个例子,有时做项目经常碰到在前端页面获取MasterPage或者UserControl中某一个子控件时,在外部文件中不能使用$("#<%=id.ClientID%>")的方式来获取控件,因此我封装了一个函数并放到oa.lib.js中(oa是项目名,可自定义)。

/*DOM*/

oa.prototype.dom = {

    //根据ID获取对应的元素

    get: function (id, tag) {

        if (tag == undefined) return $("#" + id);

        switch (tag.toLowerCase()) {

            case "drop":

                return $("select[name$=" + id + "]");

            case "radio":

                return $("input[name$=" + id + "]");

            case "check":

            case "table":

                return $("table[id$=" + id + "]");

            case "input":

                return $("input[id$=" + id + "]");

            case "link":

                return $("a[id$=" + id + "]");

        }

    },

    //获取一组ID指定的元素

    gets: function (ids, tag) {

        var arr = ids; //ids可为数组或以逗号分隔的ID列表

        if (!(ids instanceof Array)) {

            arr = ids.split(',');

        }

        var elems = oa.dom.get(arr[0], tag);

        for (var i = 1; i < arr.length; i++) {

            elems = elems.add(oa.dom.get(arr[i], tag));

        }

        return elems;

    }

};
dom = oa.dom;

而当用户调用时,就很简单了。

<!--html-->

<asp:Content ID="Content3" ContentPlaceHolderID="content" runat="server">

     <asp:TextBox ID="txtSubject" runat="server" Text="科目"></asp:TextBox>

</asp:Content>

<!--javascript-->

dom.get("txtSubject", "input");

(9).保持Javascript(行为),HTML(结构),CSS(展现)分离,js和css以外部文件方式导入到html中。不要将三者混搭,这样极不专业也难以维护。我还是举个例子来说明。

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>*****</title>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <link href="Contents/styles/index.css" rel="stylesheet" type="text/css" />

    <script src="Scripts/lib/jquery-1.7.1.min.js" type="text/javascript"></script>

    <script src="Scripts/plugins/jquery.include.js" type="text/javascript"></script>

    <script src="Scripts/import/index.js" type="text/javascript"></script>

    <link rel="shortcut icon" href="Contents/images/common/favicon.ico" type="image/x-icon" />

</head>

<body>

    <form id="form1" runat="server">

    <div class="top">

        <iframe src="Shared/Header.aspx" width="100%" scrolling="no" marginwidth="0" marginheight="0"

            frameborder="0" height="85px" id="header"></iframe>

    </div>

    <div class="content">

        <div class="side">

            <iframe src="Shared/Menu.aspx" height="100%" frameborder="0" scrolling="auto" id="menu">

            </iframe>

        </div>

        <div class="bar">

            <iframe src="Shared/MenuBar.aspx" height="100%" frameborder="0" scrolling="auto" id="menubar">

            </iframe>

        </div>

        <div class="main">

            <iframe src="Shared/PageContainer.aspx" height="100%" frameborder="0" scrolling="auto"

                id="page"></iframe>

        </div>

    </div>

    <div class="bottom">

        Copyright ? 2007 - 2012 ***. All Rights Reserved

    </div>

    </form>

</body>

</html>

然后是外部文件(js,css),我这里就不列出具体内容了。

(10).尽量编写有"防护性"的代码,即对你编写的代码保持很好的逻辑判断和异常处理。下面我们来看一个示例。

var hr = document.getElementById("horizontal-rule");

if (hr) { // 如果对象存在的前提下执行

    hr.parentNode.removeChild(hr); 

}

当你对你的代码不太确认时,请添加异常处理,以更好的进行调试。

try {

    // 以下代码不合法将导致异常

    document.getElementById("horizontal-rule").propertyName.toString();

} catch (error) {

    alert("An error occurred.");

)

请注意,才这里catch中的参数error,包含异常产生的原因和类型等信息。

try {

    // varx 不是有效的关键字,因此将抛出语法错误异常

    varx x = 0;

} catch (error) {

    // 以下列举六种对应的错误

    if (error instanceOf TypeError) {

        // 类型错误...

    } else if (error instanceOf SyntaxError) {

        // 输出错误消息

        alert(error.message); 

    } else if (error instanceOf RangeError) {

        // 超界错误

    } else if (error instanceOf EvalError) {

        // eval()执行错误

    } else if (error instanceOf ReferenceError) {

        // 非法引用错误

    } else if (error instanceOf URIError) {

        // URI解码错误

    }

}

有时为了满足业务需要,也可以自定义异常。

// 定义自定义异常

var domObjectNotFoundException = new Error("DOM object not found");

function getDOMObjectById(id) {

    var domObject = document.getElementById(id);

    if (!domObject) {

        // 当对象不存在时抛出错误

        throw domObjectNotFoundException;

    }

    return domObject;

}

try {

    // 假定我们获取一个不存在的对象

    getDOMObjectById("this-id-is-not-on-the-page").style.width = "100px";

} catch (error) {

    if (error instanceOf domObjectNotFoundException) {

        // 输出错误

        alert(error.message); 

    } else {

        // 做其他错误处理

    }

}

类似于很多面向对象的高级语言,你还能使用try/catch/finally形式,在finally在放置你必须执行的代码,不管是否产生异常。

try {

    getDOMObjectById("this-id-is-not-on-the-page").style.width = "100px";

} catch (error) {

    alert(error.message);

} finally {

    alert("不管你的对错,我依然光顾!");

}

后续还有很多规范,我会逐步总结下来....

你可能感兴趣的:(JavaScript)