1.语法:
区分大小写:ECMAScript 中的一切(变量、函数名和操作符)都区分大小写。这也就意味着,变量名test 和变量名Test 分别表示两个不同的变量。而函数名不能使用typeof,因为它是一个关键字(3.2 节介绍关键字),但typeOf 则完全可以是一个有效的函数名。
标识符:就是指变量、函数、属性的名字,或者函数的参数。第一个字符必须是一个字母、下划线(_)或一个美元符号($);其他字符可以是字母、下划线、美元符号或数字。标识符中的字母也可以包含扩展的ASCII 或Unicode 字母字符(如À和Æ),但不推荐这样做。(不能把关键字、保留字、true、false 和null 用作标识符。)
注释:ECMAScript 使用C 风格的注释,包括单行注释和块级注释。
// 单行注释
/*
* 块级注释以一个斜杠和一个星号(/*)开头,以一个星号和一个斜杠(*/)结尾
* 虽然注释中的第二和第三行都以一个星号开头,但这不是必需的。
* 之所以添加那两个星号,纯粹是为了提高注释的可读性(这种格式在企业级应用中用得比较多)
*/
<!-- 可以是单行,也可以是多行 -->
严格模式:严格模式通过抛出错误来消除了一些原有静默错误。 严格模式修复了一些导致 JavaScript引擎难以执行优化的缺陷:有时候,相同的代码,严格模式可以比非严格模式下运行得更快。 严格模式禁用了在ECMAScript的未来版本中可能会定义的一些语法。在没有对运行环境展开特性测试来验证对于严格模式相关方面支持的情况下,就算采用了严格模式也不一定会取得预期效果。严格模式代码和非严格模式代码可以共存,因此项目脚本可以渐进式地采用严格模式。
//将过失错误转成异常
//(没有mistypedVaraible变量)因为变量名拼写错误,这一行代码就会抛出ReferenceError
"use strict";
var mistypedVariable;
mistypedVaraible = 17;
//严格模式会使引起静默失败(silently fail,不报错也没有任何效果)的赋值操作抛出异常
//给不可写属性赋值,抛出TypeError错误
"use strict";
var obj1 = {};
Object.defineProperty(obj1, "x", { value: 42, writable: false });
obj1.x = 9;
//给只读属性赋值,抛出TypeError错误
"use strict";
var obj2 = { get x() { return 17; } };
obj2.x = 5;
//给不可扩展对象的新属性赋值,抛出TypeError错误
"use strict";
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai";
//在严格模式下,试图删除不可删除的属性时会抛出异常(之前这种操作不会产生任何效果)
"use strict";
delete Object.prototype;
// 严格模式要求函数的参数名唯一。
//在正常模式下,最后一个重名参数名会掩盖之前的重名参数,
//之前的参数仍然可以通过arguments[i]来访问, 还不是完全无法访问。
//然而,这种隐藏毫无意义而且可能是意料之外的(比如它可能本来是打错了),
//所以在严格模式下重名参数被认为是语法错误
"use strict";
function sum(a, a, c) {// !!! 语法错误
"use strict";
return a + a + c; // 代码运行到这里会出错
}
//严格模式下八进制语法会引起语法错误
"use strict";
var sum = 015 + // !!! 语法错误
197 +
142;
//ECMAScript 6中的严格模式禁止设置primitive值的属性。
//不采用严格模式,设置属性将会简单忽略(no-op);采用严格模式,将抛出TypeError错误
(function() {
"use strict";
false.true = ""; //TypeError
(14).sailing = "home"; //TypeError
"with".you = "far away"; //TypeError
})();
//第一, 严格模式禁用 with
//with所引起的问题是块内的任何名称可以映射(map)到with传进来的对象的属性,
//也可以映射到包围这个块的作用域内的变量(甚至是全局变量),
//这一切都是在运行时决定的: 在代码运行之前是无法得知的.
//严格模式下, 使用 with 会引起语法错误,
//所以就不会存在 with 块内的变量在运行时才决定引用到哪里的情况了:
"use strict";
var x = 17;
with (obj) { // !!! 语法错误
// 如果没有开启严格模式,with中的这个x会指向with上面的那个x,还是obj.x?
// 如果不运行代码,我们无法知道,因此,这种代码让引擎无法进行优化,速度也就会变慢。
x;
}
//第二, 严格模式下的 eval 不再为上层范围(surrounding scope,注:包围eval代码块的范围)引入新变量
var x = 17;
var evalX = eval("'use strict'; var x = 42; x");
console.assert(x === 17);
console.assert(evalX === 42);
//第三, 严格模式禁止删除声明变量。delete name 在严格模式下会引起语法错误:
"use strict";
var x;
delete x; // !!! 语法错误
eval("var y; delete y;"); // !!! 语法错误
语句:ECMAScript 中的语句以一个分号结尾;如果省略分号,则由解析器确定语句的结尾;可以使用C 风格的语法把多条语句组合到一个代码块中,即代码块以左花括号 { 开头,以右花括号 } 结尾。
var sum = a + b // 即使没有分号也是有效的语句,不推荐
var diff = a - b; // 有效的语句—,推荐
//虽然语句结尾的分号不是必需的,但我们建议任何时候都不要省略它。
//因为加上这个分号可以避免很多错误(例如不完整的输入),
//开发者可以放心地通过删除多余的空格来压缩ECMAScript代码(代码行结尾处没有分号会导致压缩错误)。
//另外,加上分号也会在某些情况下增进代码的性能,这样解析器就不必再花时间推测应该在哪里插入分号了。
if (test){
test = false;
alert(test);
}
//虽然条件控制语句(如if 语句)只在执行多条语句的情况下才要求使用代码块,
//但最佳实践是始终在控制语句中使用代码块——即使代码块中只有一条语句,例如:
if (test) // 有效但容易出错,不要使用
alert(test);
if (test){ // 推荐使用
alert(test);
}
//在控制语句中使用代码块可以让编码意图更加清晰,而且也能降低修改代码时出错的几率。
2.关键字和保留字
ECMA-262 描述了一组具有特定用途的关键字,这些关键字可用于表示控制语句的开始或结束,或者用于执行特定操作等。按照规则,关键字也是语言保留的,不能用作标识符。
break | do | instanceof | typeof | case | else | new | var |
catch | finally | return | void | continue | for | switch | while |
debugger* | function | this | with | default | if | throw | delete |
in | try |
ECMA-262 还描述了另外一组不能用作标识符的保留字。尽管保留字在这门语言中还没有任何特定的用途,但它们有可能在将来被用作关键字。
abstract | enum | int | short | boolean | export | interface | static |
byte | extends | long | super | char | final | native | synchronized |
class | float | package | throws | const | goto | private | transient |
debugger | implements | protected | volatile | double | import | public |
第5 版把在非严格模式下运行时的保留字缩减为下列这些
class | enum | extends | super | const | export | import |
在严格模式下,第5 版还对以下保留字施加了限制:
implements | package | public | interface | private | static | let | protected |
yield |
3.变量:ECMAScript 的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。定义变量时要使用var 操作符(注意var 是一个关键字),后跟变量名(即一个标识符)
var message;
//这行代码定义了一个名为message 的变量,该变量可以用来保存任何值
//像这样未经过初始化的变量,会保存一个特殊的值——undefined
var message = "hi";
//ECMAScript 也支持直接初始化变量,因此在定义变量的同时就可以设置变量的值
var message = "hi";
message = 100;
//可以在修改变量值的同时修改值的类型。有效,但不推荐
function test(){
var message = "hi";//局部变量
}
test();
alert(message);//错误!
//即用var 操作符定义的变量将成为定义该变量的作用域中的局部变量。
//如果在函数中使用var 定义一个变量,那么这个变量在函数退出后就会被销
function test(){
message = "hi"; // 全局变量
}
test();
alert(message); // "hi"
//这个例子省略了var 操作符,因而message 就成了全局变量。
//这样,只要调用过一次test()函数,这个变量就有了定义,就可以在函数外部的任何地方被访问到。
//虽然省略var 操作符可以定义全局变量,但这不是推荐的做法。
//因为在局部作用域中定义的全局变量很难维护。
//而且如果有意地忽略了var 操作符,也会由于相应变量不会马上就有定义而导致不必要的混乱。
//给未经声明的变量赋值在严格模式下会导致抛出ReferenceError 错误。
var message = "hi",
found = false,
age = 29;
//可以使用一条语句定义多个变量,只要把每个变量(初始化或不初始化均可)用逗号分隔开即可。
//在严格模式下,不能定义名为eval 或arguments 的变量,否则会导致语法错误。