最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript實現(xiàn)設計模式中的單例模式的一些技巧總結(jié)

 更新時間:2016年05月17日 09:30:08   作者:luojianjava  
單例模式是JavaScript項目中最常用的設計模式之一,下面羅列了JavaScript實現(xiàn)設計模式中的單例模式的一些技巧總結(jié),包括惰性加載與分支技術(shù)等,需要的朋友可以參考下.

一、使用全局變量保存單例

這是最簡單的實現(xiàn)方法

function Person(){ 
  this.createTime=new Date(); 
} 

var instance=new Person(); 
function getInstance(){ 
  return instance; 
} 

加載該js時就創(chuàng)建一個Person對象,保存到instance全局變量中,每次使用都取這個對象。如果一次都沒使用,那么創(chuàng)建的這個對象則浪費了,我們可以優(yōu)化一下,

var instance 
function getInstance(){ 
  if(!instance){ 
    instance=new Person(); 
  } 
  return instance; 
} 

這樣,第一次使用時才創(chuàng)建對象。
這個方法的缺點是,instance是全局的變量,在多人合作或者開發(fā)周期比較長的情況下,很難保證instance不會被其它代碼修改或覆蓋,很可能到調(diào)用的時候,發(fā)現(xiàn)instance根本就不是Person對象。
我們考慮下使用閉包來封裝起instance,使它不再是全局變量就可以解決這個問題了

二、閉包創(chuàng)建對象

var getInstance(){ 
var instance; 
return function(){ 
    if(!instance){ 
      instance=new Person(); 
    } 
    return instance; 
  } 
}(); 

這樣,instance就被封裝起來了,不用擔心被修改了。
現(xiàn)在通過getInstance()函數(shù)可以獲得單例了。新的問題,如果我通過new Person()來創(chuàng)建對象,獲得的還是多個對象,javascript又不可以像java一樣把構(gòu)造器私有化。那怎么樣可以讓多次new出來的對象都是一個實例呢?

三、構(gòu)造函數(shù)的靜態(tài)屬性緩存實例

先看代碼

function Person(){ 
  //如果已經(jīng)緩存了實例,則直接返回緩存的實例 
  if(typeof Person.instance==='object'){ 
    return Person.instance; 
  } 
  this.createTime=new Date(); 
  //緩存實例 
  Person.instance=this; 
  return this; 
} 

從代碼可以看到,第一次new時,if的條件返回false,會往下走,初始化對象,然后保存對象到Person.instance這個靜態(tài)屬性中。
第二次new 時,if的條件返回true,直接返回Person.instance,不會再往下運行初始化的代碼。所以不管new幾次,返回的都是第一次創(chuàng)建的對象。

這個方法的缺點和方法一的缺點一樣,Person.instance也是公開屬性,有可能會被修改。

我們參考方法二,使用閉包來封裝一個,也許就能解決該問題了

四、重寫構(gòu)造函數(shù)

這個方法要使用閉包,但不能像方法二那么簡單,我們需要重寫構(gòu)造函數(shù)。

function Person(){ 
  //緩存實例 
  var instance=this; 
  this.createTime=new Date(); 
  //重寫構(gòu)造函數(shù) 
  Person=function(){ 
    return instance; 
  } 
} 

第一次new 時,調(diào)用原始構(gòu)造函數(shù)先緩存該實例,然后再初始化,同時,重寫該構(gòu)造函數(shù)。以后再new 時,永遠調(diào)用不到原始的構(gòu)造函數(shù)了,只能調(diào)用到重寫后的構(gòu)造函數(shù),而這個函數(shù)總是返回緩存的instance.
上面的方法似乎沒什么問題,但通過下面的測試,可以發(fā)現(xiàn)問題

//向原型添加屬性 
Person.prototype.prop1=true; 
var p1=new Person(); 
//在創(chuàng)建初始化對象后,再次向該原型添加屬性 
Person.prototype.prop2=true; 
var p2=new Person(); 

//開始測試 
console.log(p1.prop1);//結(jié)果為true 
console.log(p2.prop1);//結(jié)果為true 

console.log(p1.prop2);//結(jié)果為undefined 
console.log(p2.prop2);//結(jié)果為undefined 

console.log(p1.constructor===Person);//結(jié)果為false 
console.log(p2.constructor===Person);//結(jié)果為false 

我們預期中的結(jié)果,應該是全都是true。
分析一下上述測試代碼

Person.prototype.prop1=true;是在原始構(gòu)造函數(shù)的原型下增加了prop1這個屬性,并賦值

而在執(zhí)行 var p1=new Person();之后,Person這個構(gòu)造函數(shù)已經(jīng)被重寫了

所以Person.prototype.prop2=true;是在新的原型下增加prop2這個屬性

var p2=new Person(); p2和p1實際上是同一個對象,即原始構(gòu)造函數(shù)創(chuàng)建的對象

所以p1 p2都有prop1這個屬性,而沒有prop2這個屬性

同樣的,p1 p2的constructor指向的也是原始的構(gòu)造函數(shù),而Person此時已不是原來那個函數(shù)了

為了能按預期的結(jié)果那樣運行,可以通過一些修改來實現(xiàn)

function Person(){ 
  //緩存實例 
  var instance=this; 
  //重寫構(gòu)造函數(shù) 
  Person=function(){ 
    return instance; 
  } 
  //保留原型屬性 
  Person.prototype=this; 
  //實例 
  instance=new Person(); 
  //重置構(gòu)造函數(shù)引用 
  instance.constructor=Person; 

  //其他初始化 
  instance.createTime=new Date(); 
 
  return instance; 
} 

再運行前面的測試代碼,結(jié)果都是true了。

五、惰性加載:
在大型或復雜的項目中,起到了優(yōu)化的作用:那些開銷較大卻很少用到的組件可以被包裝到惰性加載單例中,示例程序:

/* Singleton with Private Members, step 3. */

MyNamespace.Singleton = (function() {
 // Private members.
 var privateAttribute1 = false;
 var privateAttribute2 = [1, 2, 3];

 function privateMethod1() {
  ...
 }
 function privateMethod2(args) {
  ...
 }

 return { // Public members.
  publicAttribute1: true,
  publicAttribute2: 10,

  publicMethod1: function() {
   ...
  },
  publicMethod2: function(args) {
   ...
  }
 };
})();

/* General skeleton for a lazy loading singleton, step 1. */

MyNamespace.Singleton = (function() {

 function constructor() { // All of the normal singleton code goes here.
  // Private members.
  var privateAttribute1 = false;
  var privateAttribute2 = [1, 2, 3];

  function privateMethod1() {
   ...
  }
  function privateMethod2(args) {
   ...
  }

  return { // Public members.
   publicAttribute1: true,
   publicAttribute2: 10,

   publicMethod1: function() {
    ...
   },
   publicMethod2: function(args) {
    ...
   }
  }
 }

})();

/* General skeleton for a lazy loading singleton, step 2. */

MyNamespace.Singleton = (function() {

 function constructor() { // All of the normal singleton code goes here.
  ...
 }

 return {
  getInstance: function() {
   // Control code goes here.
  }
 }
})();

/* General skeleton for a lazy loading singleton, step 3. */

MyNamespace.Singleton = (function() {

 var uniqueInstance; // Private attribute that holds the single instance.

 function constructor() { // All of the normal singleton code goes here.
  ...
 }

 return {
  getInstance: function() {
   if(!uniqueInstance) { // Instantiate only if the instance doesn't exist.
    uniqueInstance = constructor();
   }
   return uniqueInstance;
  }
 }
})();

六、使用分支單例:
針對特定環(huán)境的代碼可以被包裝到分支型單例中,示例程序:

/* SimpleXhrFactory singleton, step 1. */

var SimpleXhrFactory = (function() {

 // The three branches.
 var standard = {
  createXhrObject: function() {
   return new XMLHttpRequest();
  }
 };
 var activeXNew = {
  createXhrObject: function() {
   return new ActiveXObject('Msxml2.XMLHTTP');
  }
 };
 var activeXOld = {
  createXhrObject: function() {
   return new ActiveXObject('Microsoft.XMLHTTP');
  }
 };

})();

/* SimpleXhrFactory singleton, step 2. */

var SimpleXhrFactory = (function() {

 // The three branches.
 var standard = {
  createXhrObject: function() {
   return new XMLHttpRequest();
  }
 };
 var activeXNew = {
  createXhrObject: function() {
   return new ActiveXObject('Msxml2.XMLHTTP');
  }
 };
 var activeXOld = {
  createXhrObject: function() {
   return new ActiveXObject('Microsoft.XMLHTTP');
  }
 };

 // To assign the branch, try each method; return whatever doesn't fail.
 var testObject;
 try {
  testObject = standard.createXhrObject();
  return standard; // Return this if no error was thrown.
 }
 catch(e) {
  try {
   testObject = activeXNew.createXhrObject();
   return activeXNew; // Return this if no error was thrown.
  }
  catch(e) {
   try {
    testObject = activeXOld.createXhrObject();
    return activeXOld; // Return this if no error was thrown.
   }
   catch(e) {
    throw new Error('No XHR object found in this environment.');
   }
  }
 }

})();

相關(guān)文章

  • layui關(guān)閉層級、簡單監(jiān)聽的實例

    layui關(guān)閉層級、簡單監(jiān)聽的實例

    今天小編就為大家分享一篇layui關(guān)閉層級、簡單監(jiān)聽的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • 基于BootStrap的圖片輪播效果展示實例代碼

    基于BootStrap的圖片輪播效果展示實例代碼

    這篇文章主要介紹了基于BootStrap的圖片輪播效果展示實例代碼的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • 在小程序Canvas中使用measureText的方法示例

    在小程序Canvas中使用measureText的方法示例

    有時候我們在使用Canvas繪制一段文本時,會需要通過measureText()方法獲取文本的寬度,本文主要介紹了在小程序Canvas中使用measureText的方法示例,需要的朋友可以參考下
    2018-10-10
  • js實現(xiàn)限定范圍拖拽的示例

    js實現(xiàn)限定范圍拖拽的示例

    這篇文章主要介紹了js實現(xiàn)限定范圍拖拽的示例,幫助大家更好的制作js特效,美化自己的網(wǎng)頁,感興趣的朋友可以了解下
    2020-10-10
  • JS前端知識點總結(jié)之頁面加載事件,數(shù)組操作,DOM節(jié)點操作,循環(huán)和分支

    JS前端知識點總結(jié)之頁面加載事件,數(shù)組操作,DOM節(jié)點操作,循環(huán)和分支

    這篇文章主要介紹了JS前端知識點總結(jié)之頁面加載事件,數(shù)組操作,DOM節(jié)點操作,循環(huán)和分支,結(jié)合實例形式總結(jié)分析了JS頁面加載事件,數(shù)組操作,DOM節(jié)點操作,循環(huán)和分支所涉及的相關(guān)事件、函數(shù)及操作注意事項,需要的朋友可以參考下
    2019-07-07
  • JS加密插件CryptoJS實現(xiàn)的Base64加密示例

    JS加密插件CryptoJS實現(xiàn)的Base64加密示例

    這篇文章主要介紹了JS加密插件CryptoJS實現(xiàn)的Base64加密,結(jié)合實例形式分析了CryptoJS進行base64加密的簡單實現(xiàn)技巧,需要的朋友可以參考下
    2018-08-08
  • 基于JavaScript打造一款桌面級便簽系統(tǒng)

    基于JavaScript打造一款桌面級便簽系統(tǒng)

    本文將用html,css和JavaScript實現(xiàn)一個簡單的便簽系統(tǒng)。除非手動清空便簽,否則便簽會一直保留,非常方便。感興趣的小伙伴可以跟隨小編一起動手試一試
    2022-02-02
  • 前端JavaScript獲取電池信息

    前端JavaScript獲取電池信息

    受到同事啟發(fā),突然發(fā)現(xiàn)了幾個有趣又實用的web api,下面這篇文章主要給大家介紹了關(guān)于前端JavaScript獲取電池信息的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-04-04
  • 僅IE9/10同時支持script元素的onload和onreadystatechange事件分析

    僅IE9/10同時支持script元素的onload和onreadystatechange事件分析

    測試結(jié)果可以看出,IE9后已經(jīng)開始支持script的onload事件了。一直以來我們判斷js文件是否已經(jīng)加載完成就是用以上的兩個事件。
    2011-04-04
  • javascript學習小結(jié)之prototype

    javascript學習小結(jié)之prototype

    本系列博文主要談一些在 javascript 使用中經(jīng)常會混淆的高級應用,包括: prototype, closure, scope, this關(guān)鍵字. 對于一個需要提高自己javascript水平的程序員,這些都是必須要掌握的,本節(jié)主要介紹prototype.
    2015-12-12

最新評論

兴和县| 秭归县| 金华市| 高邑县| 新田县| 金堂县| 辰溪县| 乐至县| 湄潭县| 罗江县| 大悟县| 海伦市| 黑龙江省| 长汀县| 阿尔山市| 穆棱市| 元江| 金秀| 肇庆市| 衡东县| 利津县| 宝应县| 娄烦县| 金昌市| 湘潭市| 马鞍山市| 西乌珠穆沁旗| 府谷县| 桐柏县| 宿迁市| 平南县| 望江县| 威信县| 韶关市| 盘锦市| 娱乐| 射洪县| 临泉县| 慈利县| 霸州市| 隆昌县|