"Code tailor",为前端开发者提供技术相干资讯以及系列根底文章,微信关注“小和山的菜鸟们”公众号,及时获取最新文章。
前言
在开始学习之前,咱们想要告诉您的是,本文章是对JavaScript
语言常识中 "语言根底-语法和变量" 局部的总结,如果您已把握上面常识事项,则可跳过此环节间接进入题目练习
- JavaScript 语法
- 申明变量与赋值
汇总总结
第一段代码
在开始学习 JavaScript
时,咱们先看一段 JavaScript
代码,如下:
console.log('Hello JavaScript!')
你能猜到这段代码的后果吗?这段代码的操作就是在控制台输入后果是 Hello JavaScript!
,到这里第一段代码就完结了。
JavaScript 语法
辨别大小写
你须要晓得,ECMAScript
中所有都辨别大小写。无论是变量、函数名还是操作符,都辨别大小写。举个例子,变量 XHS
和变量 xhs
是两个不同的变量。
标识符
所谓标识符,就是变量、函数、属性或函数参数的名称。标识符能够由一或多个下列字符组成:
- 第一个字符必须是一个字母、下划线(
_
)或美元符号($
); - 剩下的其余字符能够是字母、下划线、美元符号或数字。
标识符中的字母能够是扩大 ASCII(Extended ASCII)
中的字母,也能够是 Unicode
的字母字符.
依照常规,ECMAScript
标识符应用驼峰大小写模式,即第一个单词的首字母小写,前面每个单词的首字母大写,如:
xhsRookiesxhsRookiesBoy
尽管这种写法并不是强制性的,但因为这种模式跟 ECMAScript
内置函数和对象的命名形式统一, 所以算是最佳实际。
留神 关键字、保留字、true
、false
和null
不能作为标识符。
代码正文
JavaScript
中有两种正文形式:单行正文和多行正文。
正文的代码在程序中不会执行
单行正文以两个斜杠字符结尾,如:
// 单行正文
多行正文以一个斜杠和一个星号(/*
)结尾,以它们的反向组合(*/
)结尾,如:
/* 这是多行 正文 */
严格模式
ECMAScript 5
减少了严格模式(strict mode
)的概念。严格模式是一种不同的 JavaScript
解析和执行模型,ECMAScript 3
的一些不标准写法在这种模式下会被解决,对于不平安的流动将抛出谬误。要对整个脚本启用严格模式,在脚本结尾加上这一行:
'use strict'
尽管看起来像个没有赋值给任何变量的字符串,但它其实是一个预处理指令。任何反对 JavaScript
的引擎看到它都会切换到严格模式。抉择这种语法模式的目标是不毁坏 ECMAScript 3
语法。
也能够独自指定一个函数在严格模式下执行,只有把这个预处理指令放到函数体结尾即可:
function doSomething() { 'use strict' // 函数体}
严格模式会影响 JavaScript
执行的很多方面,所有古代浏览器都反对严格模式。
语句
ECMAScript
中的语句以分号结尾。省略分号意味着由解析器确定语句在哪里结尾,如上面的例子所示:
var sum = a + b // 没有分号也无效,但不举荐var diff = a - b // 加分号无效,举荐
即便语句开端的分号不是必须的,也应该加上。记着加分号有助于避免省略造成的问题,比方能够防止输出内容不残缺。此外,加分号也便于开发者通过删除空行来压缩代码(如果没有结尾的分号,只删除空行,则会导致语法错误)。加分号也有助于在某些状况下晋升性能,因为解析器会尝试在适合的地位补上分号以纠正语法错误。
关键字与保留字
ECMA-262
形容了一组保留的关键字,这些关键字有非凡用处,比方示意管制语句的开始和完结,或者执行特定的操作。依照规定,保留的关键字不能用作标识符或属性名。
break do in typeofcase else instanceof varcatch export new voidclass extends return whileconst finally super withcontinue for switch yielddebugger function thisdefault if throwdelete import try
标准中也形容了一组将来的保留字,同样不能用作标识符或属性名。尽管保留字在语言中没有特定用处,但它们是保留给未来做关键字用的。以下是 ECMA-262
第 6 版为未来保留的所有词汇。
始终保留:
enum
严格模式下保留
implements package publicinterface protected staticlet private
模块代码中保留
await
申明变量并赋值
在 JavaScript
中,有 3 个关键字能够申明变量: var
、const
和 let
。其中,var
在 ECMAScript
的所有版本中都能够应用,而 const
和 let
只能在 ECMAScript 6
(将在前面学到) 及更晚的版本中应用。
var 关键字
要定义变量,能够应用 var
关键字,后跟变量名:
var xhsRookies
这行代码定义了一个名为 xhsRookies
的变量,能够用它保留任何类型的值。ECMAScript
实现变量初始化,因而能够同时定义变量并设置它的值:
var xhsRookies = 'hi'
xhsRookies
被定义为一个保留字符串值 hi
的变量。像这样初始化变量不会将它标识为字符串类型,只是一个简略的赋值而已。随后,不仅能够扭转保留的值,也能够扭转值的类型:
var xhsRookies = 'hi'xhsRookies = 100 // 非法,但不举荐
在这个例子中,变量 xhsRookies
首先被定义为一个保留字符串值 hi
的变量,而后又被重写为保留了数值 100
。尽管不举荐扭转变量保留值的类型,但这在 ECMAScript
中是齐全无效的。
1. var 申明作用域
应用 var
操作符定义的变量会成为蕴含它的函数的局部变量。比方,应用 var
在一个函数外部定义一个变量,就意味着该变量将在函数退出时被销毁:
function xhsTest() { var xhsRookies = 'hi' // 局部变量}xhsTest()console.log(xhsRookies) // 出错!
这里,xhsRookies
变量是在函数外部应用 var
定义的。函数叫 xhsTest()
,调用它会创立这个变量并给它赋值。调用之后变量随即被销毁,因而示例中的最初一行会导致谬误。不过,在函数内定义变量时省略 var
操作符,能够创立一个全局变量:
function xhsTest() { xhsRookies = 'hi' // 全局变量}xhsTest()console.log(xhsRookies) // "hi"
去掉之前的 var
之后,xhsRookies
就变成了全局变量。只有调用一次函数 xhsTest()
,就会定义这个变量,并且能够在函数内部拜访到。
尽管能够通过省略 var 操作符定义全局变量,但不举荐这么做。在部分作用域中定义的全局变量很难保护,也会造成困惑。
如果须要定义多个变量,能够在一条语句中用逗号分隔每个变量(及可选的初始化):
var xhsRookies = 'hi', xhsFound = false, xhsNumber = 29
这里定义并初始化了 3 个变量。
2. var 申明晋升
应用 var
时,上面的代码不会报错。这是因为应用这个关键字申明的变量会主动晋升到块作用域 5 顶部:
{ console.log(xhsNumber) // undefined var xhsNumber = 26}
之所以不会报错,是因为 ECMAScript
运行时把它看成等价于如下代码:
{ var xhsNumber console.log(xhsNumber) // undefined xhsNumber = 26}
这就是所谓的“晋升”(hoist
),也就是把所有变量申明都拉到块作用域的顶部。
let 申明
let
跟 var
的作用差不多,但有着十分重要的区别。最显著的区别是,let
申明的范畴是块作用域, 而 var
申明的范畴是函数作用域。
{ var xhsRookies = 'xhs-rookies' console.log(xhsRookies) // xhs-rookies}console.log(xhsRookies) // xhs-rookies
{ let xhsNumber = 26 console.log(xhsNumber) // 26}console.log(xhsNumber) // ReferenceError: xhsNumber 没有定义
在这里,xhsNumber
变量之所以不能在块作用域内部被援用,是因为它的作用域仅限于该块外部。块作用域是函数作用域的子集,因而实用于 var
的作用域限度同样也实用于 let
。
let
也不容许同一个块作用域中呈现冗余申明。这样会导致报错:
var xhsRookiesvar xhsRookieslet xhsNumberlet xhsNumber // SyntaxError;标识符xhsNumber曾经申明过了
当然,JavaScript
引擎会记录用于变量申明的标识符及其所在的块作用域,因而嵌套应用雷同的标识符不会报错,而这是因为同一个块中没有反复申明:
var xhsRookies = 'xhs-rookies'console.log(xhsRookies) // 'xhs-rookies'{ var xhsRookies = 'xhs-rookies-boy' console.log(xhsRookies) // 'xhs-rookies-boy'}let xhsNumber = 30console.log(xhsNumber) // 30{ let xhsNumber = 26 console.log(xhsNumber) // 26}
对申明冗余报错不会因混用 let
和 var
而受影响。这两个关键字申明的并不是不同类型的变量, 它们只是指出变量在相干作用域如何存在。
var xhsRookieslet xhsRookies // SyntaxErrorlet xhsNumbervar xhsNumber // SyntaxError
1. 全局申明
与var
关键字不同,应用 let
在全局作用域中申明的变量不会成为 window
对象的属性(var
申明的变量则会)。
var xhsRookies = 'xhsRookies'console.log(window.xhsRookies) // 'xhsRookies'let xhsNumber = 26console.log(window.xhsNumber) // undefined
不过,let
申明依然是在全局作用域中产生的,相应变量会在页面的生命周期内存续。因而,为了 防止 SyntaxError
,必须确保页面不会反复申明同一个变量。
2. let 作用域
在 let
呈现之前,代码块中定义的迭代变量会渗透到内部:
{ var xhs = 5}console.log(xhs) // 5
改成应用 let
之后,这个问题就隐没了,因为 let
变量的作用域仅限于代码块外部:
{ let xhs = 0}console.log(xhs) // ReferenceError: xhs 没有定义
const 申明
const
的行为与 let
基本相同,惟一一个重要的区别是用它申明变量时必须同时初始化变量,且尝试批改 const
申明的变量会导致运行时谬误。
const xhsNumber = 26xhsNumber = 36 // TypeError: 给常量赋值// const 也不容许反复申明const xhsRookies = 'xhs-rookies'const xhsRookies = 'xhs-rookies-boy' // SyntaxError// const 申明的作用域也是块const xhsRookies = 'xhs-rookies'console.log(xhsRookies) // xhs-rookies
变量命名规定
- 严格辨别大小写(大写的变量和小写的变量是不同的变量);
- 变量名能够由数字、字母(大小写都能够)、下划线、美元符(
$
)组成,然而不能以数字结尾; - 不能是
javascript
中的关键字和保留字,如:if
,else
,function
等; - 变量名须要有意义,即语义化,加强代码可读性,比方:存储年龄用
age
,姓名用name
,能够避免过段时间就不了解代码是什么了,也能够避免单干时他人看不懂; - 应用驼峰命名法:从第二个单词开始,首字母大写,如用户集体数据(
userPersonalData
);
题目自测
一:下列代码输入后果是什么?
var xhsRookies = 'hello'function textFun() { var xhsRookies = 'hi'}console.log(xhsRookies)
- A.
hello
- B.
hi
- C.
hi hello
- D.
hello hi
二: 下列代码输入后果是什么?
console.log(xhsRookies)var xshRookies = 'xhs-rookies'console.log(xhsNumber)let xhsNumber = 26
三: 下列代码输入后果是什么?
const xhsNumber = 26xhsNumber = 36console.log(xhsNumber)
题目解析
一、
Answer:A
这道题考查的是 var
申明作用域,在第一行 xhsRookies
变量在 textFun
函数作用域外应用 var
定义的,第三行 xhsRookies
变量是在 textFun
作用域外部应用 var
定义的。所以最初一行输入 xhsRookies
其实是第一行定义的,后果是:hello
二、
Answer:
undefined
ReferenceError: Cannot access 'xhsNumber' before initialization
此题考查的是变量的晋升,输入 xshRookies
时,因为 xshRookies
应用 var
申明的,存在变量晋升,所以在输入前会认为 var xshRookies
并未赋值,所以是undefind
;在解析代码时,JavaScript
引擎也会留神呈现在块前面的 let
申明,只不过在此之前不能以任何形式来援用未声明的变量。在 let
申明之前的执行霎时被称为“暂时性死区”(temporal dead zone
),在此阶段援用任何前面才申明的变量都会抛出 ReferenceError
。
三、
Answer:
TypeError: Assignment to constant variable.
此题考查的是 const
申明特点,用它申明变量时必须同时初始化变量,且尝试批改 const
申明的变量会导致运行时谬误。