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.