理解 javascript 作用域

对于作用域的话,我觉得就是一些变量能够被访问或者操作的一个区域。如果超过这个区域的话,它似乎就没有了利用价值了。

作用域前的准备

在了解作用域前,我们来说一下题外话。

1.可执行代码:有三种:(1)全局代码  (2)函数代码  (3)eval函数

2.执行环境:每当javascript解析器进入可执行代码的时候,它就会为它创建一个执行环境,也称执行上下文

3.变量对象:执行环境中的变量和函数都是保存到整个对象中的,还有一点就是我们不能用javascript代码去访问整个对象,但是解析器在访问的时候会在后台使用它。

4.活动对象:当执行环境是函数的时候,那么函数被调用的时候,该活动对象也就是被创建,并且把它作为变量对象。

进入这篇文章的作用域

上面为了作用域这个概念铺垫了很久了。那好,我们来讲下作用域这个似乎很抽象的概念。每当javascript解析器进入到一个执行环境的时候,就会为变量对象创建一个作用域链。作用域链的前端总是该执行环境所对应的变量对象,然后作用域链下一个变量对象来着外部的环境,而下一个变量对象就来着下一个外部的环境,一直到全局执行环境就停止。(摘自《javascript高级程序设计》)其实也就是外部的执行环境就是它所包含的执行环境的父环境。然后在寻找变量的时候会沿着作用域一级一级去寻找,从作用域链的前端到全局执行环境,如果找不到就报错,如果找到就不向下寻找了。

我们先来看看一个例子来了解上面很抽象的解释:

var name = 'monkind';
(function fun(){
 alert(name);//monkind
})();
上面弹出来的就是monkind不是undefined,记住这个,下面待会有一个跟它很相似的。用上面的理论我们可以理解:在全局代码中创建一个执行环境和作用域链,然后执行环境相关联的变量对象把name还有fun函数设置为属性并赋值。然后就是自执行函数fun的运行,也创建一个执行环境,它会创建活动对象,再把当前的执行环境放在作用域链的最前端,外面就是全局执行环境。当要访问name这个变量的时候,javascript解析器会沿着作用域访问下去,在fun函数中找不到,就只能到全局执行环境也就是window找了。

javascript没有块级作用域

什么是块级作用域,就是用花括号封闭的代码有自己的执行环境和作用域,一旦离开花括号的话就会自动销毁里面的变量等,但是不要跟函数作用域混淆,块级作用域不包含函数的,只有if和for语句。但是偏偏javascript就要搞特殊。来,我们来看下面的代码:

if (true) {
	var j = '19';
	for (var k = 0; k < 10; k++) {
	}
}
console.log(k + '...last');
console.log(j + '....j');

如果它没有块级作用域的话,那么他的k和j的值是什么?

其实上面的代码相当于这样子写的:

var j = '19', k = 0;
if (true) {
	for (; k < 10; k++) {
	}
}
console.log(k + '...last');
console.log(j + '....j');

我们再看下下面的代码,它弹出来会是哪个值呢?

if (true) {
	var j = '19';
	for (var k = 0; k < 10; k++) {
	}
}
function fun(){
 alert(k);
}
fun();
没错,它还是弹出来10,为什么呢?这个就留给读者慢慢琢磨了,原理都在上面了。

javascript词法作用域

对于一些新的专业名称,我第一反应就是它究竟是什么?不喜欢太专业太权威的解释,用比较淳朴的语言或者举个例子来解释容易让菜鸟懂呀。对于词法作用域就是javascript执行环境的作用域是从定义它的时候就确定下来了,而不是在它运行的时候。作为第一次看见这个解释之后我还是很懵懂呀,不知道你们会不会呀,我觉得应该举一两个例子来解释下。

var name = 'monkind';
function myName() {
	alert(name);
}

function callMyName() {
	var name = 'zkh';
	myName();
}
callMyName();

那么究竟会弹出来那个name呢?是monkind还是zkh呢?事实上弹出的是monkind。那么为什么呢?我们要知道myName这个函数在全局执行环境定义的,所以它的作用域就是全局执行环境的,虽然它执行的是在callMyName函数中,但是记住javascript是词法作用域。那么当然不能访问callMyName函数中的name啦,只能访问全局环境的name也就是monkind。

回应上面的那句"记住这个,下面待会有一个跟它很相似的",我们再来看下一个例子,也是很经典的例子。

var name = 'monkind';
(function fun(){
 alert(name);
 var name = 'zkh';
 alert(name);
})();

第一个弹出的窗口是"undefined",第二个是"zkh";那么为什么第一个alert不去访问全局的name呢?我们首先要去了解一个就是:javascript引擎会先对执行环境中的变量和函数进行定义,如果没有赋值的话就设置为undefined。所以fun函数中的name对该函数是可见的,在词法分析后的构造作用域链中,会把name放在fun函数的执行环境中。所以第一个访问就是还没赋值的undefined,要访问第二个name的时候,name已经赋值给"zkh"了,大家可以用chrome开发者工具的断点去看。


这个是在第一个alert断点的情况。

感谢那些好的文章还有书籍,给我写作的动力。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript 作用域指的是变量、函数和对象可以被访问的范围。在 JavaScript 中,作用域分为全局作用域和局部作用域两种。 全局作用域指的是在函数外定义的变量和函数,它们可以被整个程序访问。在浏览器中,全局作用域指的是 window 对象。 局部作用域指的是在函数内部定义的变量和函数,它们只能在函数内部被访问。在 JavaScript 中,每当一个函数被调用时,都会创建一个新的局部作用域JavaScript 使用词法作用域(也称为静态作用域)规则来决定变量的作用域。这意味着函数的作用域是在函数定义时确定的,而不是在函数调用时确定的。因此,在函数内部定义的变量可以在函数外部访问,但函数外部定义的变量不能在函数内部访问。 例如,下面的代码演示了 JavaScript 中的作用域: ``` var x = 10; // 全局变量 function foo() { var y = 20; // 局部变量 console.log(x); // 可以访问全局变量 x console.log(y); // 可以访问局部变量 y } foo(); console.log(x); // 可以访问全局变量 x console.log(y); // 不能访问局部变量 y ``` 在上面的例子中,变量 x 是在全局作用域中定义的,可以在函数内部和外部访问。变量 y 是在函数内部定义的,只能在函数内部访问。函数 `foo()` 调用后,可以在函数内部访问变量 x 和 y。函数调用结束后,只能在全局作用域中访问变量 x,无法访问变量 y。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值