9月阅读周·JavaScript权威指南:语句,其他语句类型篇

举报
叶一一 发表于 2024/09/24 09:20:15 2024/09/24
【摘要】 背景去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。没有计划的阅读,收效甚微。新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。这个“玩法”虽然常见且板正,但是有效,已经坚持阅读七个月。已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScri...

背景

去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。

没有计划的阅读,收效甚微。

新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。

这个“玩法”虽然常见且板正,但是有效,已经坚持阅读七个月。

已读完书籍《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》

当前阅读周书籍《JavaScript权威指南》

其他语句类型

with语句

作用域链(scope chain),一个可以按序检索的对象列表,通过它可以进行变量名解析。with语句用于临时扩展作用域链,它具有如下的语法:

  with(object)
  statement

这条语句将object添加到作用域链的头部,然后执行statement,最后把作用域链恢复到原始状态。

在严格模式中是禁止使用with语句的,并且在非严格模式里也是不推荐使用with语句的,尽可能避免使用with语句。那些使用with语句的JavaScript代码非常难于优化,并且同没有使用with语句的代码相比,它运行得更慢。

在对象嵌套层次很深的时候通常会使用with语句来简化代码编写。例如,在客户端JavaScript中,可能会使用类似下面这种表达式来访问一个HTML表单中的元素:

  document.forms[0].address.value

如果这种表达式在代码中多次出现,则可以使用with语句将form对象添加至作用域链的顶层:

  with(document.forms[0]){//直接访问表单元素,例如:
  name.value="";
  address.value="";
  email.value="";
  }

这种方法减少了大量的输入,不用再为每个属性名添加document.forms[0]前缀。这个对象临时挂载在作用域链上,当JavaScript需要解析诸如address的标识符时,就会自动在这个对象中查找。当然,不使用with语句的等价代码可以写成这样:

  var f=document.forms[0];
  f.name.value="";
  f.address.value="";
  f.email.value="";

不要忘记,只有在查找标识符的时候才会用到作用域链,创建新的变量的时候不使用它,看一下下面这行代码:

  with(o)x=1;

如果对象o有一个属性x,那么这行代码给这个属性赋值为1。但如果o中没有定义属性x,这段代码和不使用with语句的代码x=1是一模一样的。它给一个局部变量或者全局变量x赋值,或者创建全局对象的一个新属性。with语句提供了一种读取o的属性的快捷方式,但它并不能创建o的属性。

debugger语句

debugger语句通常什么也不做。然而,当调试程序可用并运行的时候,JavaScript解释器将会(非必需)以调式模式运行。实际上,这条语句用来产生一个断点(breakpoint),JavaScript代码的执行会停止在断点的位置,这时可以使用调试器输出变量的值、检查调用栈等。例如,假设由于调用函数f()的时候使用了未定义的参数,因此f()抛出一个异常,但无法定位到底是哪里抛出了异常。为了有助于调试这个问题,需要修改函数f():

  function f(o){
  if(o===undefined)debugger;//这一行代码只是用于临时调试
  ...//函数的其他部分
  }

这时,当调用f()的时候没有传入参数,程序将停止执行,这时可以通过调试器检测调用栈并找出错误产生的原因。

在ECMAScript 5中,debugger语句正式加入到这门语言里。但在相当长的一段时间里,主流浏览器厂商已经将其实现了。注意,可用的调试器是远远不够的,debugger语句不会启动调试器。但如果调试器已经在运行中,这条语句才会真正产生一个断点。例如,如果使用Firefox的调试扩展插件Firebug,则必须首先为待调试的网页启用Friebug,这样debugger语句才能正常工作。

"use strict"

"use strict"是ECMAScript 5引入的一条指令。指令不是语句(但非常接近于语句)。"use strict"指令和普通的语句之间有两个重要的区别:

  • 它不包含任何语言的关键字,指令仅仅是一个包含一个特殊字符串直接量的表达式(可以是使用单引号也可以使用双引号),对于那些没有实现ECMAScript 5的JavaScript解释器来说,它只是一条没有副作用的表达式语句,它什么也没做。将来的ECMAScript标准希望将use用做关键字,这样就可以省略引号了。
  • 它只能出现在脚本代码的开始或者函数体的开始、任何实体语句之前。但它不必一定出现在脚本的首行或函数体内的首行,因为"use strict"指令之后或之前都可能有其他字符串直接量表达式语句,并且JavaScript的具体实现可能将它们解析为解释器自有的指令。在脚本或者函数体内第一条常规语句之后字符串直接量表达式语句只当做普通的表达式语句对待;它们不会当做指令解析,它们也没有任何副作用。

使用"use strict"指令的目的是说明(脚本或函数中)后续的代码将会解析为严格代码(strict code)。如果顶层(不在任何函数内的)代码使用了"use strict"指令,那么它们就是严格代码。如果函数体定义所处的代码是严格代码或者函数体使用了"use strict"指令,那么函数体的代码也是严格代码。如果eval()调用时所处的代码是严格代码或者eval()要执行的字符串中使用了"scrict code"指令,则eval()内的代码是严格代码。

严格代码以严格模式执行。ECMAScript 5中的严格模式是该语言的一个受限制的子集,它修正了语言的重要缺陷,并提供健壮的查错功能和增强的安全机制。严格模式和非严格模式之间的区别如下(前三条尤为重要):

  • 在严格模式中禁止使用with语句。
  • 在严格模式中,所有的变量都要先声明,如果给一个未声明的变量、函数、函数参数、catch从句参数或全局对象的属性赋值,将会抛出一个引用错误异常(在非严格模式中,这种隐式声明的全局变量的方法是给全局对象新添加一个新属性)。
  • 在严格模式中,调用的函数(不是方法)中的一个this值是undefined。(在非严格模式中,调用的函数中的this值总是全局对象)。

总结

“使某件事发生”的一个方法是计算带有副作用的表达式。诸如赋值和函数调用这些有副作用的表达式,是可以作为单独的语句的,这种把表达式当做语句的用法也称做表达式语句(expression statement)。类似的语句还有声明语句(declaration statement),声明语句用来声明新变量或定义新函数。

JavaScript程序无非就是一系列可执行语句的集合。默认情况下,JavaScript解释器依照语句的编写顺序依次执行。另一种“使某件事发生”的方法是改变语句的默认执行顺序。



作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。