zoukankan      html  css  js  c++  java
  • 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 hmiinyu@sina.com
    * @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("不管你的对错,我依然光顾!");
    }

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

  • 相关阅读:
    SAX解析XML笔记
    使用 Angular 2 来创建FlexGrid控件
    算法-快速排序(优雅版)
    使用泛型简化动态代理
    Java泛型概述
    POI-PPT官方文档
    Java 利用POI操作PPT
    Java8学习笔记(九)--日期/时间(Date Time)API指南
    Java8学习笔记(八)--方法引入的补充
    Android WebView加载本地html并实现Java与JS交互
  • 原文地址:https://www.cnblogs.com/hmiinyu/p/2508144.html
Copyright © 2011-2022 走看看