Heim  >  Artikel  >  Web-Frontend  >  Analyse des Ausführungskontexts und variabler Objekte in js

Analyse des Ausführungskontexts und variabler Objekte in js

不言
不言Original
2018-08-14 10:02:021176Durchsuche

In diesem Artikel geht es um die Analyse des Ausführungskontexts und variabler Objekte in js. Ich hoffe, dass er für Freunde hilfreich ist.

Ausführungskontext

Der Prozess der JavaScript-Codeausführung umfasst zwei Phasen: Kompilierung und Kompilierung dienen dazu, einen abstrakten Syntaxbaum durch lexikalische Analyse zu erstellen In der Phase der JavaScript-Code-Kompilierung werden die Bereichsregeln festgelegt. Sobald die Funktion aufgerufen wird, wird ein Ausführungskontext (Ausführungskontext) erstellt, der auch als Ausführungsumgebung bezeichnet wird

Es gibt die folgende Definition in ECMA-262

Wenn der Controller zum ausführbaren Code des ECMA-Skripts wechselt, betritt der Controller eine Ausführungsumgebung. Mehrere aktuell aktive Ausführungsumgebungen bilden logischerweise eine Stapelstruktur. Die Ausführungsumgebung der obersten Ebene des logischen Stapels wird als aktuell ausgeführte Ausführungsumgebung bezeichnet. Jedes Mal, wenn der Controller von ausführbarem Code, der von der aktuell ausgeführten Ausführungsumgebung abhängig ist, zu ausführbarem Code übergeht, der von dieser Ausführungsumgebung unabhängig ist, wird eine neue Ausführungsumgebung erstellt. Die neu erstellte Ausführungsumgebung wird in den Stapel verschoben und zur aktuell ausgeführten Ausführungsumgebung.
Dies ist auch ein abstraktes Konzept, in dem mehrere Ausführungskontexte erstellt werden Variablen oder andere Daten, auf die die Funktion Zugriff hat, haben wir erfahren, dass der Ausführungskontext (kurz EC) hauptsächlich drei Punkte umfasst, die im Pseudocode wie folgt ausgedrückt werden:

EC = {
    this: // 绑定this指向为当前执行上下文, 如果函数属于全局函数,则this指向window
    scopeChain: [] // 创建当前执行环境的作用域链,
    VO: {} // 当前环境的变量对象(Variable Object),每个环境都有一个与之关联的变量对象
}
Sehen Sie sich den folgenden Code an:

var a = 1;
function foo() {
    var b = 2;
    function bar() {
        console.log(b)
    }
    bar()
    console.log(a);
}

foo()
  • 1. Beim Ausführen dieses Codes wird zuerst der globale Kontext globalEC erstellt und in den Ausführungskontextstapel verschoben

  • 2. Beim Aufruf von foo() wird der Kontext fooEC von foo erstellt und in den Ausführungskontextstapel verschoben

  • 3 , der Kontext barEC wird erstellt und in den Ausführungskontextstapel

  • 4 verschoben 🎜>

  • 5. Wenn die foo-Funktion ausgeführt wird, erscheint fooEC aus dem Ausführungskontextstapel
  • 6 , der globale Kontext globleEC wird aus dem Ausführungskontextstapel angezeigt;
  • Zusammenfassung: Der untere Teil des Stapels ist immer der globale Kontext und der obere Teil des Stapels ist der aktuell ausgeführte Kontext . Nur wenn der Browser geschlossen ist, wird der globale Kontext aus dem Ausführungskontextstapel angezeigt

Variables Objekt:

Jeder Ausführungsumgebung ist ein Variablenobjekt zugeordnet Es handelt sich um ein abstraktes Konzept. Alle in der Umgebung definierten Variablen und Funktionen werden in diesem Objekt gespeichert. Obwohl der von uns geschriebene Code keinen Zugriff auf dieses Objekt hat, verwendet der einzelne Parser sie im Hintergrund bei der Verarbeitung der Daten.

Wenn der Browser das js-Skriptprogramm zum ersten Mal lädt, wechselt er standardmäßig in die globale Ausführungsumgebung. Diesmal ist das globale Umgebungsvariablenobjekt ein Fenster, auf das im Code zugegriffen werden kann.

Wenn die Umgebung eine Funktion ist, wird dieses aktive Objekt als Variablenobjekt des aktuellen Kontexts verwendet (VO = AO). Zu diesem Zeitpunkt kann nicht über den Code zugegriffen werden das aktive Objekt.

Aktivierungsobjekt (Aktivierungsobjekt)

1. Initialisieren Sie das Aktivitätsobjekt (im Folgenden als AO abgekürzt)

Wenn die Funktion aufgerufen wird, wird das aktuelle Objekt wird sofort erstellt Das aktive Objekt des Kontexts, und das aktive Objekt wird als Variablenobjekt verwendet, über das Argumentattribut initialisiert, und der Wert ist das Argumentobjekt (der Satz tatsächlicher Parameter, der übergeben wird, hat nichts damit zu tun formale Parameter, die formalen Parameter werden als lokale Variablen der lokalen Umgebung definiert)

Das
AO = {
  arguments: <ArgO>
};

arguments-Objekt hat die folgenden Attribute:

  • Länge:

    Die Anzahl der tatsächlich übergebenen Parameter;

  • callee:

    bezieht sich auf einen Verweis auf die aktuelle Funktion, also die aufgerufene Funktion

  • 'class index':

    Ganzzahl vom Typ String, Wert Dies ist der Wert des Objektindex im Argumentobjekt. Das Argumentobjekt sollte vom Array unterschieden werden Objekt, aber es kann das gleiche Längenattribut wie das Array haben, und auf den Wert kann über den Index zugegriffen werden

    function show (a, b, c) {
        // 通过Object.prototype.toString.call()精准判断类型, 证明arguments不同于数组类型
        var arr = [1, 2, 3];
        console.log(Object.prototype.toString.call(arr)); // [object Array]
    
        console.log(Object.prototype.toString.call(arguments)); // [object Arguments]
    
        console.log(arguments.length) // 2  传递进来实参的个数
    
        console.log(arguments.callee === show) // true 就是被调用的函数show自身
    
        //参数共享
    
        console.log(a === arguments[0]) // true
    
        a = 15;
    
        console.log(arguments[0]) // 15
    
        arguments[0] = 25;
    
        console.log(a)  // 25;
    
        但是,对于没有传进来的参数c, 和arguments的第三个索引是不共享的
    
        c = 25;
    
        console.log(arguments[2]) // undefined
    
        argument[2] = 35;
    
        console.log(c) // 25
    
    }
    
    show(10, 20);
  • Weiter so, das ist der entscheidende Punkt Die Verarbeitung ist in zwei Phasen unterteilt:

    Betreten Sie die Ausführungsumgebung
  1. Code zum Ausführen der Funktion
  2. 2. Geben Sie die Ausführungsumgebung ein

Wenn die Funktion aufgerufen wird, geben Sie die Ausführungsumgebung (Kontext) ein und erstellen Sie sofort das aktive Objekt. Gleichzeitig werden alle formalen Parameter initialisiert. Alle Funktionsdeklarationen und alle Variablendeklarationen in der Ausführungsumgebung werden gescannt, dem aktiven Objekt (AO) hinzugefügt und dessen Wert bestimmt. Anschließend beginnt die Codeausführung.

In der Phase des Eintritts in die Ausführungsumgebung:

Alle formalen Parameterdeklarationen:

Formale Parameternamen werden verwendet als aktive Objektattribute Erstellen, wenn tatsächliche Parameter übergeben werden, ist der Wert der tatsächliche Parameterwert, wenn keine Parameter übergeben werden, ist der Wert undefiniert

Alle Funktionsdeklarationen:

Funktionsname als aktives Objekt Die Eigenschaft wird erstellt, der Wert ist ein Zeiger im Speicher, der auf diese Funktion zeigt. Wenn bereits eine Eigenschaft mit demselben Namen im Variablenobjekt vorhanden ist, wird diese vollständig ersetzt.

Alle Variablendeklarationen:

所有变量名称作为活动对象的属性被创建, 值为undefined,但是和函数声明不同的是, 如果变量名称跟已经存在的属性(形式参数和函数)相同、则不会覆盖
function foo(a, b) {
    var c = 10;
    function d() {
        console.log('d');
    }
    var e = function () {
        console.log('e');
    };
    (function f() {})
    if (true) {
        var g = 20;
    } else {
        var h = 30;
    }
}

foo(10);

此时在进入foo函数执行上下文时,foo的活动对象fooAO为:

fooAO = {
    arguments: {
        0: 10,
        length: 1
    },
    a: 10,
    b: undefined,
    c: fundefined,
    d: <d reference>  //指向d函数的指针,
    e: undefined,
    g: undefined,
    h: undefined  // 虽然else中的代码永远不会执行,但是h仍然是活动对象中的属性
}

这个例子做如下几点说明:

  • 1.关于函数,只会创建函数声明作为活动对象的属性, 而f函数作为函数表达式并不会出现在活动对象(AO)中

  • 2.e虽然值是一个函数, 但是作为变量属性被活动对象创建

3、代码执行阶段

在进入执行上下文阶段,活动对象拥有了属性,但是很多属性值为undefined, 到代码执行阶段就开始为这些属性赋值了

还是上面的代码例子, 此时活动对象如下:

fooAO = {
    arguments: {
        0: 10,
        length: 1
    },
    a: 10,
    b: undefined,
    c: 10, // 赋值为undefined
    d: <d reference>  //指向d函数的指针,
    e: <d reference>  // 指向e函数的指针
    g: 20,
    h: undefined  // 声明h变量,但是没有赋值
}

变量对象包括:{ arguments对象+函数形参+内部变量+函数声明(但不包含表达式) }

这时这个活动对象, 即作为当前执行环境的变量对象会被推到此执行环境作用域链的最前端(作用域链本篇不做介绍,会在下一篇文章中单独讲解作用域和作用域链), 假定执行环境为一个对象,则整个执行环境可以访问到的属性如下:

伪代码如下:

fooExecutionContext = {
    scopeChain: [], //fooAO +所有父执行环境的活动对象,
    fooAO: {
        arguments: {
            0: 10,
            length: 1
        },
        a: 10,
        b: undefined,
        c: 10, // 赋值为undefined
        d: <d reference>  //指向d函数的指针,
        e: <d reference>  // 指向e函数的指针
        g: 20,
        h: undefined
    },
    this: 当前执行环境的上下文指针
}

补充:

下面的例子为了说明一下变量声明的顺序及变量同名不会影响函数声明

console.log(foo); //  foo的函数体
var foo = 10;
console.log(foo) // 10
function foo() {};
foo = 20;
console.log(foo); // 20

在代码执行之前, 就会读取函数声明,变量声明的顺序在函数声明和形参声明之后, 整个流程如下:

进入执行环境阶段:

1. var VO = {}
2. VO[foo] = 'foo函数指针'
3. 扫描到var foo = 10,

 // 但是foo做为function已经声明,所以变量声明不会影响同名的函数声明,如果代码中没有foo函数声明的话,则foo为undefined

代码执行阶段:

1. VO[foo] = 10;
2. VO[foo] = 20;

解析代码完成。

相关推荐:

js对象是什么?js对象的介绍(附代码)

Js中前端模块化的详细分析及其区别对比

js中字符方法以及字符串操作方法的总结(附代码)

Das obige ist der detaillierte Inhalt vonAnalyse des Ausführungskontexts und variabler Objekte in js. 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