0 / 题
(1)第一题
var a = {n: 1};var b = a;a.x = a = {n: 2};console.log(a.x);console.log(b);
△ 援用数据类型:object
(2)第二题
var x = [12, 23];function fn(y) { y[0] = 100; y = [100]; y[1] = 200; console.log(y);}fn(x);console.log(x);
△ 援用数据类型:function
这些题是不是很简略?咱们次要看逻辑:
1 / 援用数据类型:object
在Web浏览器中执行JS代码,会开拓一块栈内存来作为执行环境:ECStack
(Execution Context Stack)
会开拓一块栈内存供全局代码执行:全局执行上下文 EC(G)
(Execution Context Global),还有其余的上下文:函数公有执行上下文、块级公有上下文…… 本人管好本人那一摊的代码执行内容
造成的执行上下文都会 进栈 到执行环境栈中运行.公有上下文会在不被占用时出栈开释,浏览器的回收机制GC
.当浏览器敞开时,全局执行上下文就会出栈开释了
△ 图2.1_第一题,简图
GO:全局对象 Global Object ,并不是VO(G)全局变量对象 Variable Object Global
全局对象,它是个对象,它就是个堆内存,浏览器关上一加载页面就默认开拓的堆内存。
浏览器提供的一些供JS调用的API,在Web浏览器中,全局对象能够通过window
来拜访的
留神:运算符优先级,要多看看多比划比划
留神:根本数据类型值间接存储在栈内存中,援用数据类型值存在堆内存中
2 / 援用数据类型:function
var x = [12, 23];function fn(y) { y[0] = 100; y = [100]; y[1] = 200; console.log(y);}fn(x);console.log(x);
△ 函数执行
(1)第二题,简图
△ 图2.2_函数执行
△ 图2.3_数组的格局:键值对
(2)创立函数
创立函数的步骤:【和创立变量区别不是很大,函数名就是变量名】
① 独自开拓一个堆内存:16进制地址,函数堆内存中存储的是函数体中的<u>代码字符串</u>
② 创立函数的时候,就申明了它的作用域[[scope]],也就是所在的上下文环境
③ 把16进制地址(16进制以0x
结尾)寄存到栈中,供函数名变量名关联援用即可
只创立函数,不执行函数,没啥意义,那就是一堆字符串。
函数执行的目标:把创立函数的时候在堆内存中存储的 <u>代码字符串</u> 变为代码执行
代码执行肯定会有一个执行的环境,它的下级执行上下文,是函数创立的中央
函数执行会造成一个全新的、公有的执行上下文,在公有上下文中,也有寄存本人变量的对象:AO(Active Object 流动对象),它是VO的一种。
变量对象: ① 在全局上下文中:VO ② 在公有上下文中:AO
实参都是值。形参是变量。
fn(x)
:执行函数fn,把全局上下文中存储的x
变量关联的值(0x000001),作为实参传递给函数的形参变量
(3)执行函数
执行函数做了哪些事件:
1、造成了一个全新的、公有的执行上下文EC(xxx)
2、以后公有的上下文中,有一个寄存此上下文内申明的变量的中央 AO(xxx)
公有变量对象
① 形参变量
② 以后上下文中申明的变量
3、进栈执行
4、代码执行之前还要解决很多事件:
① 初始化作用域链
[[scope-chain]]:<以后本人的上下文, 下级上下文(创立函数时造成的作用域)>
(作用域链有中间,一头是本人执行的上下文,另一头是本人创立时所在的上下文)
即:以后函数的下级上下文是创立函数所在的上下文,就是作用域
当前再遇到函数内的代码执行,遇到一个变量,首先看是否为本人上下文中的公有变量(看AO中有没有,有,是本人公有的;没有,不是本人公有的)。如果是公有的变量,则以后变量的操作和外界环境中的变量互不烦扰(没有间接关系);如果不是本人的公有变量,则依照作用域链,查找是否为其下级上下文中的公有变量.....始终找到EC(G)全局上下文为止:作用域链查找机制
② 初始化this....
③ 初始化arguments....
④ 形参赋值:形参都是公有变量,放在AO中的。如果不传递实参,默认值是undefined
⑤ 变量晋升....
5、代码自上而下执行
6、.....
7、个别状况下,函数执行所造成的公有上下文,进栈执行完后,会默认出栈开释掉
【公有上下文中存储的公有变量和一些值都会被开释掉,目标:为了优化内存空间,缩小栈内存的耗费,进步页面或者计算机的处理速度......】
不能出栈开释:以后上下文中某些内容(个别是堆内存地址)被以后上下文的内部的事物占用了,则无奈出栈开释。一旦被开释,前期内部事物就无奈找到对应的内容了
留神: 屡次函数执行,会造成多个全新的、公有执行上下文,这些上下文之间没有间接的关系
(4)闭包
个别,很多人认为:大函数返回小函数是闭包。
这只是闭包机制中的一种状况。
闭包:函数执行造成一个公有的执行上下文,此上下文中的公有变量,与此上下文以外的变量互不烦扰;也就是以后上下文把这些变量爱护起来了,咱们把函数的这种爱护机制称为闭包。
闭包不是具体的代码,而是一种机制。
个别状况下,造成的公有上下文很容易被开释掉,这种爱护机制存在工夫太短了,不是谨严意义上的闭包。有人认为,造成的上下文不被开释,才是闭包。此时,不仅爱护了公有变量,而且这些变量和存储的值也不会被开释掉,保留起来了。
闭包的作用:① 爱护 ② 保留
利用闭包的两个作用,能够实现高阶编程技巧,当前再说~
3 / 练习题
(1)第一题
var x = 100;function fn() { var x = 200; return function(y) { console.log(y + x++); }}var f = fn();f(10);f(20);
△ 第一题
i++
后加
△ 图2.4_后加
(2)第二题
let a=0, b=0;function A(a){ A=function(b){ alert(a+b++); }; alert(a++);}A(1);A(2);
△ 第二题
(3)第三题
let x = 5;function fn(x) { return function(y) { console.log(y + (++x)); }}let f = fn(6);f(7);fn(8)(9);f(10);console.log(x);
△ 第三题
- end -
好啦,好啦,碎碎念了很多:
全局执行上下文、创立函数、作用域、执行函数、公有执行上下文、AO和VO、实参、形参、作用域链
△ 图2.5_练习题,第一题