单例模式
1 |
|
这就是单例模式
- 作用: 实现分组,把描述同一个事物的属性和方法放在了同一个空间中,起到了分组的作用,避免了相同变量名之间的干扰
- 在单例模式中,我们把对象名叫命名空间
- 单例模式是我们项目中常用的模式,因为可以利用它进行模块化开发。
1 | //同样都用change方法,为了避免污染 |
工厂模式
为了实现”低冗余,高聚合“的方式,为了批量生产,于是有了工厂模式。
1 |
|
于是,不用像单例模式那样,进行多次的重复的写内容了
1 | var person1 = creatPerson("tom",15); |
特点:
- 把实现相同功能的代码放到一个函数中,以后再想实现这个功能,不需要重新编写代码,只要运行代码即可 >>>我们把这个叫函数的封装 ==低耦合,高内聚==
面向对象的编程语言
- 封装 封装已经实现,就是函数
- 继承 通过原型链实现
- 多态 当前方法和类的多种姿态,包括 重载和重写
多态之重载
方法名相同,参数类型、个数不同。
但是,JS中没有重载,因为当重复写的时候,会被覆盖
1 | function sum (num,num){} |
这是不行的,因此JS是没有重载的(overload)!!
但是可以通过if语句判断,来模拟实现重载(overload)
但是JS有多态,因为有重写
构造函数模式
1 | function CreatPerson (name,age) { |
这就是构造函数设计模式,注意方面里面的this是在调用的时候,才知道指向谁; 而前面的属性上的this,则是在构造函数时,指向实例。 因为构造函数,遇到new 的时候,会自己创建一个this对象,最后再自动返回this对象。
这种,在内建对象中,也有类似的模式,比如创建数组:1
2var arr = [];
var arr1 = new Array();
不管哪组方式,arr都是 Array的实例。
但是注意: 不同实例的方法虽然名称相同,但是是不同的东西,那是各自实例的私有属性,单独的个体。
这个不是单例模式,而是构造函数模式
有的时候,面试官认为这个是单例模式,实际上,这并不是,这个是构造函数模式,也创造了单独的对象,但是在W3C中是可以查询的!
JS中,所有类都是函数数据类型的,它与函数没有很大的区别。只不过在new的时候,会自动创建一个this对象,最后再自动返回。 (注意,实例都是object类型)
构造函数中,this.xxx中的this都是指向实例本身。 在方法中,this需要等待调用才有所指代
p1和p2中都是同一个类的实力,都有相同的方法,但是那是私有属性,是单独个体,不相等。
还有一些特点(扩展)
- var p1 = new CreatPerson 在构造函数中,如果没有参数,括号可以省略. 但是函数执行是不可以省略的
- 如果提前return了一个对象,则会返回新的对象;如果返回一个基本数据类型,则没有任何影响
- 测一个实例是否是一个类的实力
instanceof
1 | console.log(p1 instanceof CreatPerson); //true |
检测数据类型来说,typeof不能准确检测Array的具体类型(只能返回object)。 可以使用istanceof
1 | var arr = []; |
- 检测某一个实例是否有某个属性
in
1 | var obj = { |
注意in无论是共有(prototype)还是私有的,都会返回。 因此,为了检测私有属性,有hasOwnProperty
- 检测某一个属性是否是私有属性
hasOwnProperty
1 | console.log(obj.hasOwnProperty('age')) //true; |
- 检测某一个实例是否有某个属性
in
1 | function hasPubProperty (obj,property) { |
原型链模式
- 数组去重,链式写法
1 | Array.prototype.myUnique = function () { |
- 写一个mySlice方法
1 | Array.prototype.mySlice = function (start,end) { |
原型链批量设置共有属性的小问题
当有多项属性、方法需要在原型链上配置的时候,可以使用批量设置,但是注意,一定要设置好constuctor
1 | Myfun.prototype = { |
记住这张图中的内容,这种设置方式相当于新开辟的一个内存地址来保存prototype,如果没有设置contructor,这个时候,constructor 就会指向Object。
另一方面,如果直接内置的类上批量添加,因为会覆盖原有的很多方法,因此浏览器会屏蔽这种设置方法
1 | Array.prototype = {} |
原型继承
- 最常用的方法;
- 子类B想要继承父类A中所有的属性和方法(私有+共有),让B的prototype = A的实例。
B.prototype = new A
- 原型继承特点,父类私有和共有的都变成了子类私有的方法和属性。
圣杯模式
1 | var inherit = (function () { |
中间类继承
这个比较特殊,主要用在一个问题上:
当遇到argument[]这种类数组时,无法使用数组的方法,很蛋疼。比如想封装一个平均值的方法
1 | function avgFn() { |
显得很麻烦,因为要通过调用Array的方法。所以,这里可以直接修改类数组(同样也是对象)的__proto__
属性1
2arguments.__proto__ = Array.prototype;
...