Heim  >  Artikel  >  Web-Frontend  >  Was ist ein JS-Variablenobjekt? Detaillierte Erläuterung der JS-Variablenobjekte und der Dinge, die Aufmerksamkeit erfordern

Was ist ein JS-Variablenobjekt? Detaillierte Erläuterung der JS-Variablenobjekte und der Dinge, die Aufmerksamkeit erfordern

php是最好的语言
php是最好的语言Original
2018-07-23 11:10:502600Durchsuche

Was ist in JavaScript ein Variablenobjekt? In diesem Artikel wird zunächst das Konzept variabler Objekte vorgestellt, wie variable Objekte im Kontext ausgeführt werden, wie der Code in variablen Objekten verarbeitet wird und schließlich, was sind Variablen?

Variables Objekt ist die Brücke zwischen Ausführungskontext und Bereichskette.
Spoiler-Alarm, das Geheimnisvolle dieses existiert im Ausführungskontext!
Natürlich werde ich später ein paar Abschnitte damit verbringen, ausführlich zu erklären, was das ist (eigentlich ist das sehr einfach).

Als nächstes geben wir den Haupttext ein.

1. Was beinhaltet der Ausführungskontext

Wir können einen Ausführungskontext abstrakt als Objekt verstehen.
Jeder Ausführungskontext verfügt über einige Eigenschaften (auch Kontextstatus genannt), die verwendet werden, um den Ausführungsfortschritt des zugehörigen Codes zu verfolgen.

Ich verwende ein Strukturdiagramm zur Veranschaulichung:

执行上下文环境 object

Variables Objekt stellt das variable Objekt dar.
Scope Chain steht für die Scope-Kette.
thisValue repräsentiert das Geheimnisvolle this .

Die Scope-Kette und dies werden später besprochen. Heute werden wir zunächst das variable Objekt verstehen.

2. Variablenobjekt

Ein Variablenobjekt ist ein Datenbereich, der mit dem Ausführungskontext verknüpft ist und in dem Variablen und Funktionsdeklarationen gespeichert werden innerhalb des Kontexts definiert.

Ein Variablenobjekt ist der Umfang der Daten, die sich auf den Ausführungskontext beziehen. Es handelt sich um ein spezielles Objekt, das einem Kontext zugeordnet ist und im Kontext definierte Variablen und Funktionsdeklarationen speichert.

Variables Objekt (Variables Objekt – kurz VO) ist ein abstraktes Konzept, das sich auf ein spezielles Objekt bezieht, das sich auf den Ausführungskontext bezieht. Es speichert, was im Kontext deklariert wird :
- Variable (var)
- Funktionsdeklaration (Funktionsdeklaration, abgekürzt als FD)
- Formale Parameter der Funktion ( Argumente)

Wir gehen davon aus, dass das Variablenobjekt ein gewöhnliches ECMAScript-Objekt ist:

VO = {};

Wie bereits erwähnt, ist VO ein Attribut des Ausführungskontexts:

activeExecutionContext = {
  VO: {
    // 上下文数据 (vars, FD, arguments)
  }
}

Weil die Variable Objekt ist ein abstraktes Konzept, daher kann nicht direkt über den Namen des variablen Objekts darauf zugegriffen werden, sondern es kann indirekt über andere Methoden aufgerufen werden. Beispielsweise verfügt das variable Objekt in der globalen Kontextumgebung über ein Attributfenster (. im DOM), das auf das Variablenobjekt selbst verweisen kann, ein weiteres Attribut des globalen Kontexts, das ebenfalls auf das Variablenobjekt des globalen Kontexts verweist.

Zum Beispiel:

var a = 2;

function foo (num) {
   var b = 5;
}

(function exp () {
   console.log(111);
})

foo(10);

Das entsprechende Variablenobjekt hier ist:

// 全局上下文环境的变量对象
VO(globalContext) = {
   // 一些全局环境初始化时系统自动创建的属性: Math、String、Date、parseInt等等
   ···

   // 全局上下文的变量对象中有一个属性可以访问到自身,在浏览器中这个属性是 window ,在 node 中这个属性是 global
   window: global

   // 自己定义的属性
   a: 10,
   foo: <reference to function>
};

// foo 函数上下文的变量对象
VO(foo functionContext) = {
   num: 10,
   b: 5
};

Hinweis: Funktionsausdrücke sind nicht im Variablenobjekt enthalten.

3. Variable Objekte in verschiedenen Ausführungskontexten

Ausführungskontexte umfassen: globaler Kontext, Funktionskontext und eval()-Kontext.

Variable Objekte im globalen Kontext

Hier verstehen wir zunächst, was ein globales Objekt ist:

全局对象(global object)是指在进入任何执行上下文之前就已经创建了的对象。
这个对象只有一份,它的属性在程序中的任何地方都可以访问,全局对象的生命周期终止于程序退出的那一刻。

Wenn das globale Objekt initialisiert wird, erstellt das System und Initialisieren Sie eine Reihe primitiver Eigenschaften wie Math, String, Date, parseInt, window usw., gefolgt von globalen Variablen, die wir im globalen Kontext definieren. Im DOM kann die Eigenschaft window des globalen Objekts auf das globale Objekt selbst verweisen, und die Eigenschaft this des globalen Kontexts kann auch auf das globale Objekt verweisen.

// 全局执行上下文环境
EC(globalContext) = {
   // 全局对象(全局上下文环境的变量对象) 
   global: {
      Math: <...>,
      String: <...>,
      ...
      ...
      window: global     // 引用全局对象自身
   },

   // this 属性
   this: global

   // 作用域链
   ...
}

Zum Beispiel:

var a = 10;

console.log(a);               // 10
console.log(window.a);        // 10
console.log(this.a);          // 10

Daher wird im globalen Kontext das variable Objekt durch das globale Objekt dargestellt.

Variable Objekte im Funktionskontext

Im Funktionskontext werden variable Objekte durch aktive Objekte AO (Active Object) dargestellt.

VO(functionContext) = AO

Das aktive Objekt wird beim Betreten des Funktionskontexts erstellt. Es wird über die Argumenteigenschaft der Funktion initialisiert. arguments ist auch ein Objekt.

AO = {
   arguments: {
      ...
   }
}

arguments ist ein Attribut des aktiven Objekts und enthält die folgenden Attribute:
1. Aufgerufene – eine Referenz auf die aktuelle Funktion.
2 tatsächlich übergebene Parameter
3. Eigenschaften-Indizes – Index ist eine Ganzzahl vom Typ String, z. B. „1“: „aa“, die einem Array-Typ ähnelt und auch über Argumente[1] aufgerufen werden kann, aber nicht Der Zugriff erfolgt über Array-Methoden (Push, Pop usw.). Darüber hinaus werden die Werte der Eigenschaftsindizes und die tatsächlich übergebenen Parameter gemeinsam genutzt. Wenn sich einer ändert, ändert sich auch der andere.

Zum Beispiel:

function foo (x, y, z) {

   // 声明的函数参数数量
   console.log(foo.length);      // 3

   // 实际传递进来的参数数量
   console.log(arguments.length);      // 2

   // arguments 的 callee 属性指向当前函数
   console.log(arguments.callee === foo)   // true

   // 参数共享
   console.log(x === arguments[0]);      // true
   console.log(x);      // 10

   arguments[0] = 20;
   console.log(x);   // 20

   x = 30;
   console.log(arguments[0]);    // 30

   // 但是注意,没有传递进来的参数 z ,和第3个索引值是不共享的
   z = 40;
   console.log(arguments[2]);      // undefined

   arguments[2] = 50;
   console.log(z);      // 40
}

foo(10, 20);

4. Wie der Code verarbeitet wird

In Abschnitt 1 haben wir über den Kompilierungsprozess von js-Code gesprochen, einer der Schritte heißt Vorkompilierung bedeutet, dass der Code einige Mikrosekunden vor der Codeausführung kompiliert wird, einen lexikalischen Bereich bildet und dann ausgeführt wird.

Dann kann der Ausführungskontextcode in zwei zu verarbeitende Phasen unterteilt werden:
1. Geben Sie den Ausführungskontext ein (vorkompiliert)
Führen Sie den Code aus

而变量对象的修改变化和这两个阶段是紧密相关的。
并且所有类型的执行上下文都会有这2个阶段。

进入执行上下文

当引擎进入执行上下文时(代码还未执行),VO 里已经包含了一些属性:
1. 函数的所有形参(如果是函数执行上下文)
由名称和对应值组成的一个变量对象的属性被创建,如果没有传递对应的实参,那么由名称和 undefined 组成的一种变量对象的属性也会被创建。

2.所有的函数声明(Function Declaration - FD)
由名称和对应值(函数对象 function object)组成的一个变量对象的属性被创建,如果变量对象已经存在相同名称函数的属性,则完全替换这个属性。

3.所有的变量声明(Variable Declaration - var)
由名称和对应值(在预编译阶段所有变量值都是 undefined)组成的一个变量对象的属性被创建,如果变量名和已经声明的形参或者函数相同,则变量名不会干扰已经存在的这类属性,如果已经存在相同的变量名,则跳过当前声明的变量名。

注意:变量碰到相同名称的变量是忽略,函数碰到相同名称的函数是覆盖。

举个例子:

function test(a, b, c) {
            
    console.log(a); // 函数体a
    console.log(b);  // 20
    function a() {
         console.log(1);
    }
    var a = 100;
    console.log(a);  // 100
    var b = 2;
    console.log(b); // 2

}
test(10,20,30);
function foo (a, b) {
   var c = 5;

   function bar () {};

   var d = function _d () {};

   (function f () {});
}

foo(10);

当进入带有实参10的 foo 函数上下文时(预编译时,此时代码还没有执行),AO 结构如下:

AO(foo) = {
   a: 10,
   b: undefined,

   c: undefined,
   bar: <reference to FunctionDelcaration "bar">,
   d: undefined 
};

注意,函数表达式 f 并不包含在活动对象 AO 内。
也就是说,只有函数声明会被包含在变量对象 VO 里面,函数表达式并不会影响变量对象。

行内函数表达式 _d 则只能在该函数内部可以使用, 也不会包含在 VO 内。

这之后,就会进入第2个阶段,代码执行阶段。

代码执行

在这个阶段,AO/VO 已经有了属性(并不是所有的属性都有值,大部分属性的值还是系统默认的初始值 undefined)。

AO 在代码执行阶段被修改如下:

AO[&#39;c&#39;] = 5;
AO[&#39;d&#39;] = <reference to FunctionDelcaration "_d">

再次要提醒大家,因为函数表达式 _d 已经保存到了声明的变量 d 上面,所以变量 d 仍然存在于 VO/AO 中。我们可以通 d() 来执行函数。但是函数表达式 f 却不存在于 VO/AO 中,也就是说,如果我们想尝试调用 f 函数,不管在函数定义前还是定义后,都会出现一个错误"f is not defined",未保存的函数表达式只有在它自己的定义或递归中才能被调用。

再来一个经典例子:

console.log(x);      // function

var x = 10;
console.log(x);      // 10

x = 20;

function x () {};

console.log(x);      // 20

这里为什么是这样的结果呢?

上边我们说过,在代码执行之前的预编译,会为变量对象生成一些属性,先是形参,再是函数声明,最后是变量,并且变量并不会影响同名的函数声明。

所以,在进入执行上下文时,AO/VO 结构如下:

AO = {
   x: <reference to FunctionDeclaration "x">

   // 在碰到变量声明 x 时,因为已经存在了函数声明 x ,所以会忽略
}

紧接着,在代码执行阶段,AO/VO 被修改如下:

AO[&#39;x&#39;] = 10;
AO[&#39;x&#39;] = 20;

希望大家可以好好理解变量对象,对于理解我们后边要讲的作用域链有很大的帮助。

5. 变量

有一些文章说过:

不管是使用 var 关键字(在全局上下文)还是不使用 var 关键字(在任何地方),都可以声明一个变量。

请记住,这是错误的观念。

任何时候,变量都只能通过使用 var 关键字来声明(ES6 之前)

a = 10;

上面的赋值语句,仅仅是给全局对象创建了一个新属性(在非严格模式,严格模式下会报错),但注意,它不是变量。“不是变量”并不是说它不能被改变,而是指它不符合ECMAScript 规范中变量的概念。

让我们通过一个例子来看一下两者的区别:

console.log(a);        // undefined
console.log(b);        // 报错,b is not defined

b = 10;
var a = 20;

只要我们很好的理解了:变量对象、预编译阶段和执行代码阶段,就可以迅速的给出答案。

预编译(进入上下文)阶段:

VO = {
   a: undefined
}

我们可以看到,因为 b 不是通过 var 声明的,所以这个阶段根本就没有 b ,b 只有在代码执行阶段才会出现。但是在这个例子中,还没有执行到 b 那就已经报错了。

我们稍微更改一下示例代码:

console.log(a);      // undefined

b = 10;
console.log(b);             // 10 代码执行阶段被创建
console.log(window.b);      // 10
console.log(this.b);        // 10

var a = 20;
console.log(a);      // 20 代码执行阶段被修改

关于变量,还有一个很重要的知识点。

变量不能用 delete 操作符来删除。

a = 10;

console.log(window.a);    // 10

console.log(delete a);    // true

console.log(window.a);    // undefined

var b = 20;
console.log(window.b);    // 20

console.log(delete b);    // false

console.log(window.b);    // 20

注意:这个规则在 eval() 上下文中不起作用。

eval(&#39;var a = 10;&#39;);
console.log(window.a);    // 10

console.log(delete a);    // true

console.log(window.a);    // undefined

 相关推荐:

 js高级面向对象和组件开发视频教程

js 多种变量定义(对象直接量,数组直接量和函数直接量)_javascript技巧

Das obige ist der detaillierte Inhalt vonWas ist ein JS-Variablenobjekt? Detaillierte Erläuterung der JS-Variablenobjekte und der Dinge, die Aufmerksamkeit erfordern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn