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_练习题,第一题