第二章 Javascript 的语法
2.1 语法综述
标识符
- 语法关键字 : 命名语法(以及类型)
- 变量/常量 : 命名值(的存储位置)
绑定
- 语法关键字与语法(语义)逻辑的绑定 – 作用域的限定
- 变量与它所存储值的位置的绑定 – 变量生存周期的限定
2.1.1 标识符所绑定的语义
声明
- 约定变量的生存周期和逻辑的作用域
- - 纯粹陈述“值”的过程,被称为变量和类型声明
- 纯粹陈述“逻辑”的过程,被称为语句(含流程控制子句)
- 陈述“值与(算法的)逻辑”的关系的过程,被称为表达式
2.1.2 识别语法错误与运行错误
一般,Javascript 引擎会在代码装入时先进行语法分析,如果语法分析通不过,整个脚本代码块都不执行;
语法分析通过时,若执行过程中出错,那么在同一代码上下文中,出错点之后的代码将不再执行。
2.2 Javascript 的语法:变量声明
弱类型语言:只表明在表达式运算中不强制校验运算元的数据类型,并不表明该语言是否具有类型系统。
说 Javascript 是“无类型语言(untype language)” 是不正确的。
2.2.1 变量的数据类型
Javascript 没有明确的类型声明过程。
总的来说,Javascript 识别 6 种数据类型,并在运算过程中自动处理语言类型的转换。
2.2.1.1 基本数据类型
- undefined 未声明的变量,或者声明过但未赋值的变量的值
- number 除赋值操作之外,只有数值与数值的运算结果是数值;一些函数/方法的返回值是数值
- string 不能直接读取或修改字符串中的单一字符
- boolean true/false
- function 多重含义:函数、方法、构造器、类、函数对象
- object 基于原型继承的面向对象
任何一个变量或值的类型都可以(而且应当首先)使用 typeof 运算来得到。typeof 关键字可以像函数调用一样,在后面跟上一对括号。
2.2.1.2 值类型与引用类型
Javascript 中的值类型
- undefined 无值
- number
- boolean
- string 字符串在赋值运算中会按照引用类型的方式来处理
引用类型
- function
- object
全等(===)运算符用来对值类型/引用类型的实际数据进行比较和检查
- 一般表达式运算的结果总是值
- 函数/方法调用的结果可以返回值或者引用
- 值与引用、值与值之间即使等值(==),也不一定全等(===) 【NaN 与自身并不等值,也不全等】
- 两个引用之间如果等值(==),则一定全等(===)
2.2.2 变量声明
- 显式声明 – 使用关键字 var
- 隐式声明
解释器总是将显式声明理解为“变量声明”,而对隐式声明则不一定:
- 如果变量未被声明,则该语句是变量声明(并立即赋值)
- 如果变量已经声明过,则该语句是变量赋值语句
2.2.3 变量声明中的一般性问题
2.2.3.1 字符串直接量、转义符
用一对双引号或一对单引号来表示字符串直接量 ECMA 要求 Javascript 中的字符串必须是 Unicode 字符序列。
\ 除用于定义转义符之外,位于一行的末尾时,也用于表示连续的字符串声明。
空字符串长度值总为 0,也可以用作对象成员。
obj = { '' : 100 } alert(obj['']); // 100
2.2.3.2 数值直接量
总是以一个数字字符,或一个点字符“.”,以及不多于一个的正值符号“+”或负值符号“-”开始。
- 十六进制数值以 0x/0X 开始
- 八进制数值以 0 开始
- 其他为十进制整数或浮点数
十进制整数的存放个是可能是浮点数也可能是整形数,取决于引擎的实现。位运算总是以整数型的形式来运算 – 即使运算元是浮点数。
2.2.3.3 函数直接量声明
function functionName(){ //... }
() 不能省略,表示形式参数(在函数体内部使用的、有效的标识符名)列表。
函数体内部使用一个名为 arguments 的内部对象来存取调用中传入的实际参数。
2.2.3.4 正则表达式的常见问题
2.2.3.5 数组的常见问题
2.3 Javascript 的语法:表达式运算
page 59/60
(function(){ //... }());
最外层的 () 是强制运算符,返回调用结果
(function(){ //... })();
包围函数的 () 强制运算符运算“函数直接量声明”这个表达式,并返回一个函数自身的引用,然后通过函数调用运算符 () 来操作这个函数引用。
void function(){ //... }();
调用函数并忽略返回值。
function(){ //... }() function(){ //... }();
以上两种无法通过脚本引擎的语法检测,都不可执行。
在语法检测阶段,脚本引擎会认为下面的代码
function(){} function foo(){}
是函数声明。也就是说 function(){} 作为完整的语法结构被解释,因此相当于其后已经存在语句结束符。而 “();” 则被独立成一行进行语法解释,显示这是错误的语法。
2.5 面向对象变成的语法概要
2.5.1 对象直接量声明与实例创建
2.5.1.1 使用构造器创建对象实例
构造器其实是一个普通函数,不过此函数执行过程中,javascript 将传入 new 运算产生实例,并以该实例作为函数上下文环境中的 this 对象引用。
obj = new constructor[(arguments)]; // 产生对象的一个实例
参数表为空时与没有参数表是一致的,因此下面等价
obj = new constructor; obj = new constructor();
constructor 后面的括号不是函数调用的括号。否则
//错误的代码 obj = new (constructor());
就是合理的了
2.5.1.2 对象直接量声明
obj = {propertyName:expression[,...]}
2.5.2 对象成员列举、存取和删除
for…in 列举成员的显示成员
delete 不能删除:
- 用 var 声明的变量
- 直接继承自原型的成员
delete 不能删除继承自原型的成员,但如果修改了这个成员的值,仍然可以删除它 – 使它恢复到原型的值
delete 实际上是删除了实力的成员表中的
2.5.3 属性存取与方法调用
. [] 是运算符
2.5.4 对象及其成员的检查
- in
- typeof
- instanceof
2.5.5 可列举性
propertyIsEnumerable()
2.5.6 默认对象的指定
with
2.6 运算符的二义性
开发人员理解上的“二义性”
- , 增值运算符 参数分隔符;对象/数组声明分隔符
- + 增值运算符;正值运算符;连接运算符
- () 函数调用运算符 强制运算(优先级);参数声明
- ?: 条件运算符 :号有声明标签的含义;switch分支的含义;声明对象成员的含义
- 数组下标 数组直接量声明;对象成员存取;
- {} 函数直接量(代码部分的)声明;对象直接量声明;符合语句
- ; 空语句;语句分隔符
2.6.1 加号的二义性
规则:“如果表达式中存在字符串,则优先按照字符串连接进行运算”
注意:浏览器中 DOM 模型的很多至看起来是数字,其实是字符串
2.6.2 括号的二义性
2.6.3 冒号与标签的二义性
2.6.4 大括号的二义性
2.6.5 逗号的二义性
a = 1,2,3; a = (1,2,3); var a = 1,2,3;
var 声明会使连续运算表达式变为连续声明语句
2.6.6 方括号的二义性
a = [[1][1]]; // a = [undefined]; arr = [1]; a = arr[1];