细说JavaScript中的作用域与变量
本篇文章讲述了JavaScript中的作用域与变量,大家对JavaScript中的作用域与变量不了解的话或者对JavaScript中的作用域与变量感兴趣的话那么我们就一起来看看本篇文章吧, 好了废话少说进入正题吧
变量作用域
作用域:就是变量声明的区域,也是变量和函数的可访问范围。在全局声明的变量为全局可见可访问的就是全局变量,如果在函数内部声明的变量只能在函数内部可访问,可称为局部变量。
几个注意点:
1.JavaScript中没有块级作用域(在ES5和ES6之前),只有函数作用域和全局作用域。for循环内部定义的变量是函数级别的作用域。
2.变量没有在函数内声明或者声明的时候没有带var就是全局变量,拥有全局作用域。特殊:var a = b = c = 0; b与c是全局变量。
3.变量的作用域是以它声明时为准的,因为变量的作用域在js代码的解析阶段就已经完成规则的制定。
简单案例:
//变量的作用域 var t = 90; //全局作用域,在js代码中任何一个地方都可以访问 function f1(){ //f1函数 在全局作用域中 var t2 = 10; //t2是f1函数内部变量,只有在f1内可访问 console.log(t2); function f2(){ //f2函数 在f1函数的作用域中 var t3 = 20;//只能在f2函数内部才能访问 console.log(t3); return t2*t3; // 访问了父级作用域中的t3 } return f2(); } var m = f1(); console.log(m);
2.没有块级作用域
前面我说到JavaScript中没有块级作用域,这是对于es5 es6之前来说9(let const等)。for循环,while循环中定义的变量的作用域是函数级别的作用域。
例如:
//没有块级作用域 function f1(){ for(var i=0;i<10;i++){//i变量是在for中定义的 console.log(i);//打印1-9 } console.log(i);//可以访问到i变量 打印10 而在c++ Java等语言中是不行的 } f1();
3.变量提升 (hositing)
js引擎在执行js代码的时候,首先会先创建全局的EC(上下文)和函数的EC(如果有函数),在创建EC的时候已经把当前作
用域里面声明的变量初始化为undefined,怎么初始化呢?js引擎首先会在当前作用域去找var这个变量定义,发现有这个定义,那么就
把它提升到作用域的最前面,并且保存在内存中(即EC中的变量对象VO),设为undefined。
案例:
var a = 10; function f1(){ //在这里首先会创建f1的执行上下文 并把里面的变量初始化为undefined console.log(a); //代码执行到这里的时候, js引擎会去当前作用域内存中问有没有这个变量的声明,发现有,那么就给他初始的undefined //假如说下面没有var变量进行定义a,那么js就会向父级作用域中去找这个变量,直到找到为止 var a = 19; //在这里给a赋值了19 console.log(a); // 打印了19 } f1(); console.log(a); //这里无疑是10 没什么问题
所以,js引擎在创建上下文的时候,就会对有需要的变量进行变量提升,可以说是一种安全保护机制,ES6中对其进行了详细讨论。
注意:当变量声明和函数声明 为同一个名字的时候,函数的优先级高。
console.log(b); //打印b(){} var b = 9; function b(){ } console.log(b); //打印9
由于函数被提升到最前面,那么一开始打印的无疑是b(){} ,因为js是动态语言,把b重新赋值为9,覆盖掉之前的function。
案例一:
if ("a" in window) { var a = 1; } console.log(a);
首先看到你段代码,你的答案是什么?会不会是Uncaught ReferenceError: a is not defined?
告诉你,答案是1
首先,你要清楚var a = 1其实是定义了一个全局变量(属于window对象下的属性),因为if并不是块作用域,JavaScript中es5之前没有块作用域。所以这个条件判断是成立的。
再来看:
if (!("a" in window)) { var a = 1; } console.log(a);
那么这个应该是什么呢?答案是undefined,因为条件不成立,没有给a赋值成功,默认为undefined
案例二:
fun(); console.log(a); console.log(b); console.log(c); function fun(){ var a = b = c = 10; console.log("fun中的a="+a); console.log("fun中的b="+b); console.log("fun中的c="+c); }
你得答案是什么?
答案是:
由于a没有定义,所以直接报错,下面的两行代码被阻止执行了,假如把外面的console.log(a)注释掉呢?
fun(); //console.log(a); console.log(b); console.log(c); function fun(){ var a = b = c = 10; console.log("fun中的a="+a); console.log("fun中的b="+b); console.log("fun中的c="+c); }
输出的是:
为什么外面b c都会是10呢? 原因就是var a = b = c = 10 ;其中b c就是全局变量,如果你想定义三个内部变量,那么应该这样定义:
var a = 10 ,b = 10, c = 10;
弄懂了以上这些区别,基本上变量提升就没什么大问题了。以上就是本篇文章的所有内容,大家要是还不太了解的话,可以自己多实现两边就很容易掌握了哦!
相关推荐:
以上是细说JavaScript中的作用域与变量的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

typedef struct 在 C 语言中用于创建结构体类型别名,简化结构体使用。它通过指定结构体别名将一个新的数据类型作为现有结构体的别名。优点包括增强可读性、代码重用和类型检查。注意:在使用别名前必须定义结构体,别名在程序中必须唯一并且仅在其声明的作用域内有效。

Java 中的变量期望值异常可以通过以下方法解决:初始化变量;使用默认值;使用 null 值;使用检查和赋值;了解局部变量的作用域。

JavaScript 闭包的优点包括保持变量作用域、实现模块化代码、延迟执行和事件处理;缺点包括内存泄漏、增加了复杂性、性能开销和作用域链影响。

C++ 中的 #include 预处理器指令将外部源文件的内容插入到当前源文件中,以复制其内容到当前源文件的相应位置。主要用于包含头文件,这些头文件包含代码中需要的声明,例如 #include <iostream> 是包含标准输入/输出函数。

可以。C++ 允许函数嵌套定义和调用。外部函数可定义内置函数,内部函数可在作用域内直接调用。嵌套函数增强了封装性、可复用性和作用域控制。但内部函数无法直接访问外部函数的局部变量,且返回值类型需与外部函数声明一致,内部函数不能自递归。

C++智能指针的生命周期:创建:分配内存时创建智能指针。所有权转移:通过移动操作转移所有权。释放:智能指针离开作用域或被明确释放时释放内存。对象销毁:所指向对象被销毁时,智能指针成为无效指针。

JavaScript 中,this 的指向类型有:1. 全局对象;2. 函数调用;3. 构造函数调用;4. 事件处理程序;5. 箭头函数(继承外层 this)。此外,可以使用 bind()、call() 和 apply() 方法显式设置 this 的指向。

在 Vue 中,let 和 var 声明变量时在作用域上存在差异:作用域:var 具有全局作用域,let 具有块级作用域。块级作用域:var 不创建块级作用域,let 创建块级作用域。重新声明:var 允许在同一作用域内重新声明变量,let 不允许。
