import { CodeSurferLayout } from 'code-surfer'; import { Appear } from 'mdx-deck'; export { nightOwlFull as theme } from 'code-surfer/themes';
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
为什么第四行代码alert(value)
会弹出undefined
呢?
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
}
alertValue();
- 执行上下文
- 作用域
- 作用域链
- var变量、函数提升
- 怎么查找到变量?
- 最后,讲讲闭包
execution context
有哪些执行上下文?
- 全局
- 函数(又称之为本地)
- 块(block)
- eval
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
function inner() {
alert(value);
}
inner();
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
function inner() {
alert(value);
}
inner();
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
function inner() {
alert(value);
}
inner();
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
function inner() {
alert(value);
}
inner();
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
function inner() {
alert(value);
}
inner();
}
alertValue();
var value = 'global value';
function alertValue() {
alert(value);
var value = 'local value';
alert(value);
function inner() {
alert(value);
}
inner();
}
alertValue();
- 红色的区域是全局执行上下文
- 只能有一个全局执行上下文
- 两个黄色框是两个函数执行上下文
- 只要调用一次函数,就创建了一个函数执行上下文
- 所以,可以有无数个函数执行上下文
两阶段:
- 阶段一:创建阶段。创建的是执行上下文。
- 创建作用域链
- 创建 var 变量、内部函数、函数入参
- 准备this
- 阶段二:一行一行执行代码。
JS 解释器执行代码的过程,会带来一个很让人费解的现象:
可以在 var 变量、函数定义之前使用 var 变量和函数;
在 var 变量之前使用 var 变量,变量值是 undefined。
let和const就横空出世啦!
通过let和const定义的变量不参与到创建阶段。
alert(value);
let value = '123';
alert(value);
let value = '123';
使用**{}**就可以定义一个块作用域。
- var 变量是跨块级作用域的。
- let, const 变量只能在块作用域中使用。
{
let value = 0;
console.log(value);
}
console.log(value);
{
let value = 0;
console.log(value);
}
console.log(value);
{
let value = 0;
console.log(value);
}
console.log(value);
{
let value = 0;
console.log(value);
}
console.log(value);
{
var value = 0;
console.log(value);
}
console.log(value);
{
var value = 0;
console.log(value);
}
console.log(value);
{
var value = 0;
console.log(value);
}
console.log(value);
{
var value = 0;
console.log(value);
}
console.log(value);
if
、for
、while
、do
这些带有**{}**的语句都会创建块作用域。
执行上下文就是一个 JavaScript 对象,其中有三个最重要的属性:
- scopeChain - 作用域链
- variableObject - 变量对象:包括函数入参、内部变量、内部函数定义
- this
作用域链类似链表的一个结构:
以alertValue
和inner
函数为例。
**console.dir(fn)**会输出更详细的函数信息,包括一些解释器信息。
展开 global scope,发现:
Chrome 在创建函数时,会将当前执行上下文的作用域链与这个函数实例进行绑定。
这样,在调用这个函数时,在“创建阶段”,就很容易构建出作用域链。
这种在创建函数时绑定父执行上下文的作用域的行为,称之为“Closure”。也就是所谓的“闭包”。
第一个定义:按照 Chrome 的说法,在创建函数时绑定父执行上下文的作用域的行为。
第二个定义:按照 MDN 的说法,闭包是函数和声明该函数的词法环境的组合。
这个环境包括了这个闭包创建时所能访问的所有局部变量。
第三个定义:闭包是一种能够在函数声明过程中将环境信息与所属函数绑定在一起的数据结构。
从本质上讲,闭包就是函数继承而来的作用域。这类似于对象方法时如何访问其继承的实例变量的,它们都具有其父类型的引用。
是对变量的引用。
应用所学的知识思考一个问题。
for (var i = 0; i < 100; i++) {
setTimeout(() => {
console.log(i);
}, 25);
}
for (var i = 0; i < 100; i++) {
setTimeout(() => {
console.log(i);
}, 25);
}
for (let i = 0; i < 100; i++) {
setTimeout(() => {
console.log(i);
}, 25);
}
for (let i = 0; i < 100; i++) {
setTimeout(() => {
console.log(i);
}, 25);
}
为什么呢?:sunglasses:
谢谢!!!!
👏👏👏
🎉🎉🎉