1. 单例模式
对像数据类型的作用
把描述同一个事物 (同一个对像) 的属性和方法放在同一个内存空间下, 起到了分组的作用, 这样不同的事物之间的属性即使属性名相同, 相互也不会起冲突, 我们把这种分组编写代码的模式叫做'单例模式'.
例:
- var personal1 = {
- name: 'ant',
- age: '20'
- };
- var personal2 = {
- name: '张飞',
- age: '32'
- }
- // 在上面单例模式中我们常把 personal1 和 personal2 叫做命名空间. 单例模式主要解决了分组的作用, 但是不能批量生产
2. 工厂模式
把实现同一件事情的相同代码方到同一个函数中. 工厂模式也称'函数的封装'
'低耦合高内聚': 减少页面的冗余代码, 提高代码的重复利用率.
例:
- function createPersonal (name, age) {
- var obj = {};
- obj.name = name;
- obj.age = age;
- obj.personal = function () {
- console.log('name'+ this.name + ';' + 'age' + this.age)
- }
- return obj
- }
- var p1 = createPersonal('ant', 35);
- p1.personal()
3. 构造函数模式
构造函数模式的目的是为了创建一个自定义类, 并且创建这个类的实例. 构造函数模式拥有了类和实例的概念, 并且实例和实例之间是相互独立拉开的, 实例识别
js 中的所有类都是函数数据类型的, 它通过 new 执行变成了一个类, 但是本身也是一个普通函数; js 中所有的实列都是对象数据类型的.
3.1 构造函数和工厂模式的区别:
(1)执行的时候
1.1 普通函数的执行 createPersonal()
1.2 构造函数模式 new CreatePersonal() 通过 new 来执行后, CreatePersonal 就是一个类了
// 函数的返回值 p1 就是 CreatePersonal 的一个实例
(2)在函数代码执行的时候
相同: 都是形成了一个私有的作用域, 然后形参赋值 ->预解释 ->代码从上到下执行(类和普通函数一样, 有普通函数的一样)
不同: 在代码执行之前, 不用手动的创建对象了, 浏览器会默认创建一个对象数据类型的值(这个对象其实就是我们当前的一个实例). 接下来代码从上到下执行, 以前当前实例为执行的主体(this 就是当前的实例), 然后分别把属性名和属性值赋值给当前的实例. 浏览器会默认的把创建的实例返回.
3.2 在构造函数模式中 new Fn()执行, 如果 Fn 不需要传递参数的话, 后面小括号可以省略.
例:
- function CreatePersonal (name, age) {
- // 浏览器默认创建了 p1, 这时候 this 就是指的 p1
- this.name = name;
- this.age = age;
- this.personal = function () {
- console.log('name'+ this.name + ';' + 'age' + this.age)
- }
- // 浏览器把
- }
- var p1 = new CreatePersonal('ant', 35);
- p1.personal()
- var p2 = new CreatePersonal('dog', 10);
- p2.personal()
- // console.log(p1.personal === p2.personal) // false
- // 在类中给实例增加的属性 this.xxx = xxx 属于当前实例的私有属性, 实例和实例之间是单独的个体, 所有私有的属性之间是不相等的
拓展:
- // js 当中所有的类都是函数数据类型的, 它通过 new 执行变成了一个类, 但是它本身也是一个普通的函数
- // js 当中所有的实例都是对象数据类型的
3.4 类有普通函数的一面, 当函数执行的时候, var num 是当前函数形成的私有的作用域中的私有变量, 它和 f1 这个实例没有任何关系; 只有 this.xxx = xxx 才相当于给 f1 这个实例添加的私有的属性和方法, 才和 f1 有关系
例:
- function Fn () {
- var num = 100;
- this.x = 200;
- this.Fn1 = function () {
- console.log(this.x)
- }
- }
- var f1 = new Fn;
- console.log(f1.num) // undefined
3.5 在构造函数模式中, 浏览器会默认的把我们的实例返回(返回一个对象数据类型的值); 但是如果我们自己手动加一个 return 返回:
3.5.1 返回一个基本的数据类型, 当前的实例不变; 例如 return 200
3.5.2 返回一个引用数据类型的值, 当前实例会被自己返回的给替换掉例如 return {name:'ant'}, 这时候 f2 是对象{name: 'ant'}
3.6 检查某一个实例是否属于这个类, 用 instanceof 检测
// console.log(f1 instanceof Fn) //true
3.7 in 是检测一个属性是否属于这个对象 attr in object
console.log(Fn1 in f1) // true
hasOwnProperty: 用来检测某一个属性是否为这个对象的私有的属性, 这个方法只能检测私有的属性
- console.log(f1.hasOwnProperty('Fn1'))
- function Fn () {
- var num = 100;
- this.x = 200;
- this.Fn1 = function () {
- console.log(this.x)
- }
- return 200
- }
- var f1 = new Fn;
- console.log(f1.num) // undefined
- console.log(f1) // 还是 this.x =200 ;this.Fn1 = function() {}
- function Fn1 () {
- var num = 100;
- this.x = 200;
- this.Fn1 = function () {
- console.log(this.x)
- }
- return {name: 'ant'}
- }
- var f2 = new Fn1;
- console.log(f2) // 返回 {name: 'ant'}
4. 原形链模式
4.1 每一个函数数据类型 (普通函数, 类) 都有一个天生自带的属性: prototype(原型), 并且这个属性是一个对象数据类型的值.
4.2 并且在 prototype 上浏览器天生给它加上一个属性 constructor(构造函数), 属性值是当前函数 (类) 本身.
4.3 每一个对象数据类型 (普通对象, 实例, prototype...) 也天生自带一个属性: proto, 属性值是当前实例所属类的原型(prototype)
- function Fn () {
- var num = 100;
- this.x = 200;
- }
- Fn.prototype.fn1 = function () {
- console.log(this.x)
- }
- var f1 = new Fn;
- console.log(Fn.prototype.constructor === Fn) // true
备注:
- // 1.Object 是所有数据类型的基类(最顶层的类)
- // 1.1 f1 instanceof Object ->true 因为 f1 通过 proto 可以往上级查找, 不管多少级, 最后总能找到 Object
- // 1.2. 在 Object.prototype 上没有 proto 这个属性
- // 2. 原型链模式
(1)通过 对象名. 属性名 的方式获取属性值的时候, 首先在对象的私有属性上进行查找, 如果私有中存在这个属性, 则获取的是私有属性的值; 如果私有的没有, 则通过 proto 找到所属类的原型(类的原型上定义的属性和方法都是当前实例公有的属性和方法), 原型上存在的话, 获取的是公有的属性值; 如果原型上也没有, 则继续通过 proto 继续向上查找, 一直找到 Object.prototype 为止. 这种查找的机制就是原型链模式
- function Fn () {
- var num = 100;
- this.x = 200;
- this.sum = function(){}
- }
- Fn.prototype.fn1 = function () {
- console.log(this.x)
- }
- Fn.prototype.sum = function () {}
- var f1 = new Fn;
- var f2 = new Fn;
- console.log(Fn.prototype.constructor === Fn) // true
- f1.sum === f2._proto_.sum // false f1.sum 是私有的, f2 找的 sum 是公有的
- f1.sum === Fn.prototype.sum // false f1.sum 是私有的, Fn 找的 sum 是公有的
- f1.sum = function () {
- // 修改自己私有的 sum
- }
- f1._proto_.sum = function () {
- // 修改所属类原型上的 sum, 修改公有的
- }
- Fn.prototype.sum = function () {
- // 修改公有的 sum
- }
来源: http://www.jianshu.com/p/3d7ec5eee21f