MySQL数据库引擎和数据类型

数据库引擎介绍 前言 1、存储引擎其实就是对于数据库文件的一种存取机制,如何实现存储数据,如何为存储的数据建立索引以及如何更新,查询数据等技术实现的方法。 2、MySQL中的数据用各种不同的技术存储在文件(或内存)中,这些技术中的每一种技术都使用不同的存储机制,索引技巧,锁定水平并且最终提供广泛的不同功能和能力。在MySQL中将这些不同的技术及配套的相关功能称为存储引擎。 3、根据需求可以在表中设置不同的存储引擎。 查看mysql中的引擎 MySQL中常用的几种存储引擎 1.MyISAM存储引擎 存放的位置 MySQL如果使用MyISAM存储引擎,数据库文件类型就包括.frm、.MYD、.MYI,默认存放位置是C:\Documentsand Settings\All Users\Application Data\MySQL\MySQL Server 5.1\data 存放的方式 MyISAM 这种存储引擎不支持事务,不支持行级锁,只支持并发插入的表锁,主要用于高负载的select。 索引的方式 MyISAM也是使用B+tree索引但是和Innodb的在具体实现上有些不同。 该引擎基于ISAM数据库引擎,除了提供ISAM里所没有的索引和字段管理等大量功能,MyISAM还使用一种表格锁定的机制来优化多个并发的读写操作,但是需要经常运行OPTIMIZE TABLE命令,来恢复被更新机制所浪费的空间,否则碎片也会随之增加,最终影响数据访问性能。MyISAM还有一些有用的扩展,例如用来修复数据库文件的MyISAMChk工具和用来恢复浪费空间的 MyISAMPack工具。MyISAM强调了快速读取操作,主要用于高负载的select,这可能也是MySQL深受Web开发的主要原因:在Web开发中进行的大量数据操作都是读取操作,所以大多数虚拟主机提供商和Internet平台提供商(Internet Presence Provider, IPP)只允许使用MyISAM格式。 MyISAM类型的表支持三种不同的存储结构:静态型、动态型、压缩型。 静态型:指定义的表列的大小是固定(即不含有:xblob、xtext、varchar等长度可变的数据类型),这样MySQL就会自动使用静态MyISAM格式。使用静态格式的表的性能比较高,因为在维护和访问以预定格式存储数据时需要的开销很低;但这种高性能是以空间为代价换来的,因为在定义的时候是固定的,所以不管列中的值有多大,都会以最大值为准,占据了整个空间。 动态型:如果列(即使只有一列)定义为动态的(xblob, xtext, varchar等数据类型),这时MyISAM就自动使用动态型,虽然动态型的表占用了比静态型表较少的空间,但带来了性能的降低,因为如果某个字段的内容发生改变则其位置很可能需要移动,这样就会导致碎片的产生,随着数据变化的增多,碎片也随之增加,数据访问性能会随之降低。 对于因碎片增加而降低数据访问性这个问题,有两种解决办法: a、尽可能使用静态数据类型; b、经常使用optimize table table_name语句整理表的碎片,恢复由于表数据的更新和删除导致的空间丢失。如果存储引擎不支持 optimize table table_name则可以转储并 重新加载数据,这样也可以减少碎片; 压缩型:如果在数据库中创建在整个生命周期内只读的表,则应该使用MyISAM的压缩型表来减少空间的占用。 优缺点:MyISAM的优势在于占用空间小,处理速度快。缺点是不支持事务的完整性和并发性。 2.innoDB存储引擎 存储位置 MySQL如果使用InnoDB存储引擎,数据库文件类型就包括.frm、ibdata1、.ibd,存放位置有两个,.frm文件默认存放位置是C:\Documents and Settings\All Users\ApplicationData\MySQL\MySQL Server 5.1\data,ibdata1、.ibd文件默认存放位置是MySQL安装目录下的data文件夹。 innodb存储引擎的mysql表提供了事务,回滚以及系统崩溃修复能力和多版本迸发控制的事务的安全。 innodb支持自增长列(auto_increment),自增长列的值不能为空,如果在使用的时候为空的话怎会进行自动存现有的值开始增值,如果有但是比现在的还大,则就保存这个值。 innodb存储引擎支持外键(foreign key) ,外键所在的表称为子表而所依赖的表称为父表。 innodb存储引擎最重要的是支持事务,以及事务相关联功能。 innodb存储引擎支持mvcc的行级锁。 innodb存储引擎索引使用的是B+Tree 优缺点:InnoDB的优势在于提供了良好的事务处理、崩溃修复能力和并发控制。缺点是读写效率较差,占用的数据空间相对较大。 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 9 min | 📖字数: 4467 words | Luenci

MySQL索引和事务

索引 索引特点:创建与维护索引会消耗很多时间与磁盘空间,但查询速度大大提高! 在关系数据库中,如果有上万甚至上亿条记录,在查找记录的时候,想要获得非常快的速度,就需要使用索引。 索引是关系数据库中对某一列或多个列的值进行预排序的数据结构。通过使用索引,可以让数据库系统不必扫描整个表,而是直接定位到符合条件的记录,这样就大大加快了查询速度。 例如,对于students表: id class_id name gender score 1 1 小明 M 90 2 1 小红 F 95 3 1 小军 M 88 如果要经常根据score列进行查询,就可以对score列创建索引: 1 2 ALTER TABLE students ADD INDEX idx_score (score); 使用ADD INDEX idx_score (score)就创建了一个名称为idx_score,使用列score的索引。索引名称是任意的,索引如果有多列,可以在括号里依次写上,例如: 1 2 ALTER TABLE students ADD INDEX idx_name_score (name, score); 索引的效率取决于索引列的值是否散列,即该列的值如果越互不相同,那么索引效率越高。反过来,如果记录的列存在大量相同的值,例如gender列,大约一半的记录值是M,另一半是F,因此,对该列创建索引就没有意义。 可以对一张表创建多个索引。索引的优点是提高了查询效率,缺点是在插入、更新和删除记录时,需要同时修改索引,因此,索引越多,插入、更新和删除记录的速度就越慢。 对于主键,关系数据库会自动对其创建主键索引。使用主键索引的效率是最高的,因为主键会保证绝对唯一。 MySQL索引的类型 1. 普通索引 这是最基本的索引,它没有任何限制,比如上文中为title字段创建的索引就是一个普通索引,MyIASM中默认的BTREE类型的索引,也是我们大多数情况下用到的索引。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 01 –直接创建索引 02 CREATE INDEX index_name ON table(column(length)) 03 –修改表结构的方式添加索引 04 ALTER TABLE table_name ADD INDEX index_name ON (column(length)) 05 –创建表的时候同时创建索引 06 CREATE TABLE `table` ( 07 `id` int(11) NOT NULL AUTO_INCREMENT , 08 `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , 09 `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , 10 `time` int(10) NULL DEFAULT NULL , 11 PRIMARY KEY (`id`), 12 INDEX index_name (title(length)) 13 ) 14 –删除索引 15 DROP INDEX index_name ON table ...

📅最后更新: 0001-01-01 | ⏲︎时长: 7 min | 📖字数: 3093 words | Luenci

Pandas函数

【python】Pandas中DataFrame基本函数整理 构造函数 DataFrame([data, index, columns, dtype, copy]) #构造数据框1 属性和数据 DataFrame.axes #index: 行标签;columns: 列标签 DataFrame.as_matrix([columns]) #转换为矩阵 DataFrame.dtypes #返回数据的类型 DataFrame.ftypes #返回每一列的 数据类型float64:dense DataFrame.get_dtype_counts() #返回数据框数据类型的个数 DataFrame.get_ftype_counts() #返回数据框数据类型float64:dense的个数 DataFrame.select_dtypes([include, include]) #根据数据类型选取子数据框 DataFrame.values #Numpy的展示方式 DataFrame.axes #返回横纵坐标的标签名 DataFrame.ndim #返回数据框的纬度 DataFrame.size #返回数据框元素的个数 DataFrame.shape #返回数据框的形状 DataFrame.memory_usage() #每一列的存储12345678910111213 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 6 min | 📖字数: 2902 words | Luenci

Python 中的上下文管理器

with 这个关键字,对于每一学习Python的人,都不会陌生。 操作文本对象的时候,我们用 with open ,这就是一个上下文管理的例子。 1 2 with open('test.txt') as f: print f.readlines() 上下文管理器概念 基本语法 1 2 with EXPR as VAR: BLOCK 几个概念 1 2 3 1. 上下文表达式:with open('test.txt') as f: 2. 上下文管理器:open('test.txt') 3. f不是上下文管理器,应该是资源对象。 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 4 min | 📖字数: 1612 words | Luenci

python之百度接口语音识别

python编程之百度接口语音识别 首先在百度AI开放平台上创建语音识别应用,创建完毕应用后,得到系统分配给用户的AppID, API Key, secret Key,均为字符串,用于标识用户,为访问做签名验证。 得到验证后,开始编程 1.记录自己声音 2.将记录下来的音频文件上传至云端 3.解析返回后的结果 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 1 min | 📖字数: 433 words | Luenci

python函数补充

递归函数 递归特性 1.必须有一个明确的结束条件 2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少 3.递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出) 代码演练 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def send(student): if len(student) == 0: return 'All student revice messges' one = student.pop() if one == 'luenci': print('luenci get') send(student) elif one == 'jack': print('jack get') send(student) else: print('xiaoming get') send(student) if __name__ == "__main__": student_list = ['luenci', 'jack', 'xiaoming'] send(student_list) 函数作用域 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def foo(): name = 'luenci' def bar(): name = 'xiaoming' def tt(): print(name) return tt return bar print(foo) print(foo()) print(foo()()) # bar=foo() # tt=bar() # print(tt) # tt() foo()()() out>> <function foo at 0x0000020655A92E18> <function foo.<locals>.bar at 0x00000206577809D8> <function foo.<locals>.bar.<locals>.tt at 0x0000020657780A60> xiaoming 函数式编程 匿名函数 函数声明:lambda 参数:表达式返回值 1 2 3 4 5 6 7 8 9 10 11 def test(x): return x+1 print(test(10)) fun = lambda x:x+1 print(fun(10)) out: 11 11 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 2 min | 📖字数: 801 words | Luenci

Python后端架构演进(转载)

Python后端架构演进 本文转自python社区:https://www.pythontab.com/html/2018/pythonweb_0725/1329.html ...

📅最后更新: 0001-01-01 | ⏲︎时长: 5 min | 📖字数: 2197 words | Luenci

python多线程,并发和锁

多任务 同一个时间有多个任务在执行 python程序默认是单任务 线程 线程概念 线程,可简单理解为是程序执行的一条分支,也是程序执行流的最小单元。 线程是被系统独立调度和分底的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程为其它线程共享进程所拥有的全部资源。 主线程 当一个程序后动时,就有一个进程被操作系统(OS)创建,与此同时一个线程也立刻运行,该线程通常叫做程序的主线程,简而言之;程序后动就会创建一个主线程。 Copy主线程的重要性有两方面: 1)是产生其他子线程的线程; 2)通常它必须最后完成执行比如执行各种关闭动作· ...

📅最后更新: 0001-01-01 | ⏲︎时长: 7 min | 📖字数: 3206 words | Luenci

Python的asyncio(协程)

本文转载自:https://pythonav.com/wiki/detail/6/91/ 1.协程 协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术。简而言之,其实就是通过一个线程实现代码块相互切换执行。例如: 1 2 3 4 5 6 7 8 9 10 11 12 def func1(): print(1) ... print(2) def func2(): print(3) ... print(4) func1() func2() 上述代码是普通的函数定义和执行,按流程分别执行两个函数中的代码,并先后会输出:1、2、3、4。但如果介入协程技术那么就可以实现函数见代码切换执行,最终输入:1、3、2、4 。 在Python中有多种方式可以实现协程,例如: greenlet,是一个第三方模块,用于实现协程代码(Gevent协程就是基于greenlet实现) yield,生成器,借助生成器的特点也可以实现协程代码。 asyncio,在Python3.4中引入的模块用于编写协程代码。 async & awiat,在Python3.5中引入的两个关键字,结合asyncio模块可以更方便的编写协程代码。 1.1 greenlet greentlet是一个第三方模块,需要提前安装 pip3 install greenlet才能使用。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from greenlet import greenlet def func1(): print(1) # 第1步:输出 1 gr2.switch() # 第3步:切换到 func2 函数 print(2) # 第6步:输出 2 gr2.switch() # 第7步:切换到 func2 函数,从上一次执行的位置继续向后执行 def func2(): print(3) # 第4步:输出 3 gr1.switch() # 第5步:切换到 func1 函数,从上一次执行的位置继续向后执行 print(4) # 第8步:输出 4 gr1 = greenlet(func1) gr2 = greenlet(func2) gr1.switch() # 第1步:去执行 func1 函数 注意:switch中也可以传递参数用于在切换执行时相互传递值。 1.2 yield 基于Python的生成器的yield和yield form关键字实现协程代码。 1 2 3 4 5 6 7 8 9 10 11 12 def func1(): yield 1 yield from func2() yield 2 def func2(): yield 3 yield 4 f1 = func1() for item in f1: print(item) 注意:yield form关键字是在Python3.3中引入的。 1.3 asyncio 在Python3.4之前官方未提供协程的类库,一般大家都是使用greenlet等其他来实现。在Python3.4发布后官方正式支持协程,即:asyncio模块。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import asyncio @asyncio.coroutine def func1(): print(1) yield from asyncio.sleep(2) # 遇到IO耗时操作,自动化切换到tasks中的其他任务 print(2) @asyncio.coroutine def func2(): print(3) yield from asyncio.sleep(2) # 遇到IO耗时操作,自动化切换到tasks中的其他任务 print(4) tasks = [asyncio.ensure_future( func1() ), asyncio.ensure_future( func2() )] loop = asyncio.get_event_loop()loop.run_until_complete(asyncio.wait(tasks)) 注意:基于asyncio模块实现的协程比之前的要更厉害,因为他的内部还集成了遇到IO耗时操作自动切花的功能。 1.4 async & awit async & awit 关键字在Python3.5版本中正式引入,基于他编写的协程代码其实就是 上一示例 的加强版,让代码可以更加简便。 Python3.8之后 @asyncio.coroutine 装饰器就会被移除,推荐使用async & awit 关键字实现协程代码。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import asyncio async def func1(): print(1) await asyncio.sleep(2) print(2) async def func2(): print(3) await asyncio.sleep(2) print(4) tasks = [ asyncio.ensure_future(func1()), asyncio.ensure_future(func2())] loop = asyncio.get_event_loop()loop.run_until_complete(asyncio.wait(tasks)) 1.5 小结 关于协程有多种实现方式,目前主流使用是Python官方推荐的asyncio模块和async&await关键字的方式,例如:在tonado、sanic、fastapi、django3 中均已支持。 接下来,我们也会针对 asyncio模块 + async & await 关键字进行更加详细的讲解。 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 21 min | 📖字数: 10099 words | Luenci

python的值传递和引用传递

函数的传参 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。 值传递(pass-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。 引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 In [1]: from ctypes import * In [2]: import os.path In [3]: import sys \# 传入不可变类型 In [4]: def test(x): ...: print("test before") ...: print(id(c)) ...: c+=2 ...: print("test add") ...: print(id(c)) ...: return c In [5]: a = 2 In [6]: id(2) Out[6]: 11496672 In [7]: n = test(a) test before 11496672 test add 11496736 \# 传入可变类型 In [17]: def test2(x): ...: print("test before") ...: print(id(x)) ...: x[0] = 45 ...: print("test after") ...: print(id(x)) ...: return x ...: In [18]: e = [0,1,2,3] In [19]: id(e) Out[19]: 140323019352896 In [20]: g = test2(e) test before 140323019352896 test after 140323019352896 结论:python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合。 如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。 如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象--相当于通过“传值’来传递对象。 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 2 min | 📖字数: 967 words | Luenci

python的协程

可迭代对象 可遍历对象就是可迭代对象 列表、元组、字典、字符串都是可迭代对象 100和自定义myclass 默认都是不可以迷代的 myclass 对象所属的类MyClass如果包含了__iter__()方法,此时 myclass就是一个可送代对象 可送代对象的本质:对象所属的类中包含了__iter__()方法 检测一个对象是否可以送代,用isinstance()函数检测。 迭代器 我们发现选代器最核心的功能就是可以通过next0函数的调用来返回下一个数据值。如果每次返回的数据值不是在一个已有的数据集合中读取的,而是通过程序按照一定的规律计算生成的,那么也就意味着可以不用再依赖一个已有的数据集合,也就是说不用再将所有要迭代的数据都一次性缓存下来供后续依次读取,这样可以节省大量的存储(内存)空间。 举个例子,比如,数学中有个著名的斐波拉契数列(Fibonacci),数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到: 特点 记录遍历的位置 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 8 min | 📖字数: 3684 words | Luenci

Python的模块和类

import导入模块路径问题 存在的问题:当我们把模块文件放到工程文件夹的外部的文件,发现无法正常引入模块 原因:外部的文件夹的路径,没有放到环境变量中。 查看环境变量 1.导入sys模块 2.sys.path 查看环境变量返回值是列表 把自己写的模块的路径加入到环境变量中 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 12 min | 📖字数: 5901 words | Luenci

python的进程,线程和协程对比

概念 进程 ​ 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。 线程 ​ 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。 协程 ​ 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。 三者关系 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 2 min | 📖字数: 733 words | Luenci

python的进程概念

进程 进程概念 进程(Process)是资源分配的最小单位,是线程的容器。 程序是固定不变的,而进程会根据运行需要,让操作系统动态分配各种资源的CPU的时间片轮转,在不同的时间段切换执行不同的进程,但是切换进程是比较耗时的;就引来了轻量级进程,也就是所谓的线程,一个进程中包括多个线程(代码流,其实也就是进程中同时跑的多个方法体) 程序:例xxx.py这是程序,是一个静态的 进程:一个程序运行起来后,代码+用到的资源称之为进程,它是操作系统分配资源的基本单元。 进程状态 工作中,任务数往往大于cpu的核数,即一定有一些任务正在执行,而另外一些任务在等待cpu进行执行,因此导致了有了不同的状态 进程状态 就绪态:运行的条件都已经满足,正在等在cpu执行 执行态:cpu正在执行其功能 等待态:等待某些条件满足,例如一个程序sleep了,此时就处于等待态 进程的创建 - multiprocessing multiprocessing模块就是跨平台版本的多进程模块,提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。 ·创建子进程跟创建线程十分类似,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start0方法后动 Process语法结构如下: Process([group [,target[,name,[args[,kwargs]]]) target:如果传递了函数的引用,这个子进程就执行这里(函数)的代码 args:给target指定的函数传递的参数,以元组的方式传递 kwargs:给target指定的函数传递命名参数 name:给进程设定一个名字,可以不设定 group:指定进程组,大多数情况下用不到 Process创建的实例对象的常用方法: start():后动子进程实例(创建子进程) is_alive:判断进程子进程是否还在活着 join([timeout]):是否等待子进程执行结束,或等待多少秒o terminate:不管任务是否完成,立即终止子进程 Process创建的实例对象的常用属性: name:当前进程的别名,默认为Process-N,N为从1开始递增的整数 pid:当前进程的pid(进程号) linux系统可使用kill命令结束进程 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 9 min | 📖字数: 4160 words | Luenci

python的闭包和装饰器

闭包 引入 函数名是一个特殊的变量,保存了函教的地址和 自定义一个变量可以获取函数地址 自定义变量调用函数 “函数名()” 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def work(): print("我是一个测试函数") ret = work print(ret) print("地址:%X" % id(ret)) print("地址:%X" % id(work)) ret() work() out: <function work at 0x00000161E3091E18> 地址:161E3091E18 地址:161E3091E18 我是一个测试函数 我是一个测试函数 当我们定义函数test1后,函数名test1保存的是函数在内存的首地址函数名就是一个特殊的变量,函数名()调用函数,执行函数体test1()和ret()都会调用函数,并执行函数体 和变量名一样的,函数名数名只是函数代码空间的引用,当函数名赋值给一个对象的时候就是引用传递。 闭包概念 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包 ...

📅最后更新: 0001-01-01 | ⏲︎时长: 5 min | 📖字数: 2165 words | Luenci