单例模式
单例模式:
是一种项目开发中经常使用的模式,因为项目中我们可以使用单例模式来进行我们的"模块开发"
"模块化开发":
对于一个相对来说比较大的项目,需要多人协作的开发,我们一般情况下会根据当前项目的需求划分为几个功能板块,每个人负责一部分,同时开发,最后把每个人的代码进行合并
比如:
- 公共模块
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.
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS中的单例模式/工厂模式/构造函数模式(并非完全意义上的设计模式) - Python技术站