js中的执行环境及作用域
1、作用域链是在函数声明的时候确定的,而不是执行的时候确定的。
var x = 10; function fn() { console.log(x); } function show(f) { var x = 20; f(); } show(fn); // 10
2、JS中for循环变量作用域 : https://blog.csdn.net/kai_l/article/details/50913505
for循环,不是函数,没有局部变量一说。内部 声明的变量 以及 括号里面的 i 变量 都是和 for在同级环境。
es6 中的 let 声明的变量就有 块级作用域的区别了。
注意:es5 中的作用域只有 全局作用域,局部作用域。(由函数 确定局部作用域,其他的都不能产生局部作用域;
es6 中的作用域就有 全局作用域、局部作用域、块级作用域 (由{ }确定作用域,但只针对 let 声明的变量有效)。
(个人观点): 虽然一般用法中 var 变量可以实现的功能,let都可以实现(var有而let没有的效果有点反人类思维,一般不会那样用)。但是还是把 let 只是用于for循环变量的声明上。
3、回调函数的作用域 :声明这个回调函数的,执行函数外面 ,执行函数的 括号不会影响里面回调的作用域(亲测)
var b = 0; function test(calback){ var a = 8; calback() } test(function() { // 回调函数的作用在 与调用函数test(),所在环境同级。 console.log(a); // undefined console.log(b); // 0 })
4、promise对象中then里面函数的作用域 :和回调函数一样,也是在声明这个函数所在函数内。调用函数的then不会影响then里面的作用域。(亲测)
var dd = 9 axios.get("./test.json").then( (res) => { var tt = 7; return Promise.resolve(res.data) }, () => { alert('连接失败') } ).then( (res) => { // 这个函数前面的链式写法的有关函数都不会影响到,这个函数的作用域。即作用域和axios对象同级。 console.log(dd); // 9 console.log(tt); // undefined } )
首先来说说js中的执行环境,所谓执行环境(有时也称环境)它是JavaScript中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据 ,决定了它们各自的行为。而每个执行环境都有一个与之相关的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
理解了执行环境,现在就看看什么是作用域链吧。每个函数都有自己的执行环境,当代码在执行环境中执行时,就会创建变量对象的作用域链。作用域链保证了对执行环境有权访问所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在的环境的变量对象,如果环境是一个函数,那么它的变量对象就是该函数的活动对象。作用域链的下一个变量对象来自包含(外部)环境,再下一个变量对象来自下一个包含环境。这样一直延续到全局执行环境,记住,全局执行环境的变量对象永远是作用域中的最后一个对象。
请看下面的例子:
var scope="global"; function foo(){ console.log(scope); } foo();
在这个例子中,函数foo()的作用域链包含了两个对象,一个是它自身对象,另一个是全局环境中的变量对象。因为我们可以在这个作用域链中找的scope,所以可以在函数内部里访问到它。
在看一个例子:
var color = "blue"; function changeColor(){ var anoterColor = "red"; function swapColor(){ var tempColor = anoterColor; anoterColor = color; color = tempColor; console.log(color); } swapColor(); } changeColor();
在这个例子中,有三个执行环境:全局环境、changeColor()的局部环境和swapColor()局部环境。我们来看看这个例子的作用域链是怎样的吧。
图中的矩形表示特定的执行环境。我们可以看到变量tempColor只能在swapColor()环境中访问到,而在changeColor()的局部环境还是全局环境中都无法访问到它。因此我们可以得到一个结论:内部的环境可以通过作用域链访问所有的外部环境,但外部的环境无法访问内部的环境中的任何变量和函数。每个环境都可以向上搜索作用域链,以查询变量和函数名;但是任何环境都不能通过向下搜索作用域而进入另一个执行环境。
作用域中我还想说说的是:js没有块级作用域
为什么说js没有块级作用域呢?我们来看下面的代码:
if(true){ var color = "blue"; } alert(color); //"blue"
咦,为什么color在if语句执行完毕后被销毁呢?哈哈,如果在C、C++或Java中,color确实会被销毁,但在JavaScript中,if语句中的变量声明会将变量添加到当前的执行环境中(在这里是全局环境)中。特别地,在for语句时要牢记这一差异,例如:
for(var i = 0;i< 10; i++){ doSomething(i); } alert(i); //10
记住:在JavaScript中,由for语句创建的变量i即使在for循环执行结束之后,也依然会存在于循环外部的执行环境中哟。