fe-interview
fe-interview copied to clipboard
[js] 第13天 说说你对javascript的作用域的理解
第13天 说说你对javascript的作用域的理解
- javascript有全局作用域和函数作用域,全局最大的作用域是script标签包裹的部分,函数作用域可以访问全局作用域的变量,全局作用域不能访问函数作用域的变量。
1:全局作用域 2:局部作用域 词法环境:说白了就是编写代码时候决定的,是固定不变的作用域js遵循此作用域(写在哪就是找那里的作用域,例如箭头函数)
- 全局作用域。这个没啥说的,就是在顶层环境中申明的变量都是全局作用域,他们的属性其实都在window对象下面。 2.函数作用域。在函数内部定义的变量都是函数作用域,只能在函数中访问到,当然也可以通过闭包来访问。除此之外,在其他地方是没法访问函数内部的变量的。
- 局部作用域。es6中新增的特性,弥补了以前只能使用匿名及时运行函数来创建局部变量的缺陷。使用很简单,直接用let来申明变量就行。也可以使用const来申明变量,表明这是常数。
- 作用域链。要说清这个,需要首先明白javascript的代码运行过程。假设现在有个函数funcA,在该函数内部申明了一个局部变量a,在函数内部又定义了一个函数funcB,在函数B中申明了变量b。如下: function funcA () { let a; function funcB () { let b; } } 当进入funcA时,这时候会把变量a压入当前的作用域A中,并且将作用域A入栈,当进入funcB时,则会把变量b压入当前的作用域B中,并且将作用域B入栈,那么这时候栈中就有了作用域A和作用域B,当在funcB中查找某个变量时,会先从当前的作用域B中查找,如果没有的话,那么就根据栈中的作用域依次往上查找,这就是作用域链。
补充一下:
- js是使用的词法作用域,所以当代码被加载时作用域已经被限定。
- 作用域只会引用当前作用域用到的 上层作用域的变量 其他没用到的将会随该函数一起推出调用栈
在 ES5 之前,javascript 只有函数作用域而没有块级作用域的。即,在 if
或者 for
花括号中的变量实际在外层是可以被访问的。
for(var i = 0; i < 10; i++){var j=123}
console.log(j) // 123;
不过使用 ES6 的 let
和 const
之后,就可以实现块级作用域了。
而函数作用域通过其作用域链的关系,可以实现变量的封装防止污染。子层的函数可以访问父级以及全局的的变量,但反过来则不行。这样子层函数中的变量就与外层隔绝开了。
var a = 1;
function b(){
var b = 2;
console.log(a);
function c(){
// 内部可以访问外部,而外层访问不到内部
var a = 4;
var c = 3;
console.log(a); // 4 不会污染
console.log(b); // 2
}
c();
}
console.log(b());
console.log(a);
作用域 作用域是一组规则,决定了一个变量(标识符)在哪里和如何被查找。 查找变量用于赋值,变量是一个 LHS(左手边)引用;查找变量用于取值,变量是一个 RHS(右手边)引用。 LHS 和 RHS 引用查询都从当前执行中的作用域开始,它们会在嵌套的作用域中一路向上,一次一个作用域(层)地查找这个标识符,直到它们到达全局作用域(顶层)并停止,既可能找到也可能没找到。 未找到的 RHS 引用会导致 ReferenceError 被抛出。 未找到的 LHS 引用会导致一个自动的,隐含地创建的同名全局变量(如果不是“Strict模式”),或者一个 ReferenceError(“Strict模式”)。 词法作用域 js采用词法作用域,意味着作用域是由编写时函数被声明的位置决定。编译器的词法分析阶段实质上可以知道所有的标识符是在哪里和如何声明的,并在执行期间预测它们将如何被查询。(例外是eval(),with,不推荐使用) 函数作用域和块作用域 在 JavaScript 中函数是最常见的作用域单位。在另一个函数内部声明的变量和函数,实质上对任何外围“作用域”都是“隐藏的”,这是优秀软件的一个有意的设计原则。 但是函数绝不是唯一的作用域单位。块儿作用域指的是这样一种想法:变量和函数可以属于任意代码块(一般来说,就是任意的 { .. }。 从 ES3 开始,try/catch 结构在 catch 子句上拥有块儿作用域。 在 ES6 中,引入了 let 关键字(var 关键字的表兄弟)允许在任意代码块中声明变量。if (..) { let a = 2; } 将会声明变量 a,而它实质上劫持了 if 的 { .. } 块儿的作用域,并将自己附着在这里。 https://github.com/getify/You-Dont-Know-JS/tree/1ed-zh-CN/scope%20%26%20closures
- 全局作用域 (哪哪都能访问到)
- 函数作用域(函数内)
- 块级作用域(es2015)
函数作用域内可以访问全局作用域的变量,全局作用域不能访问函数作用域的变量。 函数也不能访问函数内的函数的作用域(闭包)
理解:作用域就是一块封闭的区域,外部不能访问到这块区域里的变量、函数等,被{}包裹的就叫一个作用域(全局作用域是特殊的)
类型:函数作用域、全局作用域和块作用域
变量提升:在用var 或者function声明一个变量和函数时,变量和函数会被提升到函数的顶部
全局作用域 函数作用域 块级作用域
- 全局作用域。这个没啥说的,就是在顶层环境中申明的变量都是全局作用域,他们的属性其实都在window对象下面。 2.函数作用域。在函数内部定义的变量都是函数作用域,只能在函数中访问到,当然也可以通过闭包来访问。除此之外,在其他地方是没法访问函数内部的变量的。
- 局部作用域。es6中新增的特性,弥补了以前只能使用匿名及时运行函数来创建局部变量的缺陷。使用很简单,直接用let来申明变量就行。也可以使用const来申明变量,表明这是常数。
- 作用域链。要说清这个,需要首先明白javascript的代码运行过程。假设现在有个函数funcA,在该函数内部申明了一个局部变量a,在函数内部又定义了一个函数funcB,在函数B中申明了变量b。如下: function funcA () { let a; function funcB () { let b; } } 当进入funcA时,这时候会把变量a压入当前的作用域A中,并且将作用域A入栈,当进入funcB时,则会把变量b压入当前的作用域B中,并且将作用域B入栈,那么这时候栈中就有了作用域A和作用域B,当在funcB中查找某个变量时,会先从当前的作用域B中查找,如果没有的话,那么就根据栈中的作用域依次往上查找,这就是作用域链。
优秀
全局作用域 函数作用域 块级作用域
当前的执行上下文。值和表达式在其中 "可见" 或可被访问到的上下文 https://developer.mozilla.org/zh-CN/docs/Glossary/Scope
第13天说说你对javascript的作用域的理解 作用域 概念:运行代码时 变量或函数的可访问性 类别:全局 函数(局部) 块级(es6:let) 作用域链
出现:在函数嵌套函数的时候 理解:当我们 访问某个变量 但是本作用域中没有 ,所有就向上查找 ,直到找到为止 或者 到全局作用域(window)时停止 而这个逐级查找的过程 叫作用域链
作用域分为全局作用域和块级作用域(函数作用域) 声明全局变量就会有全局作用域 声明函数中的变量就有块级作用域(函数作用域)
负责收集和维护所有变量组成的一系列查询,并实施一套严格规则,确定当前执行的代码对这些变量的访问权限
/* 作用域可以隔开代码,让作用域内与作用域外的变量不相通
作用域目前可以分为3种:
1. 全局作用域 在此声明的变量都将保存为window的属性(?),
他们的属性其实都在window对象下面。
2. 函数作用域 函数内部定义的变量只能在函数中访问的到
3. 块级作用域 在ES5之前,if或者for又或者单独的大括号,其包括的的变量在用var定义时,
这些变量其实可以被括号外层访问得到,如下面的a,而在使用let和const后,大括号{}内 则变为了块级作用域,外层无法访问到块级作用域内的变量 */ var a = 20 let b = 30 var d = 50 let e = 60 console.log(a+' '+b) { var a = 12 let b = 13 const c = 14 d = 15 e = 16 console.log(a+' '+b) } console.log(a+' '+b) console.log(d+' '+e) console.log(c)
概念
作用域即当前的执行上下文,在运行时代码中的某些特定部分中变量,函数和对象的可访问性。
作用域决定了代码区块中变量和其他资源的可见性
作用域就是一个独立的地盘,让变量不会外泄、暴露出去(隔离变量),不同作用域下同名变量不会有冲突
ES6 之前 JavaScript 没有块级作用域,只有全局作用域和函数作用域
全局作用域
- 最外层函数和在最外层函数外面定义的变量拥有全局作用域
- 所有末定义直接赋值的变量自动声明为拥有全局作用域
- 所有window对象的属性拥有全局作用域:一般情况下,window对象的内置属性都拥有全局作用域,例如window.name、window.location、window.top等等。全局作用域有个弊端,如果写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样就会 污染全局命名空间, 容易引起命名冲突
函数作用域
- 函数作用域是指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部
- 作用域是分层的,内层作用域可以访问外层作用域的变量,反之则不行。值得注意的是:块语句(大括号“{}”中间的语句),如 if 和 switch 条件语句或 for 和 while 循环语句,不像函数,它们不会创建一个新的作用域。在块语句中定义的变量将保留在它们已经存在的作用域中
块级作用域
- 块级作用域可通过新增命令let和const声明,所声明的变量在指定块的作用域外无法被访问。块级作用域在如下情况被创建:
- let 声明的语法与 var 的语法一致。基本上可以用 let 来代替 var 进行变量声明,但会将变量的作用域限制在当前代码块中。
js有两种作用域:全局作用域和局部作用域。变量在函数中声明,只能在函数中访问,局部变量在函数开始执行时创建,函数执行完成后变量自动销毁。变量在函数外定义,即为全局变量,如果变量在函数内没有用var关键字声明,该变量为全局变量,全局变量在页面关闭后销毁。
作用域分为:
- 全局作用域
- 函数作用域
- 块级作用域 优先级为块级作用域 > 函数作用域 > 全局作用域
全局作用域、函数作用域和块级作用域。 作用域链:现在当前作用域查找值,找不到的话,会沿外层作用域一直向外查找,直到在某层作用域中找到或者在最外层作用域中都找不到,查找结束。
1 全局作用域:在全局中,最外层函数或函数外声明变量,全局都可以访问的到该变量;所有的window对象也都具有全局作用域; 2 函数作用域:在函数内部声明的变量只能在函数内部中使用,或者通过闭包来实现外部访问函数内部。 3 块级作用域: 通过es6新增命令let/const来声明,所声明的变量只在当前块级有作用,其他作用域外无法访问。
全局作用域和局部作用域,es6还有个块级作用域,就是是否能够访问到变量的一个限制
作用于是指变量和函数的可访问范围。又分为全局作用域即window下的都是全局,和局部作用域:函数或代码块。
全局作用域和局部作用域