单例模式
把描述同一个事物(同一个对象)的属性和方法放在一个内存空间下,起到分组的作用,这样不同事物之间的属性即使属性名相同,相互之间也不会冲突。
在项目中可以使用单例模式来进行模块化开发。
var person1 = {
name:'jack',
age:18
};
var person2 = {
name:'tom',
age:18
};
弊端:虽然起到了分组的作用,但是不能实现批量生产,属于手工作业模式。
工厂模式
把实现同一件事情的相同的代码放到一个函数中,以后如果再次实现这个功能就不需要重新编写新的代码了,只需要执行当前的函数即可。我们把工厂模式成为“函数的封装”(低耦合高内聚:减少页面中的冗余代码,提高代码的重复利用率。)
function createPerson(name,age){
var obj = {};
obj.name = name;
obj.age = age;
obj.say = function(){
console.log(this.name + '---' + this.age)
}
return obj;
}
var person1 = createPerson('jack',18);
var person2 = createPerson('tom',28);
构造函数模式
function createPerson(name,age){
this.name = name;
this.age = age;
this.say = function(){
console.log(this.name + '---' + this.age)
}
}
var person1 = new createPerson('jack',18);
var person2 = new createPerson('tom',28);
构造函数模式和工厂模式的区别:
1.执行的时候:
普通函数:createPerson()
构造函数:new createPerson() 通过new执行后,createPerson就是一个类了。而函数的返回值就是这个类的一个实例。
JS当中所有的类都是function数据类型,它通过new执行变成了一个类,但是它本身也是一个普通的函数。
JS当中所有的实例都是Object数据类型的。
2.在函数代码执行的时候:
相同点:都是形成一个私有的作用域,然后形参赋值--->预解释--->代码从上到下执行(类和普通函数一样,也有普通的一面)
不同点:在代码执行之前,不用自己再手动的创建对象了,浏览器会默认创建一个对象数据类型的值(这个对象就是当前类的一个实例),接下来代码从上到下执行,以当前实例为执行的主体(this代表的就是当前的主体),分别把属性名和属性值赋值给当前的实例,最后浏览器会默认的把创建的实例返回。
** 在构造函数模式中,类中(函数体中)出现的this.xxx=xxx中的this指的是new出来的当前实例。
** 虽然通过这个类实例化出来的对象都拥有相同名称的方法,但是不同实例之间的方法是不一样的。
** 在构造函数中 new Fn()执行,如果不需要传递参数,后面的小括号可以省略。
** 在类中出现的出现的this.xxx=xxx中的this指的是类的当前实例。而某一个属性值(方法)中的this需要看方法执行的时候,前面是否有‘.’才能知道this是谁。
** 类有普通函数的一面,在类中var出来的变量只是当前形成的私有作用域中的私有变量而已,它和实例没有任何关系,只有this.xxx=xxx才和实例有关系。
** 在构造函数中浏览器会默认的把实例返回(返回的是一个对象数据类型的值);如果手动return:
如果返回的是基本类型的值,当前实例是不变的;
如果返回的是引用数据类型的值,当前的实例会被自定义返回的值替换掉。
原型模式
基于构造函数模式的原型模式解决了方法或属性公有的问题,把实例之间相同的属性和方法提取成公有的属性和方法,想让谁公有就把他放到构造函数的prototype上即可。
** 每一个函数数据类型(普通函数和类)都有个天生自带的属性:prototype,并且这个属性是一个对象数据类型的值。
** 并且在prototype上浏览器天生给它加了一个属性:constructor(构造函数),属性值是当前函数(类)本身。
** 每一个对象数据类型(普通对象、实例、prototype)也天生自带一个属性:__proto__,属性值是当前实例所属类的原型(prototype)。
Object是Js中所有对象数据类型的基类(最顶层的类);
A) F1 instanceof Object 结果是true,因为f1通过__proto__可以向上级查找,不管多少级最后总能找到object
B) 在object.prototype上没有__proto__;
原型链:过 对象名.属性名 的方式获取属性值的时候,首先在对象的私有属性上查找,如果私有中存在这个属性,则获取私有属性;如果私有没有,则通过__proto__找到所属类的原型(类的原型上定义的属性和方法都是当前实例公有的属性和方法),原型上存在,获取的是公有的属性值;如果原型上也没有。则继续通过原型上的__proto__继续向上查找,一直查找到Object.prototype,如果还没有就返回undefined;
混合模式
混合模式是构造函数和原型模式的结合,它的优势是可以将公有的方法和属性放在原型上,将对象自身的可变的私有属性放在构造函数上,在使用的时候不管创建多少个实例,他们之间公有的方法只占用一份内存。只有私有的属性和方法才会另外开辟一份内存。节省了内存的使用。
function createPerson(name,age){
this.name = name;
this.age = age;
this.say = function(){
console.log(this.name + '---' + this.age)
}
}
createPerson.prototype = {
write:function(){console.log('write')} //实例公有
}