在学习面向对象编程的更高级的问题以前,必需要彻底理解函数的做用域和闭包,以及变量访问编程
而后将讨论参数this以及原型委托(prototype delegation),数组
这是实现面向对象编程的JavaScript最主要的两个语言特性,最后,提到写JavaScript类和子类的多种方法闭包
深入地理解JavaScript面向对象编程的特色,以及代码如何在运行时影响存储模型中的解释器函数
这种用法描述了源代码中的范围,在这个范围中可使用变量名引用变量,而不出现访问错误性能
这种做用域的具体规则是 即使不运行代码,也很容易理解,由于它涉及到代码中不一样变量名有意义的区域学习
全局做用域被多个不一样文件共享,使得程序的任意部分均可以和另外一部分交互this
在全局做用域中声明变量以后,就能够在该词法做用域的任意位置引用这个变量了prototype
每当定义一个函数,就会建立一个新的词法做用域,可是比其外层的词法做用域,要多一些限制对象
虽然你仍然能够访问,其外层做用域中的变量,也能够访问在这个内层做用域中定义的变量,blog
但该内层做用域中的变量,没法从该做用域以外访问。
在函数这对花括号范围以外,引用内层做用域中的局部变量,将致使错误
请注意一个容易出错的地方,JavaScript容许给未声明的变量赋值,
它将被自动添加到全局做用域,而非你赋值的这个做用域
这是很很差的行为,由于漏写var关键字,一般是由疏忽形成,而非故意为之
即便你是刻意为之,其余人阅读代码时,也会很是困惑,他们会认为这个是错误疏忽致使的
因此请记住,在任何词法做用域中声明变量时,务必加上var关键词。
如何区分不一样的词法做用域
如何控制它们的规则
当程序运行的时候,就建立一个用于保存变量和变量值的存储系统,
这些内存中的做用域结构就被称为执行环境
执行环境它是在代码运行时才被建立,而不是在代码被输入时,
规则能够控制在程序执行过程当中的不一样点能够访问哪些变量
程序运行时,将会建立内部数据存储,以记录可供不一样函数对象访问的全部变量
因为函数的每一次运行,都彻底独立于此前的任何一次运行,每次函数运行时,就会建立一个新的运行环境
所以每一个词法做用域在运行的过程当中,可能会建立多个内存做用域,也可能一个都没有,这彻底取决于此函数运行了多少次
解释器(interpreter)就开始配置执行环境(execution environment)
第一步是在内存中,建立一个全局做用域环境,以保存全部全局变量,
在这里,解释器为全局做用域建立一个存储系统
此时这里就是解释器当前的执行环境,也就是说这是解释器开始查找变量的区域
解释器会在执行环境中,建立一个新的键值映射,以记录变量名对应的值
如今这个执行环境看起来像是键值对的集合,这与对象有点相似,
会让人误觉得内存做用域和内存对象是一回事
这个类似之处很是具备欺骗性,由于他们都是由解释器彻底分开保存,
并且,在访问执行环境时的不少限制,在访问对象时并不存在
除了它们长得有点相似,其实它们存在于彻底不一样的世界,几乎永不交互
举例说明一下,你毫不可能存储一个包含不少环境的数组,但却能够存储一个包含不少对象的数组
你没法像在对象中遍历键那样,在执行环境中去遍历变量名,所以,虽然它们都是键值数据存储结构
但你只能使用彻底不一样的方式与它们交互
JavaScript开发者会常用闭包, 简单来讲,每一个函数均可以访问,其外围做用域中的全部变量
闭包是指 一些函数经过某种方式,能够随时被访问,即便它的外部代码已经执行完毕
来了解闭包是如何工做,以及咱们该如何使用闭包
在newSaga调用完成后仍然能够访问函数saga?
将saga传入setTimeout
在newSaga中返回saga
saga保存为某个全局变量
以上三种方法均可以帮助咱们在函数newSaga执行完毕后,仍然能访问函数saga