面向对象
* 单利模式
* 工厂模式
* 构造函数模式
* 原型模式
* call,apply,bind
* 继承
面向对象
对象:指的是基于对象 类 实力来研究的
类:是对对象的具体细分
实例:某一个类别种具体的事物
对象的特征:属性 方法
面向对象的特点
面向对象思想也叫(oo思想 oop思想)
1:封装:对同一个功能的函数,只能封装一次,以后遇到此功能只需要调用即可,无需重写。避免大量亢余代码:低耦合,高内聚(单利模式 工厂模式 构造函数模式 原型模式)
2:继承:子类可以继承父类的属性跟方法
3:多态:多种形态 重写 重载
重载:js没有严格意义上的重载,有类似的功能,传不同的参数,可以实现不同的功能
重写:子类可以重写父类的属性和方法
单利模式
单例模式
1:单例模式;把描述同一个对象的属性和方法,都放在同一个命名空间下避免全局变量的污染
和冲突
单利模式,解决了变量冲突,实现了分类分组
命名空间: 在单利模式中,我们的对象名叫做命名空间,单利模式把实现和描述同一件事物的属性和方法进行分类归纳,然后汇总的同一个命名空间下,不同的命名空间互不冲突
把描述這个对象的属性跟方法,所存放的空间,起个名字
2:单利模式的本质;普通对象
模块化开发;单利模式就是最简单的模块化开发
对于一个大型的项目,会分配给不同的工程师,进行同步开发;等所有人都开发完成之后,最后
进行代码合并
3:关于单利模式的优缺点
1 优点:单利模式可以避免全局变量的污染和冲突
2;单利模式是最简单的模块开发
1)本模块之间的相互调用 ;this.属性名
2)不同模块之间的相互调用;模块名.属性名
2 缺点:会存在大量的大量亢余代码
4:解决措施;工厂模式
這三种都是单例模式
1:var personRender={};
2:var studentRender=(function{
return {}
})()
3:function Person(){ } var p=new Person()
工厂模式
工厂模式的本质-封装
1;引进原材料 创建一个空对象{} new Object()
2;加工 给对象添加属性和方法
3;输出产品 输出已经加工后的对象;
5;如果想让工厂模式的调用方式,跟系统类的调用方式一样需要做两步
1)首字母大写
2)添加new
构造函数模式
函数:
object 和function 都有一个自带的name值指向自己
length是形参的个数
构造函数跟工厂模式的区别
1)类调用的时候;
(1)工厂模式是普通函数的调用 person()
普通函数执行的时候没返回值,那么是undefined
(2)构造函数;new首字母大写() new person
构造函数执行的时候,没返回值,那么是person{} 這个对象
构造函数模式执行:
- 1:创建一个私有作用域 - 进行形参赋值- 预解释
- 2:new 这样执行,在预解释完成后,浏览器默认的在私有作用域中,创建一个对象,函数中this指向這个对象
- 3:在和普通函数一样,代码从上到下执行
- 4:new这样执行,在代码执行完成之后,会默认的把第二步种(没有return也会默认返回一个对象),我们创建的這个对象返回
2)函数体内的不同
工厂模式(普通函数);三步 1)创建对象 2)加工对象 3)返回对象
构造函数;一步加工对象
7)关于构造函数的小细节
1;构造函数的this都是实例
2;构造函数中存放的都是私有的属性和方法
3;实例只跟构造函数种的this.xxx有关,跟var没任何关系
4;构造函数中,系统默认为我们创建一个实例,并且默认返回一个实例
5:通过构造函数创建出来的实例都是相互独立的个体,互不影响,而在构造函数体中写的this,xx=xx 都相当于给当前实例增加自己的私有属性
不建议自己手动返回对象,如果非要手动返回的话 return 构造函数最好不要写return
1)返回的是基本数据类型,无效,实例该有的属性和方法仍然有
2)返回的是引用数据类型,以前给实例添加的属性和方法都无效了
8;构造函数;实例和类打交道
9; new Student() new Student這个new出来的实例都会执行 在new一个实例的时候,如果不需要传参()可以省略
10;学习构造函数的目的
1)了解系统类的构成
2)自己定义一个类,并且创建一个实例;
11: 类是函数数据类型
实例是对象数据类型
原型模式
原型模式的基础知识:
1.每个函数数据类型(普通函数,类(内置类,自定义类)构造函数)上,都有一个属性,
叫做prototype,prototype是个原型;他的属性值是个对象
2.prototype这个对象上,存放的都是公有的属性和方法,
他天生自带一个属性
constructor(构造函数),指向当前这个构造函数;
3.每个对象数据类型(实例,prototype,普通对象)上,
都有一个属性叫做__proto__,指向当前实例所属类的原型;
14)Object.prototype上的方法:
in验证某一个属性是否属于這个对象,不管是私有的还是公有的,只要有,返回的结果都是true
hasOwnProperty():
判断是否为对象的私有属性
obj1.isPrototypeOf(obj2) :obj1是否在obj2的原型链上;
propertyIsEnumerable:是否为可枚举的属性
15)__proto__原型链:
如果想查找:对象.属性名
1)先看该对象的私有空间中是否有,如果有,说明这个属性是私有属性;
2)如果没有,通过__proto__继续往当前实例所属类的原型上找,找到了,说明是公有属性;
3)找不到继续通过__proto__一直往上找,找到基类Object.prototype原型上,还没有的话undefined;
__proto__原型链this:
他们的this指向不同,但是查到找的结果都一样
p1.hasOwnproperty() p1
p1.__proto__.hasOwnproperty() p1的原型
p1.__proto__.__proto__hasOwnproperty() object
16)
1:所有的函数数据类型,都是
function這个类的实例
2:所有的对象都是object這个基类的实例
3)function和object的关系:
(1)object instanceof function ===>true 所有类都是function這个类的实例
(2)function instanceof function ===>true 所有的对象都是object這个基类的实例
(3)object.prototype 是function.prototype的爹 当他的身份是函数的时候,有prototype
(4)object.prototype是function_proto_的爹 当他为对象的时候,是有這个—proto—
4:
函数的三种角色
(1):普通函数:形成私有作用域-形参赋值-预解释-代码从上到下执行 以及内存和内存的释放
(2):构造函数:实例 类 原型 —proto—
(3):对象:跟普通对象的功能一模一样
1;在ie浏览器下,禁止用户通过__proto__去修改实例上公有的属性和方法
这上ie浏览器的自我保护机制
2;在所有的浏览器下,禁止用户批量修改,实例上的公有属性和方法
但是我们可以通过,类.prototype.xx进行一个个的修改
一个个修改在标准浏览器下,有两种方式
1)实例.__proto__.属性名
2)类.prototype.属性名
3;
- 链式操作,我们关注的是前一个函数执行完成的返回值,返回的是个数组,后续就跟数组的方法,
- 链式写法:需要保证每一次执行方法返回的结果依然是当前类的一个实例,这样就可以继续调取原型上的方法了
返回的是个数字,后续就跟数字的方法
num.toFixed(2)保留小数个数2位
4;应有的条件反射
构造函数;放的都是私有的属性和方法
prototype;放的都是共有的属性和方法
类.prototype自己赋值一个对象,
constructor一定会出问题
5;in判断某个属性是否为对象私有+公有属性 加引号
6;数组去重;
1.思路1;双重循环
拿当前项跟他后面的每一项,如果相同,删除其中一个,一定要预防数组塌陷 ;
2;思路2;创建新数组
当新数组中没有重复的时候,才给新数组种放
3;思路3;利用对象不重名的特性
当对象中没有该属性的时候,赋值为1
当对象中已经有了该属性的时候,进行累加
注意;两个条件中,只走一个1)continue 2)if...else...
7;属性操作
注意;判断属性是否在对象上,属性名一定要加引号,否则会把它当作变量,报错
1;in判断某个属性是否为对象私有+公有属性 加引号
2;obj.hasOwnproperty(属性名)判断是否有对象的私有属性 propertyIsEnumerable也可以用
3;自己封装;hasOwnproperty;判断属性是否为对象的
8;原型批量设置
Fn.prototype=
{
手动添加一个:constrouctor:Fn
x:10,
y:11,
c:22
}
call,apply,bind
call:
1:call在Function.prototype原型上找:公有属性和方法
- f1.call(f2);
函数中没有this的时候,
call前面的函数f1执行
- f1.call.call.call.call.call.call.call.call(f2);
-
call(f2) 他先执行, 然后将前面f1.call改成f2.call()执行
函数中没有this的时候 f2這个函数执行
2:f1.call(obj);
严格和非严格
1: 非严格模式下如果
call的第一个参数,不传或者传的是undefined/null,方法种的this是window
2:严格模式下,如果call中第一个参数不传就是undefined,其余call中的第一个参数是啥就是啥,如果是null就是null,如果传的的undefined就是undefined 'use strict'
3:call的第一个参数,用来改变call前面这个实例中的this关键字;
4:call改完this指向,传完参数之后,让call前面的函数立即执行;
3:call的作用改变this指向
call的第一个参数,用来改变call点前面的函数中this指向
call的第二个参数开始,相当于给fn的形参从左往右赋值
1)call,apply,bind区别:
call apply 都是在改完this指向,传完参数之后,让前面的函数立即执行
区别;第二个参数不同;call从第二个参数开始,一个个写参数,
apply;第二个参数是个数组;
2)bind;
属于预处理机制;先把bind前面的函数种的this改了,参数传了,
然后返回一个修改后的函数;在需要的时候,手动调用 函数执行的时候,他才执行
继承
子类可以继承父类的属性跟方法
1:
call继承
call:把父类的私有的属性和方法,都继承给了子类私有的
2;冒充继承
把父类私有+公有的属性和方法,都继承给子类私有的(for var a in f1 )
3;
原型链继承
把父类私有+公有的属性和方法,都继承给子类公有的
4;拷贝继承
call继承+extend继承(参数里面,后面继承前面的,)
私有继承私有的,公有继承公有的
5:混合继承:子类私有有父类私有的; 子类公有也有父类私有的
原型链继承:把父类私有+公有,都给了子类公有的
call继承把父类私有的给了子类私有的;
6:混合继承