JavaScript的语法要点 1 - Lexically Scoped Language

本文探讨了JavaScript中变量作用范围的独特性,对比C风格语言的BlockScope,介绍了JavaScript的FunctionScope特性,以及变量在函数体内任何位置定义时都会被提升至函数头部的现象。

作为从一开始接触C、C++、C#的程序员而言,JavaScript的语法对我来说有些古怪,通过最近一年的接触,对它有了一定的了解,于是想把它的一些语法要点记录下来。

1. Block Scope vs. Function Scope

JavaScript第一点与C不同的是变量的作用范围。我们都知道,C风格的编程语言中,变量的作用范围是两个大括号之间,变量在两个大括号之外是不可见的,我们称之为Block Scope。

而JavaScript则不然 - 变量在真个函数内以及此函数的内嵌函数中均可见,我们称之为Function Scope。比如:

function test(o){

  var i = 0;

  if (typeof o == "object"){

    var j = 0;

    for (var k = 0; k < 10; k++){

      console.log(k);

    }

    console.log(k); // k = 10, k虽然在for循环中定义,可是在for循环之外的整个函数体依然可见。

  }

  console.log(j); // j =0 或者j = undefined,j虽然在if块中声明并定义,可是它在整个函数体中依然可见。

}

2. Hoisting

JavaScript变量的另外一个奇特的地方还在于,在一个函数体内任何一个地方定义(defined)的变量,都被假定为其在函数的一开始处被定义(但是可能没有初始化)。也就是说,所有变量的定义都被"hoisted"(提升)到函数的开始处。比如下面这个例子:

var scope = "global";

function f(){

  console.log(scope); // 输出"undefined",而不是"global",因为本地的scope变量已经生效,只是还没有初始化。

  var scope = "local"; // 在此处初始化,但是其实已经在函数的开始处被声明了,因此上面的代码输出的是"undefined"

  console.log(scope); //输出"local"

}

总而言之,JavaScript是一个Lexically Scoped Language,即JavaScript是基于词法作用域(lexically scoped)的,所以标识符被固定在它们被定义的作用域而不是语法上或是其被调用时的作用域。

转载于:https://www.cnblogs.com/AllanDragoon/p/3539358.html

<think>好的,我现在需要帮助用户理解C++中的“lexically normal”用法。首先,我得确认用户的问题具体指的是什么。用户提到“lexically normal”,这可能与文件路径的处理有关,因为在C++17中,std::filesystem::path类有一个lexically_normal成员函数。 接下来,我要回忆相关的知识。lexically_normal函数的作用是将路径进行词法规范化,即消除路径中的冗余部分,比如.和..,以及多余的斜杠。例如,将"foo/./bar/../baz"规范化为"foo/baz"。这个过程不需要访问实际文件系统,仅基于词法分析。 然后,我需要检查用户提供的引用内容。虽然引用中提到了C++标准的发展(如引用2提到C++14和C++17),以及命名空间的使用(引用1),但并没有直接提到lexically_normal。不过,引用2确认了C++17的存在,这可能与filesystem库的引入相关,因为filesystem是在C++17中正式加入标准的。 接下来,我需要构造一个清晰的中文回答,结构要符合用户的要求:行内公式用$...$,独立公式用$$...$$,正确使用LaTeX,生成相关问题,并在引用处添加标识。用户的问题是关于用法,所以需要给出示例代码和解释。 然后,示例代码部分需要包含正确的C++代码,使用std::filesystem::path,并展示lexically_normal的效果。需要注意,用户可能不熟悉如何包含头文件和启用C++17,所以在代码注释中应注明需要C++17支持,并链接相应的库。 另外,要区分绝对路径和相对路径的处理。例如,绝对路径在规范化时会保留根目录,而相对路径会完全解析.和..。需要举例说明这两种情况。 之后,生成相关问题。可能的问题包括与文件系统实际状态的区别、与其他规范化方法的比较、异常处理,以及C++17之前的替代方案。这些问题有助于用户进一步探索该主题。 最后,确保回答中引用了用户提供的引用内容,尤其是引用2关于C++17的部分,以支持filesystem库的可用性。其他引用可能不相关,但引用3提到变参模板,可能与路径处理无关,可以忽略。引用4关于Go语言,也不相关,所以不需要涉及。</think>在C++标准库中,"lexically normal"是文件系统路径处理的重要概念,主要用于$\texttt{std::filesystem::path}$类[^2]。其核心功能是通过词法分析将路径转换为规范化形式,无需实际访问文件系统。 ### 核心功能 1. **消除冗余符号**:自动处理$./$(当前目录)和$../$(上级目录) 2. **标准化分隔符**:统一路径分隔符(Windows下将$/$转换为$\\$) 3. **压缩重复分隔符**:将连续分隔符合并为单个 ### 代码示例 ```cpp #include <filesystem> #include <iostream> int main() { using namespace std::filesystem; path p1 = "foo/./bar//../baz/."; std::cout << p1.lexically_normal() << "\n"; // 输出"foo/baz/" path p2 = "/../a/b/../c"; std::cout << p2.lexically_normal() << "\n"; // 输出"/a/c" } // 编译需添加C++17支持:-std=c++17 -lstdc++fs ``` ### 关键特性 $$ \text{词法规范化} \neq \text{物理文件系统解析} $$ 该操作仅基于字符串处理,不会检测文件系统实际存在状态。对网络路径或符号链接的处理需要配合$\texttt{std::filesystem::canonical}$使用[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值