Si vous êtes un développeur JavaScript, ou souhaitez devenir développeur JavaScript, alors vous devez connaître le mécanisme d'exécution interne d'un programme JavaScript. Le contexte d'exécution et la pile d'exécution sont l'un des concepts clés de JavaScript et l'une des difficultés de JavaScript. Comprendre le contexte d'exécution et la pile d'exécution permet également de comprendre d'autres concepts JavaScript tels que le mécanisme de levage, la portée et la fermeture. Cet article présente ces concepts de la manière la plus simple à comprendre possible.
Tutoriel recommandé : "Tutoriel vidéo JavaScript"
Types de contexte d'exécution
., qui l'article se concentre sur la phase de création. 1. Phase de création
De plus, avant qu'une fonction ne soit exécutée, un contexte d'exécution de fonction sera également créé, qui est similaire au contexte global, mais le contexte d'exécution de fonction aura ces arguments et paramètres de fonction.
2. Phase d'exécution
3. Phase de recyclage
3. Détails de la promotion des variables et ce pointage
console.log(a); // undefined var a = 10;
Le code ci-dessus génère normalement
au lieu de signaler une erreur Cela est dû au levage de déclaration, ce qui équivaut à ce qui suit. code : undefined
var a; //声明 默认值是undefined “准备工作” console.log(a); a = 10; //赋值
Uncaught ReferenceError: a is not defined
2. Levage de la déclaration de fonction et l'autre par fonction expression function foo(){}
, alors ces deux méthodes sont différentes dans la promotion de fonction Quelle est la différence ?
console.log(f1); // function f1(){} function f1() {} // 函数声明 console.log(f2); // undefined var f2 = function() {}; // 函数表达式
var foo = function(){}
Ensuite, nous utilisons un exemple pour illustrer ce problème : function test() { foo(); // Uncaught TypeError "foo is not a function" bar(); // "this will run!" var foo = function() { // function expression assigned to local variable 'foo' alert("this won't run!"); }; function bar() { // function declaration, given the name 'bar' alert("this will run!"); } } test();
Dans l'exemple ci-dessus, une erreur est signalée lorsque foo() est appelé, mais bar peut être appelé normalement.
Nous avons déjà dit que les variables et les fonctions augmenteront. Lorsqu'on rencontrera une expression de fonction
, montera d'abord au sommet du corps de la fonction. Cependant, la valeur de foo à ce moment n'est pas définie. , donc exécution var foo = function(){}
Signaler une erreur. var foo
而对于函数bar()
, 则是提升了整个函数,所以bar()
才能够顺利执行。
有个细节必须注意:当遇到函数和变量同名且都会被提升的情况,函数声明优先级比较高,因此变量声明会被函数声明所覆盖,但是可以重新赋值。
alert(a); //输出:function a(){ alert('我是函数') } function a() { alert("我是函数"); } // var a = "我是变量"; alert(a); //输出:'我是变量'
function 声明的优先级比 var 声明高,也就意味着当两个同名变量同时被 function 和 var 声明时,function 声明会覆盖 var 声明
这代码等效于:
function a() { alert("我是函数"); } var a; //hoisting alert(a); //输出:function a(){ alert('我是函数') } a = "我是变量"; //赋值 alert(a); //输出:'我是变量'
最后我们看个复杂点的例子:
function test(arg) { // 1. 形参 arg 是 "hi" // 2. 因为函数声明比变量声明优先级高,所以此时 arg 是 function console.log(arg); var arg = "hello"; // 3.var arg 变量声明被忽略, arg = 'hello'被执行 function arg() { console.log("hello world"); } console.log(arg); } test("hi"); /* 输出: function arg(){ console.log('hello world') } hello */
这是因为当函数执行的时候,首先会形成一个新的私有的作用域,然后依次按照如下的步骤执行:
先搞明白一个很重要的概念 —— this 的值是在执行的时候才能确认,定义的时候不能确认! 为什么呢 —— 因为 this 是执行上下文环境的一部分,而执行上下文需要在代码执行之前确定,而不是定义的时候。看如下例子:
// 情况1 function foo() { console.log(this.a) //1 } var a = 1 foo() // 情况2 function fn(){ console.log(this); } var obj={fn:fn}; obj.fn(); //this->obj // 情况3 function CreateJsPerson(name,age){ //this是当前类的一个实例p1 this.name=name; //=>p1.name=name this.age=age; //=>p1.age=age } var p1=new CreateJsPerson("尹华芝",48); // 情况4 function add(c, d){ return this.a + this.b + c + d; } var o = {a:1, b:3}; add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34 // 情况5 <button id="btn1">箭头函数this</button> <script type="text/javascript"> let btn1 = document.getElementById('btn1'); let obj = { name: 'kobe', age: 39, getName: function () { btn1.onclick = () => { console.log(this);//obj }; } }; obj.getName(); </script>
接下来我们逐一解释上面几种情况
函数多了,就有多个函数执行上下文,每次调用函数创建一个新的执行上下文,那如何管理创建的那么多执行上下文呢?
JavaScript 引擎创建了执行上下文栈来管理执行上下文。可以把执行上下文栈认为是一个存储函数调用的栈结构,遵循先进后出的原则。
从上面的流程图,我们需要记住几个关键点:
我们再来看个例子:
var color = "blue"; function changeColor() { var anotherColor = "red"; function swapColors() { var tempColor = anotherColor; anotherColor = color; color = tempColor; } swapColors(); } changeColor();
上述代码运行按照如下步骤:
更多编程相关知识,请访问:编程学习网站!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!