JS中的單例模式/工廠模式/構造函數模式(並非完全意義上的設計模式)


單例模式

單例模式:
是一種項目開發中經常使用的模式,因為項目中我們可以使用單例模式來進行我們的"模塊開發"

"模塊化開發":
對於一個相對來說比較大的項目,需要多人協作的開發,我們一般情況下會根據當前項目的需求划分為幾個功能板塊,每個人負責一部分,同時開發,最后把每個人的代碼進行合並

比如:

  • 公共模塊
var utils = {
    select: function(){
    
    }
}
  • 頁卡模塊中的change->實現選項卡切換
var tabRender = {
    change: function(){
        utils.select(); // 在自己的名命空間下調用其他名命空間的方法
    }
}

+搜索模塊change->搜索內容變化處理的

var searchRender = {
    change: function (){
        this..clickEven(); // 在自己的名命空間下調用自己名命空間的方法
    }
    clickEvent: function(){
    
    }
}

工廠模式

單例模式雖然解決了分組的作用,但是不能實現批量的生產,屬於手工作業模式
函數的封裝:
把實現同一件事情的相同的代碼放到一個函數中,以后如果在想實現這個功能,不需要從新的編寫這些代碼了,只需要執行當前的函數即可
低耦合高內聚:
減少頁面中冗余代碼,提高代碼的重復利用率

function createJsPerson(name, age){
    var obj = {};
    obj.name = name;
    obj.age = age;
    obj.writeJS = function(){
        console.log("my name is " + this.name + ", i can                write js ~~")
    }
    return obj;
}

var p1 = createJsPerson("lemon1", 21)
var p2 = createJsPerson("lemon2", 22)

js中不存在重載,方法名一樣的話,后面的會把前面的覆蓋掉,最后只保留一個

function sum(num){
    if(typeof num === "undefined"){
        return 0; 
    }
    return num;
} 
sum(100);
sum(0)

構造函數模式

構造函數模式的目的就是為了創建一個自定義類,並且創建這個類的實例

function CreateJsPerson(name, age){
    this.name = name;
    this.age = age;
    this.writeJS = function(){
        console.log("my name is " + this.name + ", i can                write js ~~")
    }
}

var p1 = new CreateJsPerson("lemon1", 21)
var p2 = new CreateJsPerson("lemon2", 22)

構造函數和工廠模式的區別
執行的時候

  • 普通函數執行->createJsPerson()
  • 構造函數模式->new CreateJsPerson(), 通過new執行后,createJsPerson就是一個類了,而函數執行的返回值(p1)就是CreateJsPerson這個類的一個實例)

在函數代碼執行的時候

  • 相同:都是形成一個私有的作用域,然后形參賦值->解釋->代碼從上到下執行
  • 不同:在代碼執行之前,不用自己手動創建對象了,瀏覽器會默認創建一個對象的數據類型的值,這個對象其實就是我們當前類的一個實例
    接下來,代碼從上到下執行,以當前的實例為執行的主體,this代表的就是當前的實例
    最后瀏覽器會默認的把創建的實例返回

JS中所有的類都是函數數據類型的,它通過new執行變成了一個類,但是它本身也是一個普通的函數

JS中所有的實例都死對象數據類型的

p1和p2都是CreateJsPerson這個類的實例,所以都擁有writeJs這個方法,但是不同實例之間的方法是不一樣的
在類中給實例增加的屬性(this.xxx = xxx)屬於當前實例的私有的屬性,實例和實例之間單獨的個體,所以私有的屬性之間是不相等的

console.log(p1.writeJs === p2.writeJs); 

->false


this問題

var name = ""
var res = CreateJsPerson('-lemon', -22);
console.log(name);
console.log(age)

-> '-lemon'
-> -22

這樣寫不是構造函數模式執行而是普通的函數執行,由於沒有寫return所以res = undefined, 並且CreateJsPerson這個方法中的this是window

構造函數模式(擴展)

function Fn(){
    this.x = 100;
    this.getX = function(){
        console.log(this.x)
    }
}
var f1 = new Fn;
f1.getX(); // 方法中的this是f1 100
var ss = f1.getX;
ss(); // 方法中的this是window undefined
  • 在構造函數模式中new Fn()執行, 如果Fn不需要傳遞參數的話, 后面的小括號可以省略
  • this的問題:在類中出現的this.xxx = xxx 中的this都是當前類的實例,而某一個屬性值(方法),方法中的this需要看方法執行的時候,前面是否有"."才能知道this是誰
  • 類有普通函數的一面,當函數執行的時候, var num其實只是當前形成的私有作用域中的私有變量而已, 它和f1這個實例沒有任何關系.只有this.xxx = xxx才相當於給f1這個實例增加私有的屬性和方法,才和我們的f1有關系
function Fn(){
    var num = 10;
    this.x = 100;
    this.getX = function(){
        console.log(this.x)
    }
}
var f1 = new Fn;
console.log(f1.num); // -> undefined
  • 在構造函數模式中,瀏覽器會默認的把我們的實例返回(返回的是一個對象數據類型的值),如果我們自己手動寫了return返回:

返回的是一個基本數據類型的值,當前實例是不變的,例如: return 100;

返回的是一個引用數據類型的值,當前的實例會被自己返回的值替換掉,例如: return {name: 'lemon'}, 我們的f1就不在是Fn的實例了,而是對象 {name: 'lemon'}

function Fn(){
    var num = 10;
    this.x = 100;
    this.getX = function(){
        console.log(this.x)
    }
    return {name: 'lemon', age: 22};
}
var f1 = new Fn;
console.log(f1); //  {name: 'lemon', age: 22}
function Fn(){
    var num = 10;
    this.x = 100;
    this.getX = function(){
        console.log(this.x)
    }
    return 100;
}
var f1 = new Fn;
console.log(f1); // 不變

檢測屬性

  • 檢測某一個實例是否屬於這個類
console.log(f1 instanceof Fn); // -> true
console.log(f1 instanceof Array); // -> true
  • f1和f2都是Fn這個類的一個實例,都擁有x和getX兩個屬性,但是這兩個屬性都是各自都屬性,所以
console.log(f1.getX === f2.getX); // -> false
  • in 檢測某一個屬性是否屬於這個對象(attr in object), 不管是私有的屬性還是公有的屬性, 只要存在, 用in來檢測都是true
console.log("getX" in f1); // -> true
  • hasOwnProperty: 用來檢測某一個屬性是否為這個對象的"私有屬性",這個方法只能檢測私有的屬性
console.log(f1.hasOwnProperty("getX")); // -> true
  • isPrototypeOf: 用來判斷指定對象object1是否存在於另一個對象object2的原型鏈中,是則返回true,否則返回false
object1.isPrototypeOf(object2);

如果object2的原型鏈中包含object1,那么isPrototypeOf方法返回true
如果object2不是一個對象或者object1沒有出現在object2中的原型鏈中,isPrototypeOf方法將返回false.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM