javascript定义变量的关键字与词法环境

60 篇文章 0 订阅
55 篇文章 1 订阅

定义变量的3个关键字——var、let和const,还可以通过与词法环境的关系将其进行分类(换句话说,按照作用域分类)。可以将var分为一组,let与const分为一组。

使用关键字var

当使用关键字var时,该变量是在距离最近的函数内部或是在全局词法环境中定义的。(注意:忽略块级作用域)这是JavaScript由来已久的特性。

console.log("----------------------使用关键字var----------------------");
var globalNinja = 'Yoshi';//使用关键字var定义全局变量

function reportActivity() {
  //使用关键字var定义函数内部的全局变量
  var functionActivity = "jumping";

  for (var i = 1; i < 3; i++) {
    //使用关键字var在for循环中定义两个变量
    var forMessage = globalNinja + " " + functionActivity;
    //在for循环中可以访问块级变量,函数内的局部变量以及全局变量
    if (forMessage === 'Yoshi jumping') {
      console.log("Yoshi is jumping within the for block");
    }
    console.log("Current loop counter:" + i);
  }

  //在for循环外部,仍然可以访问for循环中定义的变量
  if (i === 3 && forMessage === 'Yoshi jumping') {
    console.log("Loop variables accessible outside of the loop");
  }
}

reportActivity();

//函数外部无法访问函数内部的局部变量
if (typeof functionActivity === 'undefined' && typeof i === 'undefined' && typeof forMessage === 'undefined') {
  console.log("We can not see function variables outside of a function.");
}

 

我们首先定义全局变量globalNinja,接着定义函数reportActivity,在该函数中使用循环并验证变量globalNinja的行为。可以看出,在循环体内可以正常访问块级作用域中的变量(变量i与forMessage)、函数体内的变量(functionActivity)以及全局变量(globalNinja)。

//但是JavaScript中特殊的并使得许多从其他语言转向JavaScript的开发者们困惑的是,即使在块级作用域内定义的变量,在块级作用域外仍然能够被访问:

if (i === 3 && forMessage === 'Yoshi jumping') {

console.log("Loop variables accessible outside of the loop");

}

这源于通过var声明的变量实际上总是在距离最近的函数内或全局词法环境中注册的,不关注块级作用域。下图展示了reportActivity函数内的for循环执行后的词法环境。

 

 

 

通过var声明的变量,在距离最近的函数内 或全局词法环境中定义(忽略块级作用域)。变量forMessage与i虽然是被包含在for循环中,但实际上是在reportActivity环境中注册的(距离最近的函数环境)

 

上述代码中展示了3种词法环境

1.变量globalNinja是在全局环境中定义的(距离最近的函数内或全局词法环境)。

2.reportActivity函数创建的函数环境,包含变量functionActivity、i与forMessage,这3个变量均是通过关键字var定义的,与它们距离最近的是reportActivity函数。

3.for循环的块级作用域,关键字var定义的变量忽略块级作用域。

 

使用let与const定义具有块级作用域的变量

var是在距离最近的函数或全局词法环境中定义变量,与var不同的是,let和const更加直接。

let和const直接在最近的词法环境中定义变量(可以是在块级作用域、循环内、函数内或全局环境内)。可以使用let和const定义块级别、函数级别、全局级别的变量。

console.log("----使用const与let关键字-------------");
//使用const定义全局变量,全局静态变量通常使用使用大写表示
const GLOBAL_NINJA = 'Yoshi';

function reportActivity() {
  //使用const定义函数内的局部变量
  const functionActivity = "jumping";

  //在for循环中,我们毫无意外的可以访问块级变量,函数变量和全局变量
  //使用let在for循环中定义两个变量
  for (let i = 1; i < 3; i++) {
    let forMessage = GLOBAL_NINJA + " " + functionActivity;
    if (forMessage === 'Yoshi jumping') {
      console.log("Yoshi is jumping within the for block");
    }
    console.log("Currrent loop counter:" + i);
  }

  //在for循环外部无法访问for循环内的变量
  if(typeof i === 'undefined' && typeof forMessage === 'undefined') {
    console.log("Yoshi is jumping within the for block");
  }
}

reportActivity();
//自然地,在函数外部无法访问任何一个函数的内部变量
if (typeof functionActivity === 'undefined' && typeof i === 'undefined' && typeof forMessage === 'undefined') {
  console.log("We can not see function variables outside of a function.");
}

 

 

 

reportActivity函数内的for循环执行完成之后的词法环境。此时我们仍然可以看到3个词法环境:全局环境(函数和块级作用域之外的全局代码)、reportActivity函数循环和for循环体。但是由于我们使用了关键字let和const,那么变量则是在距离最近的词法环境中定义的:变量GLOBAL_NINJA是在全局环境中定义的,变量functionActivity是在函数reportActivity中定义的,变量i与forMessage是在for循环的块级作用域中定义的。

当使用let与const声明变量时,变量是在距离最近的环境中定义的。在本例中,变量forMessage与i是在for循环的块级作用域中定义的,变量functionActivity是在函数reportActivity中定义的,变量GLOBAL_NINJA是在全局环境中定义的。

 参考《JavaScript忍者秘籍》

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript面试题的进阶可以包括以下几个方面: 1. 作用域变量提升:在JavaScript中,函数作用域块级作用域的概念是很重要的。了解变量提升和作用域链的工作原理对于理解JavaScript作用域规则至关重要。在题目中给出的代码中,变量name由于使用了var关键字声明,会被提升到函数作用域的顶部,但是在打印输出时还未被赋值,所以会输出undefined。而变量age使用let关键字声明,不会被提升,所以在console.log(age)时会报错。因此,上述代码的输出是undefined和ReferenceError。 2. 数据类型和类型转换:JavaScript有多种基本数据类型,包括数字、字符串、布尔值等。了解不同数据类型的特点以及类型转换的规则对于正确处理数据至关重要。在JavaScript中,使用双等号(==)进行比较时会发生隐式类型转换,这可能导致一些令人惊讶的结果。因此,在进行类型转换时需要格外小心。 3. 闭包和作用域:闭包是指函数能够访问并操作其定义时所在的词法环境中的变量。了解闭包的概念以及如何正确使用闭包可以帮助开发人员编写更高效和安全的代码。 4. 面向对象编程:JavaScript是一种面向对象的语言,它支持封装、继承和多态等面向对象的特性。了解如何使用构造函数、原型链和对象创建模式等概念可以帮助开发人员设计和组织复杂的代码结构。 5. 异步编程:JavaScript是一种单线程的语言,但是通过使用回调函数、Promise和async/await等机制,可以实现非阻塞的异步编程。理解JavaScript中的事件循环和异步编程模型对于编写高效的异步代码至关重要。 总结:JavaScript面试题的进阶包括作用域变量提升、数据类型和类型转换、闭包和作用域、面向对象编程以及异步编程等方面的知识。熟练掌握这些概念和技术,可以帮助您在JavaScript编码面试中取得优异的表现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值