我知道的JavaScript(1)-- 理解作用域

介绍作用域

程序中的一段源代码在执行会经历三个步骤,统称“编译”。

词法分析 -> 语法分析 -> 代码生成

词法作用域

词法作用域意味着作用域是由书写代码时函数声明的位置来决定。编译的词法分析阶段基本能知道全部标识符在哪里以及是如何声明的,从而能够预测在执行过程中如何对他们进行查找。

var x = 4;
function foo(a){
    var b = 1;
    function bar(c){
        console.log(a,b,c,x);
    }
    bar(b * 3);
}
foo(2); //2,1,3,4

在上面的代码中有三个逐级嵌套的作用域

  1. 包含整个全局作用域,其中有foo和x;
  2. 包含foo创建的作用域,其中有三个标识符,b,bar,a;
  3. 在bar函数中是最后一个函数作用域,只有一个标识符c;

在bar函数中打印a,b,c时,会进行向上查找,类似js的冒泡机制,最先从自己的内部作用域进行查找,就是第三个作用域,找到了c,其他的没有找到就会到上一级作用域继续查找,在第二个作用域找到了a和b,在第一个作用域找到了x,最后打印出结果2,3,1,4。
作用域查找会在找到第一个匹配的标识符时停止 这叫作“遮蔽效应”

var x = 4;
function foo(a){
    var b = 1,x=5;
    function bar(c){
        console.log(a,b,c,x);
    }
    bar(b * 3);
}
foo(2); //2,1,3,5

这时候找x标识符的时候在第二个作用域就找到了,就不会继续往上查找了,外层的声明x也不会覆盖函数里面定义的x。

可以通过间接的访问全局属性来访问被遮蔽的全局变量,但如果非全局变量被遮蔽了,就不能被访问到了。

x = 4;
function foo(a){
    var b = 1,x=5;
    function bar(c){
        console.log(a,b,c,window.x);
    }
    bar(b * 3);
}
foo(2); //2,1,3,4

这时候在查找x的时候访问的是window对象的属性值。

欺骗词法

欺骗词法作用域会导致性能下降。

eval

JavaScript中的eval()函数可以接受一个字符串为参数,将其中的内容好像在书写代码就存在于程序中的这个位置的代码一样。

function foo(str,a){
    eval(str);
    console(a,b);
}
var b = 2;
foo("var b = 3",1); //3,1

eval中的"var b = 3"相当于把这句代码插入进去执行。执行了后会在函数foo中找到a和b,有了遮蔽效应,所以在外面声明的"var b = 2"是不会被访问到的。
严格模式下eval运行有自己的的词法作用域,是无法修改所在声明的作用域的。

with
function foo(obj){
    with(obj){
        a=2;
    }
}
var o1 = {a:3};
var o2 = {b:3};
foo(o1);
console.log(o1.a);//2
foo(o2);
console.log(o2.a);//undefined
console.log(a);//2

在对象中可以找到对应的标识符时,可以修改属性值,没找到对应的属性值,会自动创建一个全局变量。

函数作用域和块作用域

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值