转行学前端的第 25 天 : 了解 ECMAScript 基础语法和变量

444 阅读15分钟

我是小又又,住在武汉,做了两年新媒体,准备用 6 个月时间转行前端。

今日学习目标


昨天基于一些页面搜索,学习了《JavaScirpt 高级程序设计》(第三版)  第 2 章节中的 JavaScript 嵌入页面使用,今天主要是基于搜索来学习第 3 章节中的 ES 基础概念中语法和变量,又是适合学习的一天,加油,小又又!!!!


今日学习概要


任何语言的核心都必然会描述这门语言的最基础的工作原理,而描述的内容通常都要涉及这门语言的语法、操作符、数据类型、内置功能等用于构建复杂解决方案的基础概念。

  • 基础语法说明
    • 区分大小写
    • 标识符
    • 注释
    • 严格模式
    • 语句
  • 关键词和保留字
  • 变量

ES 规范基础语法

区分大小写


JavaScript 借鉴了 Java 的大部分语法,但同时也受到 _Awk,Perl _和 _Python_的影响。 

ECMAScript 中一切 (变量、函数名 和 操作符) 都是区分大小写的,并使用 **Unicode **字符集。举个例子,可以将单词 Früh (在德语中意思是“早”)用作变量名。

var Früh = "foobar";


但是,由于 JavaScript 是大小写敏感的,因此变量 frühFrüh 则是两个不同的变量。


标识符

WHAT


所谓标识符,就是指变量、函数、属性的名字,或者函数的参数。


HOW


标识符可以是按照下列格式规则组合的一或者多个字符

  • 第一个字符必须是一个字母,下划线(_)或者一个美元符号($)
  • 其他字符可以是字母、下划线、美元符号或者数字

注释

Javascript 注释的语法和 C++ 或许多其他语言类似,包含 单行注释块级注释

注释用来在源码中增加提示、笔记、建议、警告等信息,可以帮助阅读和理解源码。在调试时,可以用来将一段代码屏蔽掉,防止其运行。

第一种是 单行注释(single-line comment),使用 //,会将该行中符号以后的文本都视为注释

function comment() {
  // 这是单行注释
  console.log("你好,小又又!");
}
comment();

第二种是多行注释(multiple-line comment),使用 /* */ ,这种方式更加灵活:



比如,可以在单行内使用多行注释:
function comment() {
  /* 单行注释 */
  console.log("你好,小又又!");
}
comment();


也可以用来实现多行注释:
function comment() {
  /* 多行注释,
     直到终止符号才结束 */
  console.log("你好,小又又!");
}
comment();


多行注释也可以用于行内注释,但这样会使代码可读性变差,所以要谨慎使用:
function comment(x) {
  console.log("Hello " + x /* 引入x的值 */ + " !");
}
comment("world");


另外,块注释也可以用来屏蔽一段代码,只要将这段代码用块注释包裹起来就可以了:
function comment() {
  /* console.log("你好,小又又!"); */
}
comment();


注释中的 console.log() 的调用始终无效。这种方式可以屏蔽任意多行的代码,也可以屏蔽一行代码的一部分。


严格模式

有时你会看到非严格模式,被称为“sloppy mode”。这不是一个官方术语,但以防万一,你应该意识到这一点。


ECMAScript 5严格模式是采用具有限制性JavaScript变体的一种方式,从而使代码显示地 脱离“马虎模式/稀松模式/懒散模式“(sloppy)模式。

严格模式不仅仅是一个子集:它的产生是为了形成与正常代码不同的语义。

不支持严格模式与支持严格模式的浏览器在执行严格模式代码时会采用不同行为。

所以,在没有对运行环境展开特性测试来验证对于严格模式相关方面支持的情况下,就算采用了严格模式也不一定会取得预期效果。严格模式代码和非严格模式代码可以共存,因此项目脚本可以渐进式地采用严格模式。

严格模式对正常的 JavaScript语义做了一些更改。

  1. 严格模式通过抛出错误来消除了一些原有静默错误
  2. 严格模式修复了一些导致 JavaScript引擎难以执行优化的缺陷:有时候,相同的代码,严格模式可以比非严格模式下运行得更快
  3. 严格模式禁用了在ECMAScript的未来版本中可能会定义的一些语法。


如果你想改变你的代码,让其工作在具有限制性JavaScript环境中,请参阅转换成严格模式


案例


严格模式可以应用到整个脚本或个别函数中。不要在封闭大括弧 {} 内这样做,在这样的上下文中这么做是没有效果的。在 eval 、Function 、内联事件处理属性、  WindowTimers.setTimeout() 方法中传入的脚本字符串,其行为类似于开启了严格模式的一个单独脚本,它们会如预期一样工作。

  • 为脚本开启严格模式

为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句 "use strict"; (或 'use strict';

// 整个脚本都开启严格模式的语法
"use strict";
var v = "Hi!  I'm a strict mode script!";


这种语法存在陷阱,有一个大型网站已经被它坑倒了:不能盲目的合并冲突代码。试想合并一个严格模式的脚本和一个非严格模式的脚本:合并后的脚本代码看起来是严格模式。

反之亦然:非严格合并严格看起来是非严格的。合并均为严格模式的脚本或均为非严格模式的都没问题,只有在合并严格模式与非严格模式有可能有问题。

建议按一个个函数去开启严格模式(至少在学习的过渡期要这样做).

也可以将整个脚本的内容用一个函数包括起来,然后在这个外部函数中使用严格模式。这样做就可以消除合并的问题,但是这就意味着您必须要在函数作用域外声明一个全局变量。


  • 为函数开启严格模式

同样的,要给某个函数开启严格模式,得把 "use strict";  (或 'use strict';)声明_一字不漏地_放在函数体所有语句之前。

function strict() {
  // 函数级别严格模式语法
  'use strict';
  function nested() { 
    return "And so am I!"; 
  }
  return "Hi!  I'm a strict mode function!  " + nested();
}
function notStrict() { 
  return "I'm not strict."; 
}

严格模式的转变


详细请看严格模式中的变化


浏览器的严格模式


主流浏览器现在实现了严格模式。但是不要盲目的依赖它,因为市场上仍然有大量的浏览器版本只部分支持严格模式或者根本就不支持(比如IE10之前的版本)。严格模式改变了语义, 依赖这些改变可能会导致没有实现严格模式的浏览器中出现问题或者错误。

谨慎地使用严格模式,通过检测相关代码的功能保证严格模式不出问题。最后,记得_在支持或者不支持严格模式的浏览器中测试你的代码_。如果你只在不支持严格模式的浏览器中测试,那么在支持的浏览器中就很有可能出问题,反之亦然。


语句

在 JavaScript 中,指令被称为语句  Statement,并用分号(;)进行分隔。


如果一条语句独占一行的话,那么分号是可以省略的,但并不建议这么做。

var v = "你好,我是小又又!";

但如果一行中有多条语句,那么这些语句必须以分号分开。

var v1 = "你好,我是小又又!";var v2 = "你好,我是小又又!";var v3 = "你好,我是小又又!";var v4 = "你好,我是小又又!";

ECMAScript 规定了在语句的末尾自动插入分号(ASI)。


如果想要了解更多信息,请参阅 JavaScript 词法语法 。虽然不是必需的,但是在一条语句的末尾加上分号是一个很好的习惯。这个习惯可以大大减少代码中产生 bug 的可能性。
 
Javascript 源码从左往右被扫描并转换成一系列由 token 、控制字符、行终止符、注释和空白字符组成的输入元素。

空白字符指的是空格、制表符和换行符等。


关键词和保留字

关键字

ECMA-262 描述了一组具有特定用途的关键字,这些关键字可以用于表示控制语句的开始或者结束,或者用于执行特定操作等。

按照规定,关键字也是语言保留的,不能用作标识符


保留字


在 ECMAScript 规格中,这些关键字被当成关键字保留。目前它们没有特殊功能,但是在未来某个时间可能会加上。所以这些保留字不能当成标识符使用。

这些关键字在严格模式和非严格模式中均不能使用。

  • enum

以下关键字只在严格模式中被当成保留关键字:

  • implements
  • interface
  • let
  • package
  • private
  • protected
  • public
  • static

以下关键字只在模块代码中被当成保留关键字:

  • await


之前保留关键字


这里是之前版本中的ECMAScript(1到3)中的保留关键字:

  • abstract
  • boolean
  • byte
  • char
  • double
  • final
  • float
  • goto
  • int
  • long
  • native
  • short
  • synchronized
  • transient
  • volatile

另外,直接量nulltruefalse同样不能被当成标识使用。


变量

基础说明

变量 是存储值的容器。

基础语法

let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN];

var1, var2, …, varN 变量名。必须是合法的标识符。 value1, value2, …, valueN 变量的初始值。可以是任意合法的表达式。


声明变量

要声明一个变量,先输入关键字 letvar,然后输入合适的名称:

let myVariable;

注: 行末的分号表示当前语句结束,不过只有在单行内需要分割多条语句时,这个分号才是必须的。然而,一些人认为每条语句末尾加分号是一种好的风格。分号使用规则的更多细节请参阅 JavaScript 分号使用指南(英文页面)。

注: 几乎任何内容都可以作为变量名,但还是有一些限制(请参阅 变量命名规则)。如果你不确定,还可以 验证变量名 是否有效。

注: JavaScript 对大小写敏感,myVariablemyvariable 是不同的。如果代码出现问题了,先检查一下大小写!


变量赋值

变量定义后可以进行赋值

myVariable = '李雷';

也可以将定义、赋值操作写在同一行

let myVariable = '李雷';

可以直接通过变量名取得变量的值

myVariable;

变量在赋值后是可以更改的:

let myVariable = '李雷';
myVariable = '韩梅梅';

在严格模式下,不能定义名为 eval 或 arguments 的变量,否则会导致语法错误~~~~


var 与 let 的区别

“为什么我们需要两个关键字来定义变量?”,“为什么有 varlet 呢?"。


原因是有些历史性的。 回到最初创建 JavaScript 时,是只有 var 的。 在大多数情况下,这种方法可以接受, 但有时在工作方式上会有一些问题——它的设计会令人困惑或令人讨厌 。 因此,let 是在现代版本中的 JavaScript 创建的一个新的关键字,用于创建与 var 工作方式有些不同的变量,解决了过程中的问题。

下面解释几个简单的差异,我们现在不会讨论所有的差异

首先,如果你编写一个声明并初始化变量的多行 JavaScript 程序,你可以在初始化一个变量之后用 var 声明它,它仍然可以工作。 

myName = 'Chris';
function logName() {
  console.log(myName);
}
logName();
var myName;

Note: 只有在 web 文档中运行多行 JavaScript 时才会有这种效果,当在 JavaScript 控制台中键入单独的行,这将不起作用。


这是由于变量的提升,更多细节请阅读变量提升

但提升操作不再适用于 let 。如果将上面例子中的 var 替换成 let 将不起作用并引起一个错误。 这是一件好事——因为初始化后再声明一个变量会使代码变得混乱和难以理解。

其次,当你使用 var 时,可以根据需要多次声明相同名称的变量,但是 let 不能。 以下将有效:

var myName = 'Chris';
var myName = 'Bob';


但是以下内容会在第二行引发错误:

let myName = 'Chris';
let myName = 'Bob';


你必须这样做:

let myName = 'Chris';
myName = 'Bob';


同样,这是一个明智的语言决定。没有理由重新声明变量——这只会让事情变得更加混乱。

出于这些以及其他原因,我们建议在代码中尽可能多地使用 let,而不是 var。因为没有理由使用 var,除非需要用代码支持旧版本的 Internet Explorer (它直到第 11 版才支持 let ,现代的 Windows Edge 浏览器支持的很好)。


松散类型

ECMAScript 的变量是松散类型的,所有松散类型就是可以用来保存任何类型的数据。

换句话说。每个变量仅仅是一个用于保存值得占位符而已。

松散类型详细说明

JavaScript 里的变量和其他语言有很大的不同,JavaScript 的变量是一个松散的类型,松散类型变量的特点是变量定义时候不需要指定变量的类型,变量在运行时候可以随便改变数据的类型,但是这种特性并不代表 JavaScript 变量没有类型,当变量类型被确定后 JavaScript 的变量也是有类型的。

注意事项


  • JavaScript 松散类型 不可以理解为了 JavaScript 变量可以随意定义~~~~


即你可以不用var定义,也可以使用 var 定义,其实在 JavaScript 语言里变量定义没有使用 var,变量必须有赋值操作,只有赋值操作的变量是赋予给 window,这其实是 JavaScript 语言设计者提升, JavaScript 安全性的一个做法。

  • JavaScript 语言的松散类型的特点以及运行时候随时更改变量类型的特点,虽然 JavaScript 变量的定义是在运行期进行的,更有甚者有些人认为javascript代码只有运行期,其实这种理解是错误的~~~~


JavaScript 代码在运行前还有一个过程就是:预加载,预加载的目的是要事先构造运行环境例如全局环境,函数运行环境,还要构造作用域链。

而环境和作用域的构造的核心内容就是指定好变量属于哪个范畴,因此在 JavaScript 语言里变量的定义是在预加载完成,而非在运行时期。 



#### 通用命名方式
具体命名方式 详细说明
小驼峰命名 (骆驼式命令法,也叫小驼峰命名lowercamel),除了第一个单词之外,函数名中的每一个逻辑断点都有一个大写字母来标记,形如thisIsAnApple。近年来越来越流行了,在许多新的函数库和Microsoft Windows这样的环境中,它使用得当相多另一方面。
pascal命名法 (帕斯卡),与骆驼命名法类似只不过骆驼命名法是首字母小写,而帕斯卡命名法是首字母大写,形如ThisIsAnApple
下划线命名法 形如this_is_an_apple,下划线法是c出现后开始流行起来的。
中划线命名法 形如this-is-an-apple
匈牙利命名法(Hungarian) 广泛应用于象Microsoft Windows这样的环境中Windows 编程中用到的变量(还包括宏)的命名规则匈牙利命名法,这种命名技术是由一位能干的 Microsoft 程序员查尔斯- 西蒙尼(Charles Simonyi) 提出的

匈牙利命名法通过在变量名前面加上相应的小写字母的符号标识作为前缀,标识出变量的作用域,类型等这些符号可以多个同时使用,顺序是先m_(成员变量), 再指针,再简单数据类型,再其它。

例如:m_lpszStr 表示指向一个以0字符结尾的字符串的长指针成员变量

匈牙利命名法关键是:标识符的名字以一个或者多个小写字母开头作为前缀;前缀之后的是首字母大写的一个单词或多个单词组合,该单词要指明变量的用途属性+类型+描述

属性一般是小写字母+:
- g
:全局变量
- m_:类成员变量
- s_:静态变量
- c_:常量

类型就多了:
- b:bool
- sz:以零结束的字符串
- p:指针
- n:整整
- dw:双字
- l:长整型
- 无符号:u
- 函数:fn

推荐命名方式

具体类型 推荐命名方式
变量名 必须使用camel命名法
参数名 必须使用camel命名法
方法/属性 必须使用camel命名法
私有(保护)成员 必须以下划线_开头
常量名 必须使用全部大写的下划线命名法,如IS_DEBUG_ENABLED
类名 必须使用pascal命名法
枚举名 必须使用pascal命名法
枚举的属性 必须使用全部大写的下划线命名法
命名空间 必须使用camel命名法

注意事项

  • 语义 ---- 命名同时还需要关注语义,
  • 变量名 ---- 应当使用名词
  • boolean类型 ---- 应当使用ishas等起头,表示其类型;
  • 函数名 ---- 应当用动宾短语
  • 类名应当用名词。

今日学习总结


今日心情


今日学习了第 3 章节中的 ES 基础概念中语法和变量,了解了注释和变量相关规范~~~~,感觉很不错,希望明天学习到更多东西~~~~

本文使用 mdnice 排版