你不知道的JavaScript上卷读后总结(1)——作用域篇

一、什么是作用域? 作用域是一套规则,用于确定在何处以及如何查找变量

作用域嵌套:当一个块或函数嵌套在另一个块或者函数时,就发生了作用域嵌套,因此当前作用域无法找到某个变量时,就会去外层嵌套的作用域中查询,直至找到,或者抵达全局作用域。作用域查找始终从运行时所处的最内部作用域开始,逐级向外进行,直至遇见第一个匹配的变量(遮蔽效应)

变量如何查询?

LHS查询和RHS都是引擎对变量的查询;当变量出现在赋值操作的左侧进行LHS,出现在右侧进行RHS,但是实际上RHS查询与简单的查找某个变量没有什么分别,而LHS查询将会去寻找变量的容器本身,从而可以对其赋值,从这个角度来看,RHS并不是真正意义上的“赋值的右侧”,更准确的说是“非左侧”。

LHS可以理解为——赋值操作的目标是谁,RHS可以理解为——谁是赋值操作的源头

当RHS查询在所以的嵌套作用中遍寻不到所需的变量,引擎就会抛出ReferenceError异常,相比下当LHS如果在全局作用域中也没有找到目标变量,全局作用域就会创建一个具有该名称的变量,并将其返回给引擎。但是在引入严格模式后,不会再创建一个变量,而是同样抛出一个ReferenceError异常。

接下来,如果HRS找到一个变量,但是对它进行了不合理的操作,比如对一个非函数进行函数调用,那么引擎将会抛出一个TypeError异常

ReferenceError同作用域判别失败相关,而TypeErrror则代表作用判别成功,但是对结果的操作是不合理的。

作用域有两种工作模型:词法作用域、动态作用域;

二、词法作用域:就是在写代码时将变量和块作用域写在哪里决定的,也就是说只由函数被声明时所处的位置决定。

怎样才能在运行时修改(欺骗)词法作用域呢?——欺骗词法作用域会导致性能下降

1.eval()函数:通常被用来执行动态创建的代码,下面的eval函数改变了foo的词法作用域,导致foo永远访问不到全局作用域的b

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

2.with方法(不推荐使用)

三、函数作用域和块级作用域

函数作用域:属于这个函数的全部变量都可以在整个函数的范围内使用及复用。

区分函数声明和函数表达式的可以看function的位置,如果是声明的第一个词,就是一个函数声明,否则就是一个函数表达式。两者的区别: 

 1. 最重要的区别 就是他们的名称标识符将会绑定在何处。

 2.函数声明存在声明提升,会被提到当前作用域的顶部,而函数表达式不会

3.以函数声明的方法定义的函数,函数可以在函数声明之前调用,而函数表达式的函数只能在声明之后调用

4.函数声明不可以省略函数名,而函数表达式可以省略,成为匿名函数表达式

函数声明
function foo(){
    console.log(hello world);
}

函数表达式
var  t = function () {
    console.log(1);
}

匿名函数表达式
setTimeout(function(){
    console.log(1);
},1000)

立即执行函数表达式(IIFE)
var a = 2;
(function IIFE(){ 
    var a = 3;
    console.log(a)//3
})()

IIFE另一个常见的用法时把他当做函数调用并传参进去。

var a = 2;
(function IIFE(global){
    var a = 3;
    console.log(a) ; //3
    console.log(global.a) //2
})()

块作用域:最常见的作用域单元,let关键字将变量绑定到所在的任意作用域中,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值