JavaScript块级作用域绑定以及状态提升详解

目录
  • 前言
  • 作用域/执行上下文
  • var声明
  • 块级声明
  • 不声明的变量
    • 1.不使用关键字声明变量
    • 2.使用var声明的变量
  • var声明和块级声明的区别
    • 全局作用域绑定
    • 状态提升
  • 块级绑定的最佳实践
  • 函数声明提升
  • 总结

前言

在ES6之前,JavaScript只有经典的var声明,这给开发者带来了很多的困扰。在ES6出现后,又增加了let和const关键字的声明方式。这里会讲有关变量声明,作用域,状态提升相关知识。

作用域/执行上下文

在JavaScript的世界里,作用域可以分为三种,分别是全局作用域,函数作用域,块级作用域。

  • 全局作用域/执行上下文:默认或者是最基础的作用域。一个程序只有一个全局作用域,在JavaScript脚本存在的生命周期中都在执行堆栈的底部不会被弹出销毁。全局作用域中有一个全局对象(以浏览器环境为例,这个全局对象是window)。
  • 函数作用域:一个函数体内部是一个作用域。
  • 块级作用域:存在于块中——字符 { 和 } 之间的区域。(显然函数体也是由大括号包裹的,所以函数作用域也是块级作用域)

var 声明

var声明在全局作用域中,会被添加到全局对象上成为全局对象的属性。在函数作用域中则会被提升到函数顶部。而且不管实际是否会执行,都会在预编译阶段将函数声明提升,初始化操作则留在本地。

  • var声明的变量会被提升到当前作用域顶部(当前作用域只包括全局作用域或函数作用域,没有块级作用域)。

块级声明

临时死区(Temporal Dead Zone,TDZ):用来描述 let 和 const 的不提升效果的术语。JavaScript引擎在扫描代码发现变量声明时,要么将他们提升到作用域顶部(var声明),要么将声明放到TDZ(let声明和const声明)。访问在TDZ中的变量会触发运行时错误,只有执行过变量声明语句后,变量才会从TDZ中移出,然后才可以正常访问。

const 和 let 是块级标识符,所以声明的变量、常量也只在当前代码块中有效,一旦执行到块外就会立即被销毁。

  • let声明:可以将变量作用域限制在当前代码块中。在声明语句前会将变量放在临时死区。
  • const声明:用来声明常量,并且每个被被const声明的常量必须进行初始化。如果是对象,则对象中的值可以修改(cosnt声明不允许修改绑定,但可以修改绑定的值)

不声明的变量

在JavaScript中,定义一个变量不使用关键字声明也不会报错。但不建议这么做。

不管在全局,函数还是块作用域里,a = 0 这样的语句都会在 window 对象上创建 a 属性,实际上也就是执行了 window.a = 0 。而只有在全局作用域中,var a = 0才会在 window 上创建属性 a,即为 window.a = 0。

1. 不使用关键字声明变量

function func() {
    b = 0
    console.log(b);
    console.log(b === window.b);
}
func()
console.log(b === window.b);

// 输出结果
/*
0
true
true
*/

这部分代码执行过 func 函数,将变量 b 作为 window 对象的属性。

2. 使用 var 声明的变量

function func(x) {
    var b = 0
    console.log(b);
    console.log(b === window.b);
}
func(1)
console.log(b === window.b);

// 输出结果
/*
0
false
Uncaught ReferenceError: b is not defined
*/

这段代码就是正常的 var 声明的变量在函数作用域内提升。

var 声明和块级声明的区别

全局作用域绑定

  • var声明在全局作用域中时,会创建一个新的全局变量作为全局对象的属性(在浏览器中为window对象)。这意味着用 var 可能会无意中覆盖一个已经存在的全局变量。
  • 块级声明(let 或 const)会在全局作用域创建一个新的绑定,但该绑定不会添加为全局对象的属性。所以用块级声明不会覆盖全局变量,只能遮蔽它。
let RegExp = 'Hello!'
console.log(RegExp);
console.log(window.RegExp === RegExp);
// 结果
/*
Hello!
false
*/
复制代码

状态提升

  • var 声明的变量会提升到当前作用域顶部,在实例化之前为 undefined。var声明的变量限制范围为全局作用域或函数作用域。
  • 块级声明的变量会被存放到临时死区,在实例化前访问会报错 Uncaught ReferenceError
console.log(RegExp);
let RegExp = 'Hello!'
// Uncaught ReferenceError: Cannot access 'RegExp' before initialization

块级绑定的最佳实践

默认使用 const,只有确实需要改变变量的值时使用 let。

函数声明提升

函数提升优先级高于变量提升。

函数声明的特点:函数声明会被提升到当前作用域顶部,并且可以在当前作用域内部任何地方都可以访问到。

总结

到此这篇关于JavaScript块级作用域绑定以及状态提升的文章就介绍到这了,更多相关JS块级作用域绑定/状态提升内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaScript的作用域和块级作用域概念理解

    作用域永远都是任何一门编程语言中的重中之重,因为它控制着变量与参数的可见性与生命周期.讲到这里,首先理解两个概念:块级作用域与函数作用域. 什么是块级作用域呢? 任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域. 函数作用域就好理解了(*^__^*) ,定义在函数中的参数和变量在函数外部是不可见的. 大多数类C语言都拥有块级作用域,JS却没有.请看下文demo: //C语言 #include <stdio.h> void mai

  • js作用域及作用域链概念理解及使用

    (1)作用域 一个变量的作用域(scope)是程序源代码中定义的这个变量的区域. 1. 在JS中使用的是词法作用域(lexical scope) 不在任何函数内声明的变量(函数内省略var的也算全局)称作全局变量(global scope) 在函数内声明的变量具有函数作用域(function scope),属于局部变量 局部变量优先级高于全局变量 var name="one"; function test(){ var name="two"; console.log

  • js变量以及其作用域详解

    一.变量的类型 Javascript和Java.C这些语言不同,它是一种无类型.弱检测的语言.它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个变量.例如: 复制代码 代码如下: i=100;//Number类型 i="variable";//String类型 i={x:4};//Object类型 i=[1,2,3];//Array类型 JS的这种特性虽然让我们的编码更加灵活,但也带来了一个弊端,不利于Debug,编译器的弱检测让我们维护冗长的

  • 深入理解Javascript中this的作用域

    大家在使用Javascript的时候经常被this这个家伙搞得晕头转向的.对大多数有OOP开发经验的开发人员来说this是当前作用域中引用普通元素的标识符,但是在Javascript中它却显得古灵精怪的,因为它不是固定不变的,而是随着它的执行环境的改变而改变.在Javascript中this总是指向调用它所在方法的对象. 举一个简单的例子: 复制代码 代码如下: function test(){ alert(this); } var obj=function(){ var name='testO

  • javascript 函数及作用域总结介绍

    在js中使用函数注意三点:1.函数被调用时,它是运行在他被声明时的语法环境中的: 2.函数自己无法运行,它总是被对象调用的,函数运行时,函数体内的this指针指向调用该函数的对象,如果调用函数时没有明确指定该对象, this 默认指向 window ( strict 模式除外,本文不涉及 strict 模式): 3.函数是一种带有可执行代码的对象类型数据. 一.声明函数 1.使用 function 关键字 复制代码 代码如下: function myfun(a,b){ //声明名为myfun的函

  • JavaScript块级作用域绑定以及状态提升详解

    目录 前言 作用域/执行上下文 var声明 块级声明 不声明的变量 1.不使用关键字声明变量 2.使用var声明的变量 var声明和块级声明的区别 全局作用域绑定 状态提升 块级绑定的最佳实践 函数声明提升 总结 前言 在ES6之前,JavaScript只有经典的var声明,这给开发者带来了很多的困扰.在ES6出现后,又增加了let和const关键字的声明方式.这里会讲有关变量声明,作用域,状态提升相关知识. 作用域/执行上下文 在JavaScript的世界里,作用域可以分为三种,分别是全局作用

  • 深入理解ES6学习笔记之块级作用域绑定

    众所周知,js中的var声明存在变量提升机制,因此ESMAScript 6引用了块级作用域来强化对变量生命周期的控制 let const 声明不会被提升,有几个需要注意的点 1.不能被重复声明 假设作用域中已经存在某个标识符(无论该标识符是通过var声明还是let.const变量声明),此时再使用let或const关键定声明会抛错 var count=10 let count=20// 此处则会抛出错误,因为同一作用域内不能重复声明 如果当前作用域内嵌另一个作用域,便可在内嵌的作用域中用let声

  • JavaScript设计模式之命令模式和状态模式详解

    目录 命令模式 命令模式介绍 代码实现 状态模式 状态模式介绍 代码实现 小结 命令模式 命令模式介绍 命令模式(Command)的定义是:用于将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及执行可撤销的操作. 也就是说改模式旨在将函数的调用.请求和操作封装成一个单一的对象,然后对这个对象进行一系列的处理.此外,可以通过调用实现具体函数的对象来解耦命令对象与接收对象. 代码实现 <!DOCTYPE html> <html lang=&qu

  • 深入理解es6块级作用域的使用

    一.var 声明与变量提升机制 在JavaScript中使用var定义一个变量,无论是定义在全局作用域函数函数的局部作用域中,都会被提升到其作用域的顶部,这也是JavaScript定义变量的一个令人困惑的地方.由于es5没有像其它类C语言一样的块级作用域,因此es6增加了let定义变量,用来创建块级作用域. 我们来看一个var定义变量的示例: function setName(){ if(condition){ var name = 'loho'; console.log(name); }els

  • 深入理解JavaScript中的块级作用域、私有变量与模块模式

    本文详细的介绍了JavaScript中的块级作用域.私有变量与模块模式,废话就不多说了,具体如下: 1.块级作用域(私有作用域),经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数. (function(count){ for(var i=0;i<count;i++){ console.log(i);//=>0.1.2.3.4 } console.log(i);//=>5 })(5); (function(){ var now=new Date(); if(no

  • 为什么JavaScript没有块级作用域

    最近在看ES2015 实战,里面有句话是这么说的 JavaScript 中没有块级作用域 可能会对这个问题大家可能有点不理解,先看个例子 var a = [] for(var i = 0; i < 10; i++){ a[i] = function(){ console.log(i); } } a[6](); 我想很多人会觉得这个问题的结果是6,然而很不幸,答案是10.在试试别的呢.a[7]().a[8]().a[8]()结果都是10!! 由于JS在处理primitive的变量的时候,很多时候会

  • 解析JavaScript模仿块级作用域

    javaScript 没有块级作用域的概念.这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的,来看下面的例子: function outputNumbers(count){ for (var i=0; i < count; i++){ alert(i); } alert(i); //计数 } 这个函数中定义了一个for 循环,而变量i 的初始值被设置为0. 在Java.C++等语言中,变量i 只会在for 循环的语句块中有定义,循环一旦结束,变量i 就会被销毁.可是在JavaS

  • JavaScript匿名函数之模仿块级作用域

    匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途. 匿名函数:就是没有函数名的函数. 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种:这也是最常规的一种 function double(x){ return 2 * x; } 第二种:这种方法使用了Function构造函数,把参数列表和函数体都作为字符串,很不方便,不建议使用. var double = new Function('x', 'return 2 * x;'); 第三种: var

  • Javascript中的作用域及块级作用域

    一.块级作用域的说明 在学习JavaScript的变量作用域之前,我们应当明确几点: a.JavaScript的变量作用域是基于其特有的作用域链的. b.JavaScript没有块级作用域. c.函数中声明的变量在整个函数中都有定义. javascript的变量作用域,与平时使用的类C语言不同,例如C#中的代码: static void Main(string[] args) { if(true) { int number=10; } Console.WriteLine(number); } 这

  • 通过函数作用域和块级作用域看javascript的作用域链

    在ES6之前,javascript只有全局作用域和函数作用域.所谓作用域就是一个变量定义并能够被访问到的范围.也就是说如果一个变量定义在全局(window)上,那么在任何地方都能访问到这个变量,如果这个变量定义在函数内部,那么就只能在函数内部访问到这个变量. 全局作用域只要页面没关闭就会一直存在,而函数作用域只有在函数执行的时候才存在,执行完就销毁.且每次执行函数都会创建一个新的作用域. 那么什么是作用域链呢? 在了解作用域链之前,我们先了解一个执行期上下文的概念. 执行期上下文:当函数执行时,

随机推荐