<dfn id="w48us"></dfn><ul id="w48us"></ul>
  • <ul id="w48us"></ul>
  • <del id="w48us"></del>
    <ul id="w48us"></ul>
  • 常用的JavaScript模式

    時間:2024-09-22 04:01:28 JavaScript 我要投稿
    • 相關推薦

    常用的JavaScript模式

      常用的JavaScript模式有哪些?模式是解決或者避免一些問題的方案。下面YJBYS小編為大家列出幾種常用的JavaScript模式,歡迎大家閱讀學習!

      在JavaScript中,會用到一些常用的編碼模式。下面就列出了一些常用的JavaScript編碼模式,有的模式是為了解決特定的問題,有的則是幫助我們避免一些JavaScript中容易出現的錯誤。

      單一var模式

      所謂“單一var模式”(Single var pattern)就是指在函數頂部,只使用一個var進行變量聲明的模式。例如:

      function func() {

      var a = 1,

      b = 2,

      sum = a + b,

      myObject = {}, i,

      j;

      // other code}

      使用這個模式的好處:

      在函數頂部展示了所有函數中使用的局部變量

      防止變量提升引起的問題

      變量提升

      JavaScript允許在函數的任意地方聲明變量,但是效果都等同于在函數頂部進行聲明,這個是所謂的變量提升(Hoisting)。

      看一個例子:

      var num = 10;

      function func() {

      alert(num); // undefined

      var num = 1;

      alert(num); // 1}func();

      從這個例子可以看到,第一次alert的值并不是10,而是undefined。所以,應該盡量使用“單一var模式”來避免類似的問題。

      關于變量提升的細節,請參考我前面一篇JavaScript的執行上下文。

      for-in循環

      在JavaScript中,for-in循環主要用來枚舉對象的屬性。

      但是,由于JavaScript中原型鏈的存在,一般都會結合hasOwnProperty()來使用for-in循環,從而過濾原型鏈上的非該對象的屬性。

      var wilber = {

      name: "Wilber",

      age: 28,

      gender: "male"};Object.prototype.printPersonalInfo = function() { console.log(this.name, "is", this.age, "years old");

      };for(var prop in wilber) { if(wilber.hasOwnProperty(prop)) { console.log(prop, ":", wilber[prop]);

      }

      }

      開放的大括號位置

      根據開發人員的習慣,開放大括號的位置會有不同的選擇,可以和語句放在同一行,也可以放在新的一行:

      var total = 10;if(tatal > 5) { console.log("bigger than 5");

      }if(tatal > 5)

      { console.log("bigger than 5");

      }

      兩種形式的代碼都能實現同樣的邏輯,但是,JavaScript允許開發人員省略分號,JavaScript的分號插入機制(semicolon insertion mechanism)會負責加上省略的分號,這時開放大括號的位置不同就可能產生不同的結果。

      看一個例子:

      function func() { return

      {

      name: "Wilber"

      };

      }

      alert(func());// undefined

      之所以得到的結果是undefined就是因為JavaScript的分號插入機制,在return語句之后自動添加了分號。

      調整一下開放的大括號的位置就可以避免這個問題:

      function func() { return {

      name: "Wilber"

      };

      }

      alert(func());// [object]

      所以,關于開放的大括號位置,建議將開放的大括號放置在前面語句的同一行。

      強制new模式

      JavaScript中,通過new關鍵字,可以用構造函數來創建對象,例如:

      function Person(name, city) { this.name = name; this.city = city;

      this.getInfo = function() { console.log(this.name, "lives at", this.city);

      }

      }var will = new Person("Will", "Shanghai");

      will.getInfo();// Will lives at Shanghai

      但是,如果開發人員忘記了new關鍵字,那么構造函數中的this將代表全局對象(瀏覽器中就是window對象),所有的屬性將會變成全局對象的屬性。

      function Person(name, city) { this.name = name; this.city = city;

      this.getInfo = function() { console.log(this.name, "lives at", this.city);

      }

      }var will = Person("Will", "Shanghai");console.log(will.name);// Uncaught TypeError: Cannot read property 'name' of undefinedconsole.log(window.name);// Willconsole.log(window.city);// Shanghaiwindow.getInfo();// Will lives at Shanghai

      所以,為了避免這類問題的方式,首先是從代碼規范上下手。建議對于所有的JavaScript構造函數的命名方式都遵循,構造函數使用首字母大寫的命名方式。

      這樣當我們看到首字母大寫的函數,就要考慮是不是漏掉了new關鍵字。

      自調用構造函數

      當然除了規范之外,還可以通過代碼的方式來避免上面的問題。

      具體的做法就是,在構造函數中檢查this是否為構造函數的一個實例,如果不是,構造函數可以通過new關鍵字進行自調用。

      下面就是使用自調用構造函數對上面的例子進行改進:

      function Person(name, city) { if(!(this instanceof Person)) { return new Person(name, city);

      }

      this.name = name; this.city = city;

      this.getInfo = function() { console.log(this.name, "lives at", this.city);

      }

      }var will = Person("Will", "Shanghai");console.log(will.name);// Willconsole.log(will.city);// Shanghaiwill.getInfo();// Will lives at Shanghaiwindow.getInfo();// Uncaught TypeError: window.getInfo is not a function

      結合構造函數的命名約定和自調用的構造函數,這下就不用擔心漏掉new關鍵字的情況了。

      數組性質檢查

      當在JavaScript中判斷一個對象是不是數組的時候,不能直接使用typeof,因為我們會得到object。

      在ECMA5中提出了Array.isArray()這個函數,我們可以直接使用來判斷一個對象是不是數組類型。

      對于不支持ECMA5的環境,我們可以通過下面的方式自己實現Array.isArray()這個函數。

      if(typeof Array.isArray === "undefined") { Array.isArray = function(arg){ return Object.prototype.toString.call(arg) === "[object Array]";

      };

      }var arr = [];console.log(Array.isArray(arr));// true

      立即執行函數

      立即執行函數是JavaScript中非常常用的一種模式,形式如下:

      (function() {

      // other code

      }());

      通過這個模式可以提供一個局部的作用域,所以函數代碼都會在局部作用域中執行,不會污染其他作用域。

      現在的很多JavaScript庫都直接使用了這種模式,例如JQuery、underscore等等。

      立即執行函數的參數

      關于立即執行函數另外一點需要注意的地方就是立即執行函數的參數。

      我們可以像正常的函數調用一樣進行參數傳遞:

      (function(name, city) {

      console.log(name, "lives at", city);}("Wilber", "Shanghai"));// Wilber lives at Shanghai

      在立即執行函數中,是可以訪問外部作用域的(當然包括全局對象),例如:

      var name = "Wilber";var city = "Shanghai";

      (function() { console.log(name, "lives at", city);

      }());// Wilber lives at Shanghai

      但是,如果立即執行函數需要訪問全局對象,常用的模式就是將全局對象以參數的方式傳遞給立即執行函數。

      var name = "Wilber";var city = "Shanghai";

      (function(global) { console.log(global.name, "lives at", global.city);

      }(this));// Wilber lives at Shanghai

      這樣做的好處就是,在立即執行函數中訪問全局變量的屬性的時候就不用進行作用域鏈查找了,關于更多JavaScript作用域鏈的內容,可以參考理解JavaScript的作用域鏈。

      初始化時分支

      初始化時分支(Init-time Branching)是一種常用的優化模式,就是說當某個條件在整個程序聲明周期內都不會發生改變的時候,不用每次都對條件進行判斷,僅僅一次判斷就足夠了。

      這里最常見的例子就是對瀏覽器的檢測,在下面的例子中,每次使用utils.addListener1屬性的時候都要進行瀏覽器判斷,效率比較低下:

      var utils = {

      addListener: function(el, type, fn) {

      if (typeof window.addEventListener === 'function') {

      el.addEventListener(type, fn, false);

      } else if (typeof document.attachEvent === 'function') { // IE el.attachEvent('on' + type, fn);

      } else { // older browsers el['on' + type] = fn;

      }

      },

      removeListener: function(el, type, fn) {

      // pretty much the same... }

      };

      所以,根據初始化時分支模式,可以在腳本初始化的時候進行一次瀏覽器檢測,這樣在以后使用utils的時候就不必進行瀏覽器檢測了:

      // the interfacevar utils = {

      addListener: null,

      removeListener: null};// the implementationif (typeof window.addEventListener === 'function') {

      utils.addListener = function(el, type, fn) {

      el.addEventListener(type, fn, false);

      };

      utils.removeListener = function(el, type, fn) {

      el.removeEventListener(type, fn, false);

      };

      } else if (typeof document.attachEvent === 'function') { // IE utils.addListener = function(el, type, fn) {

      el.attachEvent('on' + type, fn);

      };

      utils.removeListener = function(el, type, fn) {

      el.detachEvent('on' + type, fn);

      };

      } else { // older browsers utils.addListener = function(el, type, fn) {

      el['on' + type] = fn;

      };

      utils.removeListener = function(el, type, fn) {

      el['on' + type] = null;

      };

      }

      命名空間模式

      JavaScript代碼中,過多的全局變量經常會引發一些問題,比如命名沖突。

      結合命名空間模式就可以一定程度上減少代碼中全局變量的個數。

      下面就看一個通用命名空間函數的實現:

      var MYAPP = MYAPP || {};

      MYAPP.namespace = function (ns_string) { var parts = ns_string.split('.'), parent = MYAPP,

      i; // strip redundant leading global

      if (parts[0] === "MYAPP") {

      parts = parts.slice(1);

      } for (i = 0; i < parts.length; i += 1) { // create a property if it doesn't exist

      if (typeof parent[parts[i]] === "undefined") { parent[parts[i]] = {};

      } parent = parent[parts[i]];

      } return parent;

      };

      結合這個通用命名空間函數的,就可以實現代碼的模塊化:

      // assign returned value to a local varvar module2 = MYAPP.namespace('MYAPP.modules.module2');

      module2 === MYAPP.modules.module2; // true// skip initial `MYAPP`MYAPP.namespace('modules.module51');// long namespaceMYAPP.namespace('once.upon.a.time.there.was.this.long.nested.property');

      聲明依賴關系

      JavaScirpt庫通常是通過命名空間來進行模塊化,當我們在代碼中使用第三方的庫的時候,可以只引入我們代碼依賴的模塊。

      所謂聲明依賴關系,就是指在函數或者模塊的頂部是聲明代碼需要依賴哪些模塊,這個聲明包括創建一個局部變量,并將它們指向你需要的模塊:

      var myFunction = function () { // dependencies

      var event = YAHOO.util.Event,

      dom = YAHOO.util.Dom; // use event and dom variables

      // for the rest of the function...};

      通過聲明依賴關系這種模式,會給我們帶來很多好處:

      明確的依賴聲明可以向你的代碼的使用者表明這些特殊的腳本文件需要被確保包含進頁面

      數頭部的聲明解,讓發現和處理依賴關系更加簡單

      局部變量(比如:dom)通常比使用全局變量(比如:YAHOO)快,比訪問全局對象的屬性(比如:YAHOO.util.Do)更快,可以得到更好的性能,全局符號只會在函數中出現一次,然后就可以使用局部變量,后者速度更快。

      壓縮工具比如YUICompressor 和 Google Closure compiler會重命名局部變量,產生更小的體積的代碼,但從來不會重命名全局變量,因為那樣是不安全的

      代碼復用模式

      下面就看看JavaScript中的代碼復用模式。一般來說,通常使用下面的方式來實現代碼的復用:

      繼承

      借用方法

      繼承

      在JavaScript中可以很方便的通過原型來實現繼承。

      關于原型式繼承,ECMA5通過新增Object.create()方法規范化了原型式繼承。這個方法接收兩個參數:

      一個用作新對象原型的對象

      一個為新對象定義額外屬性的對象(可選的)

      看一個使用Object.create()的例子:

      utilsLibC = Object.create(utilsLibA, { sub: {

      value: function(){

      console.log("sub method from utilsLibC");

      }

      },

      mult: {

      value: function(){

      console.log("mult method from utilsLibC");

      }

      },

      })

      utilsLibC.add();// add method from utilsLibA

      utilsLibC.sub();// sub method from utilsLibCutilsLibC.mult();

      // mult method from utilsLibC

      console.log(utilsLibC.__proto__);// Object {add: (), sub: (), __proto__: Object}console.log(utilsLibC.__proto__.constructor);

      // function Object() { [native code] }

      關于JavaScript繼承的更多信息,可以參考關于JavaScript繼承的那些事。

      借用方法

      有時候可能只需要一個已經存在的對象的一個或兩個方法,但是又不想通過繼承,來建立額外的父子(parent-child)關系。

      這時就可以考慮使用借用方法模式完成一些函數的復用。借用方法模式得益于function的方法call()和apply()。

      這種模式一個常見用法就是借用數組方法。

      數組擁有有用的方法,那些類數組對象(array-like objects)比如arguments類數組對象(array-like objects)比如arguments沒有的方法。所以arguments可以借用數組的方法,比如slice()方法,看一個例子:

      function f() { var args = [].slice.call(arguments, 1, 3); return args;

      }// examplef(1, 2, 3, 4, 5, 6); // returns [2,3]

    【常用的JavaScript模式】相關文章:

    JavaScript常用方法匯總03-08

    JavaScript數組常用方法介紹03-25

    對javascript的理解03-29

    最常用的20個javascript方法函數03-10

    JavaScript的課堂講解03-31

    JavaScript 基礎教學04-01

    JavaScript學習筆記03-30

    Javascript的this用法簡述03-25

    常用排序算法之JavaScript實現代碼段03-10

    主站蜘蛛池模板: 亚洲精品国产精品乱码在线观看| 亚洲国产精品成人一区| 国产精品福利电影一区二区三区四区欧美白嫩精品 | 中文字幕亚洲综合精品一区| 亚洲精品国产V片在线观看| 亚洲国产精品自在在线观看| 久久精品国产亚洲av麻豆色欲| 久久精品国产亚洲Aⅴ香蕉 | 国产成人精品cao在线| 日本VA欧美VA精品发布| 精品无码综合一区| 亚洲精品免费在线观看| 精品无码国产污污污免费网站 | 精品国产免费一区二区三区香蕉| 亚洲精品视频在线观看你懂的| www亚洲欲色成人久久精品| 91精品国产自产在线观看永久| 亚洲乱码国产乱码精品精| 久久亚洲AV永久无码精品| 隔壁老王国产在线精品| 国产精品久久久久久影院| 久久久久亚洲精品天堂| 中文字幕亚洲精品无码| 欧美日韩精品一区二区三区不卡 | 国产亚洲精品不卡在线| 国产日韩欧美精品| 精品无码久久久久久午夜| 在线涩涩免费观看国产精品| 久久精品国产只有精品66| 国产精品无打码在线播放| 在线观看91精品国产入口| 999国内精品永久免费视频| 久久99国产综合精品女同| 免费欧美精品a在线| 精品一区二区三区自拍图片区| 无夜精品久久久久久| 免费人成在线观看欧美精品| 国产精品日日摸夜夜添夜夜添1国产精品va欧美精 | 嫖妓丰满肥熟妇在线精品| 无码精品人妻一区二区三区AV| 精品人妻伦一二三区久久|