龙空技术网

前端-JavaScript作用域和运行分析

编程码农大叔 128

前言:

眼前大家对“前端作用域”都比较注意,朋友们都想要学习一些“前端作用域”的相关知识。那么小编也在网络上汇集了一些关于“前端作用域””的相关知识,希望姐妹们能喜欢,你们快快来了解一下吧!

作用域

JavaScript中的作用域分为全局作用域,函数作用域,块作用域。

全局作用域

对于全局范围内声明的变量,可以在任何地方访问。

var messge = 'Hello'function say(){  console.log(message)}say(); // Hello
函数作用域

在函数内声明的变量,只能从该函数内部访问。

function say() {  var messge = 'Hello';  console.log(messge);}say(); // Helloconsole.log(greeting); // ReferenceError: messge is not defined
块作用域

ES6 引入了letconst 关键字,它们声明的变量只能从该代码块内访问。

{  let messge = 'Hello';  console.log(messge);}console.log(messge); // ReferenceError: messge is not defined
静态作用域

在词法分析时(编译时)确定。

let number = 42;function printNumber() {  console.log(number);}function log() {  let number = 54;  printNumber();}log(); // 42
作用域链

JavaScript运行时,引擎首先会在当前范围内查找变量,如果找不到,会向父作用域查一层一层向上查找,一直找到顶层全局作用域,如果还是找不到就返回undefined

var g = 'Global hello'function f1() {    var g1 = 'G1 hello';    function f2() {        var g2 = 'G2 hello'        function f3() {            console.log(g, g1, g2)        }        f3()    }    f2();}f1(); // Global hello G1 hello G2 hello

作用域链

执行上下文

执行上下文是执行一段 JavaScript 的环境,它存储了执行代码的一些必要信息。执行上下文分全局执行上下文和函数执行上下文。

全局执行上下文,一个程序中只会有一个,函数之外的代码都在全局执行上下文中运行。函数执行上下文,函数在每次调用时都会创建一个对应的函数执行上下文。

执行上下文的包含变量环境(Variable environment),作用域链(Scope chain),this 指向。

变量环境,函数内部所有的变量和对象引用和调用参数。作用域链,当前函数之外的变量的引用组成。this 指向。

从JavaScript运行时的内存结构来看,调用栈就是存储执行上下文的集合。

js内存

例子

例一

这是一个普通的JavaScript例子,运行流程分析:

var msg = 'Global hello'function say() {    var msg = 'Hello'    return msg;}var s = say();console.log(message) // Hello
创建全局执行上下文,然后入调用栈。调用函数say(),创建say()的函数执行上下文,并入调用栈。执行完say()函数将结果返回,更新全局执行上下文里的s 变量。将say 函数的执行上下文弹出栈。

例二

这个例子跟上面不同的是返回值是函数,这个匿名函数也称闭包,它访问了函数外部的变量,即使外部函数执行上下文被弹出栈后,它依然可以持有外部变量的引用。运行分析如下:

var msg = 'Global hello'function say() {    var msg = 'Hello'    return function() {        console.log(msg)    };}var s = say();s()
创建全局执行上下文,然后入调用栈。调用函数say(),创建say()的函数执行上下文,并入调用栈。执行完say()函数将结果返回,更新全局执行上下文里的s 变量,s 是函数类型,它依然持有say var = msg 引用。将say 函数的执行上下文弹出栈。执行 s() ,创建s()的函数执行上下文。将 s() 函数的执行上下文弹出栈。

思考题

可以尝试在脑海里动态执行下面代码。

题目一:

var msg = 'Global hello'function getMsgFunc() {    var msg = 'Hello';    function getMsg() {        return msg;    }    return getMsg();}console.log(getMsgFunc());

题目二:

var msg = 'Global hello'function getMsgFunc() {    var msg = 'Hello';    function getMsg() {        return msg;    }    return getMsg;}console.log(getMsgFunc()());

题目三:

     var msg = 'Global hello'  var obj = {    msg : 'Hello',    getMsgFunc : function(){      return function(){        return this.msg;      };    }  };  console.log(obj.getMsgFunc()());

题目四:

     var msg = 'Global hello'  var obj = {    msg : 'Hello',    getMsgFunc : function(){            var that = this      return function(){        return that.msg;      };    }  };  console.log(obj.getMsgFunc()());

关于JavaScript运行原理,请查看

前端-JavaScript运行原理

标签: #前端作用域