【JavaScript】JS高级-面向对象编程

《课前补充》

一、单例设计模式 (Singleton Pattern)

1、单例模式(就是普通对象)

表现形式:
在单例模式中,person1不仅仅是对象名,它被称为“命名空间[NameSpace]”(给堆内存空间起个名字),把描述事务的属性存放到命名空间,多个命名空间是独立分开的,互不冲突。

var person1 = {
name:"",
xxx:xxx
}

作用:
把描述同一件事务的属性和特征进行“分组、归类”(存储在同一堆内存空间中),因此避免了全局变量之间的冲突和污染。

单例模式命名由来:
每一个命名空间都是JS中Object这个内置基类的实例而实例之间是相互独立互不干扰的,所以称之为‘单例’:单独的实例。

2、高级单例模式(就是自执行函数返回的对象,还是一个对象)

高级单例模式:
在给命名空间赋值时,不是直接赋值一个对象,而是先自动执行一个匿名函数,形成一个私有作用域AA(不销毁内存),在AA中创建所需堆内存,并把堆内存地址赋值给命名空间。
好处:
我们完全可以在AA中创建很多内容(变量OR函数),那些需要提供给外面调取的,我们暴露到返回的对象中(模块化实现的一种思想

//惰性函数
var nameSpace = (function(){
var n=12;
function fn(){...};
...
return {newFn:fn};//newFn就是命名空间对象的属性名;
})();

3、基于单例模式实现模块化开发

模块化开发:

  • 团队协作开发时,会把产品按照功能版块进行划分,每一个功能版块有专人负责;
  • 把各个版块之间公用的部分进行提取封装,后期再想实现这些功能,直接调取引用即可(模块封装)。

二、工厂模式(Factory Pattern)
1、工厂模式(借助含参的函数,通过输入不同参数返回一个对应的对象,这些对象的属性名都一样,所以类似工厂流水线

概念:
把实现相同功能的代码进行封装,实现批量生产;
(利用一个固定函数,通过改变参数,生成同类对象)
(后期想要实现这个功能,我们只需要执行函数即可)

function createPerson(name,age){
var obj = {};
obj.name=name;
obj.age=age;
return obj;
}

作用:
高内聚低耦合:减少页面中冗余代码,提高代码的重复使用率。

小贴士:设计模式,就是生成普通对象{}的方式。


面向对象编程:Object Oriented Programming

一、JS是一门编程语言(具备编程思想)
1、【面向对象】

JS\JAVA(编程语言之父) \PHP\C#\Ruby\Python\C++。。。

2、【面向过程】

C语言(编程语言之母)

二、对象、类、实例

整个JS就是基于面向对象设计和开发的语言,我们学习和实战时也要按照面向对象的思想去体会和理解。

1、对象

  • 万物皆对象。

2、类

  • 对象的具体细分。
  • 按照功能特点进行分类:大类、小类。

3、实例

  • 类中具体的一个事物。
  • 拿出类别中的具体一个实例进行研究,那么当前类别下的其它实例也具备这些特点和特征。

三、基于构造函数创建自定义类(constructor)

1、在普通函数执行的基础上“new xxx()”,这样就不是普通函数执行了,而是构造函数执行,当前的函数名称称之为“类名”,接收的返回结果是当前类的一个实例;

  • 自己创建的类一般首字母大写;
  • 这种构造函数设计模式执行,主要用于组件、类库、插件、框架等的封装,平时编写业务逻辑一般不这样处理。
构造函数模式:
function Fn(){
}
Fn();//普通函数执行
var f=new Fn();//构造函数执行,Fn就是类,f是类的一个实例

2、JS创建值的两种方式:字面量方式、构造函数方式(new)

创建引用数据类型时:

  • 相同点:没有本质区别,两种创建方式都是创建对象;
  • 不同点:字面量方式可以直接写属性名;
var obj={};//字面量方式,JS的单例模式
var obj=new Object();//JS的构造函数模式(后端的单例模式)
//不管哪种,创造出来的都是Object类的实例,而实例之间是独立分开的,所以var xxx={}这种模式就是JS中的单例模式。

创建基本数据类型时:

  • 不同点:基于字面量方式创建出来的值是基本数据类型
  • 不同点:基于构造函数 (new)创建出来的值是引用类型(开堆内存)
  • 相同点:没有本质不同,都是当前数据类的实例,都能使用类提供的属性和方法;
var num1=12;
var num2=new Number(12);
console.log(typeof num1);//"number"
console.log(typeof num2);//"object"
//num1、num2都是数字类的实例,只是js表达数字的方式不同,都能使用数字类提供的属性和方法。

3、构造函数执行机制

普通函数执行:

  • 形成一个私有作用域;
  • 形参赋值;
  • 变量提升;
  • 代码执行;
  • 栈内存是否释放。
function Fn(){}
Fn();

构造函数执行机制:

  • 形成一个私有作用域;
  • 形参赋值;
  • 变量提升;
  • 【构造函数独有】在当前私有栈中创建一个对象(开辟一块堆内存,暂时不存储任何东西),让函数执行主体中的this指向这个堆内存;
  • 代码自上而下执行;
  • 【构造函数独有】代码执行完,把之前创建的堆内存地址返回。
function Fn(name,age){
var n=10;
this.name=name;
this.age=age+n
}
var f= new Fn('xxx',20);
console.log(f.n);//undefined,n是私有作用域中的私有变量,不是实例的属性;

在这里插入图片描述

构造函数机制中细节

  • 一般构造函数不写return,浏览器默认返回创建的实例堆内存地址;
  • 如果构造函数中写了return:
    • return返回基本值:返回的结果依然是类的实例;
    • return返回引用值: 则会覆盖返回的实例;
    • 所以构造函数减少使用return,一般用也是只写return:结束代码继续执行的作用,并且不会覆盖返回的实例;
  • Fn;=函数本身、Fn();=普通函数执行;
  • new Fn();构造函数执行创建实例、new Fn;也是构造函数执行创建实例,不能传参了。
function Fn(){
var n=10;
this.m=n;
return;
}
var f=new Fn();

检测实例属于类:
1、instanceof:检测某个实例是否隶属于这个类

console.log(f instanceof Fn);//true
console.log(f instanceof Array);//false
console.log(f instanceof Object);//true,万物皆对象
console.log(1 instanceof Number);//false,所以一般用于检测引用数据类型

检测属性与对象:
1、in方法:检测当前对象是否有(能使用)某个属性(不管当前这个属性是对象的私有属性还是公有属性,都返回true)

console.log('m' in f);//true
console.log('n' in f);//false
console.log('toString' in f);//true

2、hasOwnProperty方法:检测当前对象是否存在某个私有属性

console.log(f.hasOwnProperty('m'));//true
console.log(f.hasOwnProperty('n'));//false
console.log(f.hasOwnProperty('toString'));//false

四、原型链设计模式

原型(prototype):对于函数、类而言;
原型链(_ _ proto _ _):对于对象、实例而言;

JS中引用类型分类:

  • 函数类型:普通函数、所有的类(new 函数时函数就是类,内置类、自己创建的类)
  • 对象类型:普通对象、数组、正则、Math、实例(除了基本类型的字面量创建的值)、函数、万物

原型链机制:
1、所有函数类型数据,都天生自带一个属性:prototype(原型),这个属性的值是一个对象(浏览器默认给它开辟一个堆内存);

prototype属性:用于当前类存储一些公共的属性和方法,供它的实例调取使用。

2、在浏览器给prototype开辟的堆内存中有一个天生自带的属性:constructor,这个属性存储的值是当前函数本身;

Array.prototype.constructor===Array;//true

3、每一个(万物)对象都有一个__proto__的属性,这个属性指向当前实例所属类的prototype。(如果不能确定它是谁的实例,都是Object类的实例)

var arr = new Array();
arr.__proto__===Array.prototype;//true,属性值是个对象
__proto__属性:用于当前实例找到所属类上公有的属性和方法;

4、基类Object的原型(prototype)对象上的__proto__指向null,因为到最底层类,如果指向也是指向自己,没有意义。

console.log(Object.prototype.__proto__);//null;

5、判断当前对象是谁的实例:看原型链(proto)上有哪个类的prototype,就是哪个类的实例;

原型链查找机制:
它是一种基于__proto__向上查找的机制。
1、当实例调用某个属性或方法时,先在自身空间找,找到则结束查找,使用私有的即可;
2、没有找到,就通过实例对象中的__proto__原型链属性,继续向上去所属类的prototype原型属性中找公共方法,找到则使用公有的;
3、再没有找到,就沿着所属类原型中的__proto__属性,一直向上找到基类Object.prototype原型对象,没有找到就不存在:undefined;


【THIS的七种情况】
1、给当前元素的某个事件绑定方法,当事件触发方法执行,方法中的this指向是当前元素本身;
2、方法执行,看前面有没有点“.”,有点,点前面是谁,this就是谁;没有点就是window对象;
3、构造函数执行的时候,方法体中的this就是当前构造函数类的实例;
4、自执行函数一般都是window对象;
5、定时器中this:window对象(通过call传入的window对象);
6、对象方法中this指向对象本身(受定时器影响:window);
7、箭头函数中this,沿作用域链向外找,直到有this定义(不受内部定时器影响)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值