hzzzzzzzq / Blog

这是我记录博客的地方,希望能多写一些技术博客,JS、ES、React、Vue等
14 stars 0 forks source link

深入理解JavaScript系列(3):变量对象 #44

Open hzzzzzzzq opened 2 years ago

hzzzzzzzq commented 2 years ago

JavaScript 深入之变量对象

在[《JavaScript 深入之执行上下文栈》]()中提到,当 JavaScript 代码执行代码时,就会创建一个执行上下文。

对于执行上下文,都有三个重要属性:

我们先来介绍一下变量对象。

变量对象

变量对象是与执行上下文相关的数据作用域,存储了在上下文中定义的变量和函数声明。

然而,由于不同执行上下文的变量对象都存在不同,所以今天我们分不同模块来聊一下不同的变量对象。

全局对象

全局上下文中的变量对象就是全局对象。全局变量是在所有作用域都可访问的变量,与之对应的是局部变量

全局对象预定义的对象,作为 JavaScript 的全局函数和全局属性的占位符。通过使用全局对象,可以访问所有其他。

console.log(this); // window 对象
console.log(this instanceof Obejct); // true
console.log(Math.pow(2, 2)); // 4
var a = 1;
console.log(this.a); // 1
var a = 1;
console.log(window.a); // 1

this.window.b = 2;
console.log(this.b); // 2

函数上下文

函数上下文中,VO 时不能直接访问的,所以用活动对象(Activation Object,OA)来表示变量对象。 但是其实是一个东西,只不过在变量对象的规范上来说,是有区别的。 AO 是在进入函数上下文时才被创建的,它通过 arguments 属性来初始化。arguments 属性就是 Argumens 对象。

Arguments 对象是 AO 对象的一个属性,它包括如下属性:

执行过程

执行上下文,会分为两个阶段,分析阶段和执行阶段。

分析阶段

当进入分析阶段时,这时候还没有执行代码。

变量对象包括:

我们来举个例子

function fn(age) {
  var name = 'hzzzzzzzq';
  function fn2() {}
  var fn3 = function () {}; // 其实也算是一个变量

  name = 'hzq';
}

fn(18);

我们来看看进入执行上下文的分析阶段的 AO 是

AO = {
  // 函数的形参
  arguments: {
    0: 1,
    length: 1,
  },
  age: 18,
  name: undefined, // 变量声明
  fn2: reference to function fn2() {}, // 函数声明
  fn3: undefined // 变量声明
};

执行阶段

在代码执行阶段中,会顺序来执行代码,根据代码,修改变量对象的值。

我们将上面的代码执行完毕后,来看看 AO :

AO = {
  arguments: {
    0: 1,
    length: 1,
  },
  age: 18,
  name: 'hzq',
  fn2: reference to function fun2() {},
  fn3: reference to FunctionExpression "fn3"
};

其实到目前为止,我们的介绍已经结束了。但是肯定不过瘾,或许还不太懂,所以我们...

再来个例子

再来看个例子吧。

function fn1() {
  console.log(x);
  x = 1;
}
fn1();

function fn2() {
  x = 1;
  console.log(x);
}
fn1();

可以来看看上面的代码,打印的是什么呢? 第一个打印 Uncaught ReferenceError: x is not defined 第二个打印 1

这又是为什么呢?

第一个例子中,我们来看看执行上下文时的 AO,因为我们在创建时 AO 对象中没有找到 x 变量,并且往全局变量中找也没有找到,所以报错。

AO = {
  arguments: {
    length: 0,
  },
};

第二个例子中,我们来看看执行上下文时的 AO,我们在创建时找到了 x,所以会打印结果。

AO = {
  arguments: {
    length: 0,
  },
  x: 1,
};