JavaScript(17) - 面向对象,工厂模式,构造函数,闭包,this

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

面向对象的编程思想
面向对象是利用对象进行编程的一种思想, 面向对象的编程思想是相对于面向过程的编程思想而言;
在面向对象的程序设计(英语:Object-oriented programming,缩写:OOP)中, 对象是一个由信息及对信息进行处理的描述所组成的整体, 是对现实世界的抽象. 在现实世界里我们所面对的事情都是对象, 如计算机、电视机、自行车等.
谈到面向对象的语言, 总会涉及到对象的概念以及另一个概念: 类, 一般的面向对象语言都通过类可以创建任意多个具有相同属性和方法的对象. 但是,ECMAScript没有类的概念,所以它的对象与其他基于类的语言中的对象有所不同.

ECMAScript有两种开发模式: 1.面向过程, 2.面向对象(OOP).


提示:以下是本篇文章正文内容,下面案例可供参考

一、面向对象是什么?

面向对象编程(OOP)的三个基本特征是

  1. 封装

  2. 继承

  3. 多态

    封装:
    将属性和方法(数据和功能)封装在一起; //private,protect,public
    继承:
    继承是指这样一种能力:它可以使用现有类的功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
    多态:
    允许让父类的指针分别指向不同的子类, 调用不同子类的同一个方法, 会有不同的执行效果(因为没有类, 所以多态在JS中运用较少)
    多态:重写, 子类重写父类
    重载 (同一个类里的方法有多种实现, 同名(函数名,方法名)不同参)
    Override 重写 (子类重写父类的方法,(加强))
    Overload重载

1.对象的组成

属性(对象的属性) ——变量:状态、静态的
方法(对象的行为) ——函数:过程、动态的

比如:
Animal(动物)是一个抽象类,我们
可以具体到一只狗跟一只羊,而狗跟
羊就是具体的对象,他们有颜色属性,
可以写,可以跑等行为.
对象的组成

2.与面向过程的区别

面向过程:
就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

面向对象:
是把构成问题的事务分解成各个对象,每个对象都有自己独立的属性和行为, 对象可以将整个问题事务进行分工, 不同的对象做不同的事情, 这种面向对象的编程思想由于更加贴近实际生活, 所以被计算机语言广泛应用。
例如: 五子棋游戏
面向过程的设计思路: 分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2到7、最后输出输赢的结果。把上面每个步骤用分别的函数来实现,问题就解决了.
而面向对象的设计则是从另外的思路来解决问题: 整个五子棋可以分为 1、黑白双方(这两方的行为是一模一样的),2、棋盘系统(负责绘制画面),3、规则系统(负责判定诸如犯规、输赢等). 第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定.

两种不同的思路都可以实现相同的功能, 但是面向对象的实现方式更加贴近人类生活(比如: 公司的各个部门, 学校的各个院校等). 在程序的编程中我们把项目中的每个不同的个体看成整体功能的每一个对象, 对象中再包含其属性和方法, 让对象对其属性和方法进行封装, 这样也更加利于后期扩展和维护. 现在几乎所有的语言都支持面向对象的编程思想.

面向过程的语言:

C语言等.

手机百度: 轻应用, 微信小程序
面向对象的语言:
C++, java, C#,
OC, JS, Swift等.
cocos2d(OC): 苹果的游戏引擎
cocos2dx(C++):2d游戏
Linux, Windows, MacOS, Unix,
Android, iOS, Windowphone, 塞班, 黑莓
面向过程的语言:

3.创建对象

创建对象, 并添加对象所应该有的属性和方法
创建对象:

  var obj = new Object();   //也可以使用字面量的方式创建

添加属性:

   obj.name = 'zhangsan';

添加方法:

obj.show = function(){ 
		console.log(this.name); 
	       }

二、工厂模式

为了解决多个类似对象声明的问题,我们可以使用一种叫做工厂模式的方法,这种方法就是为了解决实例化对象产生大量重复代码的问题
fu

nction createObject(name) {	//集中实例化的普通函数
     var obj = new Object();
     obj.name = name;
     obj.show = function(){ 
	alert(this.name)
     }
     return obj;
}

工厂模式解决了重复实例化的问题,但还有一个问题,那就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。

console.log(typeof obj);	//object
console.log(obj instanceof Object); //true

三、构造函数

1.构造函数

构造函数: 使用了new来创建对象的函数就是构造函数.
例如: 声明构造函数Person

function Person(name) {	
      this.name = name;
      this.show = function(){ 
            console.log(this.name);
      }
}
var person = new Person(‘zhangsan’);      //new Person()即可
console.log(person instanceof Person);     //很清晰的识别他从属于 Box

2.构造函数和工厂模式的区别

构造函数和工厂模式的区别:

  1. 构造函数方法没有显示的创建对象( 在内部隐式调用了new Object() );
  2. 直接将属性和方法赋值给 this 对象;
  3. 没有 renturn 语句。

3.构造函数和普通函数的区别:

构造函数与普通函数的唯一区别在于调用它们的方式, 任何函数, 只要通过new操作符来调用, 就可作为构造函数; 而任何函数, 若不通过new操作符调用, 就是普通函数。

例如:

var person = new Person('zhangsan');   //构造模式调用 
Person('zhangsan');   //普通模式调用

类:
ECMAScript 没有类的概念, 我们可以把构造函数理解为就是类.

例如: 在下面的语句中, Person是类, person是对象; 实例化

var person = new Person(‘zhangsan’);   

3.构造函数中的方法

var person1 = new Person(“张三”);   //传递一致
var person2 = new Person(“张三”);   //同上
console.log(person1.name == person2.name);   //true,属性的值相等
console.log(person1.show == person2.show);    //false,方法其实也是一种引用地址

构造函数的注意事项:

  1. 函数名和实例化构造名相同且大写, (非强制,但这么写有助于区分构造函数和普通函数);
  2. 通过构造函数创建对象,必须使用 new 运算符

4.匿名函数

  匿名函数:  就是没有函数名字的函数

普通函数

function m1(){
      console.log("aa");
}
m1(); 

匿名函数

var aa = function(){
      console.log("aa");
}
aa();  //调用匿名函数, 这里的aa是函数名字

函数中包含匿名函数

function bb(){
      return function(){
	 console.log("cc");
      }
}
bb()();  //bb函数中的cc函数

5. 匿名函数的自运行

声明函数的方式一: 普通函数

function m2(){
      console.log("m2");
}
m2();  //需要主动调用

声明函数方式二: 匿名函数的自运行, 不需要主动调用, 会直接执行

(function(){
      console.log("m3");
})();

传参1

var m4 = (function(){
      return function bb(name){  
            console.log(name);
      }
})();
m4(“lisi”);	

传参2

var m5 = (function(a){
      return function(b){              
	console.log(a+b);
      }
})(3)     //把3传给a
m5(4);  //把4传给b

四、闭包

1, 闭包的概念

闭包是这样一种机制:
函数嵌套函数, 内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾回收机制所收回.

垃圾回收机制分为 什么和什么?

这里涉及到几个概念:

  1. 函数嵌套函数
  2. 垃圾回收机制 (内存的自动释放),
  3. 作用域(全局变量和局部变量)

2, 函数嵌套函数

函数嵌套函数

function aa(){
      console.log("aa");
      function bb(){
            console.log("bb");
      }
}
aa();
bb(); //无法直接访问函数内部的函数

3, 垃圾回收机制

JS引擎会在一定的时间间隔来自动对内存进行回收(把内存释放)

JS垃圾回收机制有两种:
1, 标记清除, 2, 引用计数

  1. 标记清除: js会对变量做一个标记Yes or No的标签以供js引擎来处理, 当变量在某个环境下被使用则标记为yes,
    当超出该环境(可以理解为超出作用域)则标记为no, js引擎会在一定时间间隔来进行扫描,
    会对有no标签的变量进行释放(将该变量所占的内存释放掉)

  2. 引用计数: 对于js中引用类型的变量, 采用引用计数的内存回收机制, 当一个引用类型的变量赋值给另一个变量时, 引用计数会+1,
    而当其中有一个变量不再等于值时, 引用计数会-1, 如果引用计数为0, 则js引擎会将其释放掉

4, 作用域

作用域(全局变量和局部变量)

//全局变量: a的作用域是全局, 内存不会被释放
var a = 1;
function m1(){
      a++;
      console.log(a);
}
m1(); //2
m1(); //3

//局部变量: b的作用域是函数m2, 调用完函数m2后就会被释放, 而在m2内部的局部变量无法被外部调用
function m2(){
      var b = 1;
      b++;
      console.log(b);
}
m2(); //2
m2(); //2
//console.log(b);

4, 闭包的写法

写法

//函数嵌套函数
function aa(){
      var a = 1;
      function bb(){
            console.log(a);
      }
      return bb;  //返回函数bb
}
//console.log(a);   //无法直接访问a
var cc = aa();       //aa函数被执行了, 并返回了bb给cc
cc();      //可以打印出a, 说明a并没有被释放

前面的函数简化一下:

function aa(){   
      var a = 5;
            return function(){
            a++;
            console.log("a=" + a);
      }
}
var cc = aa();  //aa函数被执行了, 并返回了内部的匿名函数给cc
cc();  //a=6
cc();  //a=7
cc();  //a=8

5,闭包有两大特点

相比全局变量和局部变量, 闭包有两大特点 :
1, 闭包拥有全局变量的不被释放的特点
2, 闭包拥有局部变量的无法被外部访问的特点

闭包的好处:

  1. 可以让一个变量长期驻扎在内存当中不被释放
  2. 避免全局变量的污染, 和全局变量不同, 闭包中的变量无法被外部使用
  3. 私有成员的存在, 无法被外部调用, 只可以自己内部使用

6, 闭包的应用

例如: 在循环中直接找到对应元素的索引

for (var i=0; i<aLi.length; i++) {
      (function(index){
            aLi[index].onclick = function(){
                  console.log(index);
            }
      })(i);
}

或者:
在for循环过程中将i传递到函数表达式中的index, index会成为一个局部变量,不会被释放,长期驻扎在内存中

for (var i=0; i<aLi.length; i++) {
       aLi[i].onclick = (function(index){
             return function(){
                   console.log(index);
             }
       })(i);
}

五、this

1, this关键字是什么

JS中的this到底指的是哪个对象?

先来看一段代码:

target.onclick = function() {
      console.log(this);
}

这里的this会打印出什么?
很明显, 这里的this指的是target本身

JS中的this到底指的是当前对象, 那么这个当前对象指的又是什么?

this在不同的代码环境下代表的对象是不一样的, 就像说话的语义一样:
如果有个人对你喊 : 开!
当你手里有一把枪, 你会开枪;
当你坐在车上, 你会开车;
当你站在阳台上, 你会开窗…

this关键字: 指的是此刻正在运行的函数所依附的对象

target.onclick = function() {
      console.log(this);
}
var obj = {};
obj.test = target.onclick;
target.onclick();  //结果是target对象
obj.test();  //结果是obj对象

this好比一句话, 出自不同人之口, 代表的人就不一样
A和B吵架 ; A对B说: “老子要砍死你! ” , 这里的老子指A
B对A说: “老子要弄死你! ”, 这里的老子指B

2, 定时器中的this

定时器setInterval()中的匿名函数是在被全局中的window对象调用的, 所以里面的this指的就是window对象, 而不是box

box.onclick = function() {
        console.log(this);     //box对象
        setInterval(function(){
                console.log(this); //window对象
        }, 2000);			
        setTimeout(function(){
                console.log("setTimeout:" + this);  //window对象
        }, 3000);				
}

3, 构造函数中的this

   **在构造函数中的this是使用new关键字创建的那个对象, 

下面的this是box对象**

function Box(name) {	
      this.name = name;
      this.show = function(){ 
            console.log(this.name);
      }
}
var box = new Box('zhangsan');  

4, 普通函数中的this

普通函数调用

function func() {	
        console.log(this);
}
func();  //window对象

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript中的闭包是指一个函数能够访问并使用其外部作用域中的变量,即使在该函数被调用之后,该外部作用域的上下文已经销毁。简单来说,闭包是指一个函数保留了对其词法作用域的引用,使得函数可以访问和操作外部作用域的变量。 在JavaScript中,闭包可以通过函数嵌套来创建。当一个函数在内部定义了另一个函数,并且内部函数引用了外部函数的变量,那么内部函数就形成了闭包闭包函数可以访问和修改外部函数的变量,即使在外部函数执行完毕后,这些变量依然存在于闭包函数的作用域中。 以下是一个闭包函数的例子: ```javascript function outerFunction() { var outerVariable = 'Hello'; function innerFunction() { console.log(outerVariable); } return innerFunction; } var closure = outerFunction(); closure(); // 输出 'Hello' ``` 在这个例子中,内部函数`innerFunction`形成了闭包,它可以访问和使用外部函数`outerFunction`中的变量`outerVariable`,即使`outerFunction`执行完毕后,闭包仍然可以访问和操作`outerVariable`的值。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JavaScript中的闭包](https://blog.csdn.net/qq_44482048/article/details/128714553)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [轻松学习Javascript闭包函数](https://download.csdn.net/download/weixin_38628429/13018893)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [JavaScript闭包](https://blog.csdn.net/qq_57586976/article/details/127678306)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值