JavaScript 編程模式

編程模式,是源自經驗和探索總結出的最佳實踐方案,既有助於可讀性和可維護性,也有助於提升整體性能。


行爲隔離


總則:結構、樣式和行爲之間兩兩隔離。

  • 避免在結構中使用內聯事件

  • 儘量少用 <script> 標籤

  • 考慮 JavaScript 被禁用的情況,添加一些替換標籤


命名空間


爲了減少命名衝突,優化 JavaScript 性能,儘量只定義幾個全局變量,並將其他變量和方法定義爲這幾個變量的屬性。

//定義全局變量
var MYAPP = window.MYAPP || {};
//定義屬性
MYAPP.event = {};
//定義方法
MYAPP.event = {
  addListener : function() {
    //執行相關的邏輯操作
  }
  removeListener : function() {
    //執行相關的邏輯操作
  }
  //其他方法
};

在命名空間中使用構造器函數。

MYAPP.dom = {};
MYAPP.dom.Element = function (type, prop) {
  var tep = document.createElement(type);
  for (var i in prop) {
    tmp.setAttribute(i, prop[i]);
  }
  return tmp;
}

命名空間方法:

var MYAPP = window.MYAPP || {};
MYAPP.namespace = function (name) {
  var parts = name.split(“.”);
  var current = MYAPP;
  for (var i in parts) {
    if (!current[parts[i]]) {
      current[parts[i]] = {};
    }
    current = current[parts[i]];
  } 
}
MYAPP.namespace(“dom.event”);
// 上述操作等價於:
var MYAPP = {
    dom: {
        event: {}
    }
}


初始化功能


由於瀏覽器的不一致性,當我們使用 JavaScript 操作 DOM 或 BOM 前,通常會進行一定的功能檢測。如果在運行前需要檢測的功能較多,那麼就會嚴重影響腳本的執行速度。對於這個問題,可以通過初始化功能解決,即在腳本加載後,立即對重要的函數執行功能檢測。如此,後續就無需檢測功能,可以直接執行相關的函數。

var MYAPP = window.MYAPP || {};
MYAPP.event = {
  addListener: null,
  removeListener: null
};
// 初始化功能演示如下:
if (typeof window.addEventListener === ‘function’) {
  MYAPP.event.addListener = function (el, type, fn) {
    el.addEventListener(type, fn, false);
  };
  MYAPP.event.removeListener = function (el, type, fn) {
    el.removeEventListener(type, fn, false);
  };
} else if (typeof document.attachEvent === “function”) {
  MYAPP.event.addListener = function (el, type, fn) {
    el.attachEvent(“on” + type, fn);
  };
  MYAPP.event.removeListener = function (el, type, fn) {
    el.detachEvent(“on” + type, fn);
  };
} else {
  MYAPP.event.addListener = function (el, type, fn) {
    el[“on” + type] = fn;
  };
  MYAPP.event.removeListener = function (el, type, fn) {
    el[“on” + type] = null;
  }; 
}


延遲定義


延遲定義,恰巧與初始化模式的思想相反。對於那些不一定會被調用的函數,可以讓其被調用時再初始化,並且只進行一次初始化。

var MYAPP = window.MYAPP || {};
MYAPP.event = {
  addListener: function(el, type, fn) {
    if (typeof window.addEventListener === ‘function’) {
      MYAPP.event.addListener = function (el, type, fn) {
        el.addEventListener(type, fn, false);
      };
    } else if (typeof document.attachEvent === “function”) {
      MYAPP.event.addListener = function (el, type, fn) {
        el.attachEvent(“on” + type, fn);
      };
    } else {
      MYAPP.event.addListener = function (el, type, fn) {
        el[“on” + type] = fn;
      };
    }
    MYAPP.event.addListener(el, type, fn);
  }
};

這個地方我需要修改一下,使用可以重寫自己的函數。


配置對象


配置對象模式,適用於向函數中傳遞多個參數。簡單的說,就是將參數集合放入一個對象中,將對象傳給參數,這個對象甚至可以是一個 JSON 文件。當參數量較少時,就像是傳統的傳參,當參數集龐大時,就如同傳遞環境配置變量。將變量和函數解耦,是非常不錯的實踐:

  • 無需考慮參數的順序

  • 可以忽略某些參數

  • 具有更好的可讀性和可維護性

var MYAPP = window.MYAPP || {};
MYAPP.dom = {};
MYAPP.dom.Button = function(text, conf) {
    var type = conf.type || “submit”;
    var color = conf.color || “red”
}
// 使用方式
var conf = {
    type: “reset”,
    color: “green”
};
new MYAPP.dom.Button(“Reset”, conf);


私有變量和方法


與 C++、JAVA 不同,JavaScript 中並沒有控制訪問權限的修飾符,但我們可以使用局部變量和函數來實現類似的權限控制。

var MYAPP = window.MYAPP || {};
MYAPP.dom = {};
MYAPP.dom.Button = function (text, conf) {
  var styles = {
    color: “black”
  }
  function setStyles() {
    for (var i in styles) {
      b.style[i] = conf[i] || styles[i];
    }
  }
  conf = conf || {};
  var b = document.createElement(“input”);
  b.type = conf[“type”] || “submit”;
  b.value = text;
  setStyles();
  return b;
}

在這裏,styles 是一個私有屬性,而 setStyle() 則是一個私有方法。構造器可以在內部調用它們(它們也可以訪問構造器中的任何對象),但它們不能被外部代碼所調用。


特權函數


在上例中,我們可以爲 b 添加一個 getDefaults() 方法,返回 styles 對象,從而實現對內部屬性或方法的訪問,這個 getDefaults() 就是一種特權函數。


私有函數的公有化


爲了防止外部修改,將函數設爲私有,有時候又想外部可以訪問到,所以有需要設爲公有。解決方案是,使用公有變量引用私有函數,即可將其公有化。

var MYAPP = window.MYAPP || {};
MYAPP.dom = {};
MYAPP.dom.Button = (function () {
  var _setStyle = {};
  var _getStyle = ();
  return {
    setStyle: _setStyle,
    getStyle: _getStyle,
    yetAnother: _setStyle
  };  
})();


自執行的函數


使用立即執行的匿名函數,同樣可以保證全局命名空間不會受到污染。這種函數的所有變量都是局部的,並在函數返回時被銷燬(非閉包)。

適合於執行一次性的初始化任務。

(function(){
    //編寫邏輯操作代碼
})()


鏈式調用


鏈式調用,是一種便捷的調用方式。其實現本質是使用一致的上下文對象,並在鏈式方法間傳遞這個對象。這種靈活的調用方式也是 jQuery 的一大特色。


JSON


JSON 是一種輕量級的數據交換格式。由於它本身就是由類似 JavaScript 的對象和數組標記的數據構成的,所以解析起來非常方便。

說道解析,我們可以使用 JavaScript 的 eval() 方法轉換;但是由於 eval() 本身的缺陷,這件事還是使用更安全的方法吧,比如 JavaScript 的某些庫(http://json.org):

var obj = JSON.parse(xhr.respnseText);





發佈了27 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章