js语法和数据类型

基础知识(Basics)

JavaScript 的很多语法借鉴自 Java,但也受 Awk,Perl 和 Python 影响。 

JavaScript 是大小写敏感的,使用 Unicode 字符集。

在JavaScript中,语句被称为 statements,并用分号分隔(;)。空格、制表符和换行符被称为空白。 
JavaScript的脚本的源文本从左到右扫描,并转换成由令牌,控制字符,行结束符,注释或空白组成的输入元素序列。 
ECMAScript中还定义了某些关键字和字面值,并具有分号自动插入功能(ASI)来结束语句。但是,建议随时添加分号结束你的语句以避免副作用。
欲了解更多信息,请参阅有关JavaScript的词法语法详细参考。

注释(Comments)

注释语法跟 C++ 和许多其他语言相同:

// 单行注释
 
/* 这是一个多行注释 
   多行注释
 */
 
/* 你不能, 但是, /* 嵌套注释 */ 语法错误 */

声明(Declarations)

JavaScript有三种声明。

var
声明变量,可选初始化值。
let
声明块范围局部变量,可选初始化值。
const

声明一个只读命名常量。

变量

在应用程序中,使用变量来来为值命名。变量的名称称为 identifiers,需要遵守一定的规则。

在JavaScript语言中,一个标识符必须以字母、下划线(_)或者美元($)符号开头;后续的字符可以包含数字(0-9)。因为JavaScript语言是区分大小写的,这里所指的字母可以是(大写的)“A”到字母“Z”和(小写的)“a”到“z”。

从JavaScript 1.5版开始,你可以使用 ISO 8859-1 或 Unicode 编码的字符作标识符,例如å和ü。你也可以使用\uXXXX字样的转义序列 Unicode escape sequences作标识符。

合法的标识符示例:Number_hits,temp99 和 _name

声明变量

你可以用以下两种方式声明变量:

  • 使用关键词 var。例如,var x = 42。这个语法可以同时用来声明局部和全局变量。
  • 直接赋值。例如,x = 42。这样就声明了一个全局变量并会导致JavaScript编译时产生一个严格警告。因而你应避免使用这种非常规格式。

对变量求值

用 var 或 let 声明的未赋初值的变量,值会被设定为undefined(译注:即未定义值,本身也是一个值)

试图访问一个未初始化的变量会导致一个 ReferenceError 异常被抛出:

var a;
console.log("The value of a is " + a); // logs "The value of a is undefined"
console.log("The value of b is " + b); // throws ReferenceError exception

你可以使用undefined来确定变量是否已赋值。以下的代码中,变量input未被赋值,因而if条件语句的求值结果是true

var input;
if(input === undefined){
  doThis();
} else {
  doThat();
}

 

undefined值在布尔类型环境中会被当作false。例如,下面的代码将运行函数myFunction,因为数组myArray中的元素未被赋值:

var myArray = new Array();
if (!myArray[0]) myFunction();

数值类型环境中undefined值会被转换为NaN(译注:NaN为“Not a Number”,不是一个数字,的缩写)。

var a;
a + 2 = NaN

当你对一个空变量求值时,空值null在数值类型环境中会被当作0来对待,而布尔类型环境中会被当作false
。例如:

var n = null;
console.log(n * 32); // logs 0

变量的域

在所有函数之外声明的变量,叫做全局变量,因为它可被当前文档中的其他代码所访问。在函数内部声明的变量,叫做局部变量,因为它只能在该函数内部访问。

ECMAScript 6 之前的JavaScript没有 语句块 作用域;相反,语句块中声明的变量将成为语句块所在代码段的局部变量。例如,如下的代码将在控制台输出 5,因为 x 的作用域是声明了 x 的那个函数(或全局范围),而不是 if 语句块。

if (true) {
  var x = 5;
}
console.log(x); // 5

如果使用 ECMAScript 6 中的 let 声明,上述行为将发生变化。

if (true) {
  let y = 5;
}
console.log(y); // ReferenceError: y is not defined

变量声明提升

JavaScript 变量的另一特别之处在于,你可以引用稍后声明的变量,而不会引发异常。这一概念称为变量声明提升(hoisting);JavaScript 变量感觉上是被“举起”或提升到了所有函数和语句之前。然而提升后的变量将返回 undefined 值,所以即使在使用或引用某个变量之后存在声明和初始化操作,仍将得到 undefined 值。

/**
 * Example 1
 */
console.log(x === undefined); // logs "true"
var x = 3;


/**
 * Example 2
 */
// will return a value of undefined
var myvar = "my value";

(function() {
  console.log(myvar); // undefined
  var myvar = "local value";
})();

上面的例子,也可写作:

/**
 * Example 1
 */
var x;
console.log(x === undefined); // logs "true"
x = 3;
 
/**
 * Example 2
 */
var myvar = "my value";
 
(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = "local value";
})();

由于存在变量声明提升,一个函数中所有的var语句应尽可能地放在接近函数顶部的地方。这大大地提升了程序代码的清晰度。

全局变量

全局变量实际上是全局对象的属性。在网页中,(译注:缺省的)全局对象是 window,所以你可以用形如 window.variable的语法来设置和访问全局变量。

因此,你可以通过指定 window 或 frame 的名字,从一个 window 或 frame 访问另一个 window 或 frame 中声明的变量。例如,设想一个叫 phoneNumber 的变量在文档里被声明,你可以在子框架里用 parent.phoneNumber 来引用 它。

常量

你可以用关键字 const 创建一个只读的常量。常量标识符的命名规则和变量的相同:必须以字母、下划线或美元符号开头并可以包含有字母、数字或下划线。

const prefix = '212';

常量不可以通过赋值改变其值,也不可以在脚本运行时重新声明。它必须被初始化为某个值。

常量的作用域规则与 let 块级作用域变量相同。若const关键字被省略了,该标识符将被视为变量。

在同一作用域中,不能用与变量或函数同样的名字来命名常量。例如:

// THIS WILL CAUSE AN ERROR
function f() {};
const f = 5;

// THIS WILL CAUSE AN ERROR ALSO
function f() {
  const g = 5;
  var g;

  //statements
}

数据结构和类型

JavaScript语言可以识别下面 7 种不同类型的值:

  • 六种是 原型 的数据类型:
    • Boolean.  布尔值,true 和 false.
    • null. 一个表明 null 值的特殊关键字。 JavaScript 是大小写敏感的,因此 null NullNULL或其他变量完全不同。
    • undefined.  变量未定义时的属性。
    • Number.  表示数字,例如: 42 或者 3.14159。
    • String.  表示字符串,例如:"Howdy"
    • Symbol ( 在 ECMAScript 6 中新添加的类型).。一种数据类型,它的实例是唯一且不可改变的。
  • 以及 Object 对象

仅凭这些为数不多的数据类型,你的应用程序就能够执行有用的功能。

Objects 和 functions 是本语言的其他两个基本要素。你可以将对象视为存放值的命名容器,而将函数视为你的应用程序能够执行的过程(procedures)。

数据类型的转换

JavaScript是一种支持动态数据类型的语言。这意味着你定义变量时不必指定数据类型,而数据类型会在脚本执行需要时自动转换。那么,你可以这样来定义变量:

var answer = 42;

然后,你还可以给同一个变量分配一个字符串值,例如:

answer = "Thanks for all the fish...";

因为 JavaScript 是动态类型的,这样的分配并不会提示出错。

在包含加法运算符的数字和字符串表达式中,JavaScript 会把数字值转换为字符串。例如,假设有如下的语句:

x = "The answer is " + 42 // "The answer is 42"
y = 42 + " is the answer" // "42 is the answer"

在包含其它运算符(译注:如下面的“-”)时,JavaScript语言不会把数字变为字符。例如(译注:第一例是数学运算,第二例仍是字符串运算):

"37" - 7 // 30
"37" + 7 // "377"

字符串转换为数字

有一些方法可以将内存中表示一个数字的字符串转换为对应的数字

parseInt()parseFloat()

参见:parseInt()parseFloat()的相关页面。

parseInt 仅能够返回全部的数字,所以使用它会丢失小数部分。另外,调用 parseInt 时最好总是带上进制(radix) 参数,这个参数用于指定使用哪一种数制。

单目加法运算符

将字符串转换为数字的另一种方法是使用单目加法运算符。

"1.1" + "1.1" = "1.11.1"
(+"1.1") + (+"1.1") = 2.2   // Note: the parentheses are added for clarity, not required.

 

字面值(literals)

(译注:字面值是由语法表达式定义的常量;或,通过由一定字辞组成的语词表达式定义的常量)

在JavaScript中,你可以使用各种字面值。这些字面值是脚本中按字面意思给出的固定的值,而不是变量。(译注:字面值是常量,其值是固定的,而且在程序脚本运行中不可更改,比如false,3.1415,thisIsStringOfHelloworld ,invokedFunction: myFunction("myArgument")。本节将介绍以下类型的字面值:

数组字面值

数组字面值是一个封闭在方括号对([])中的包含有零个或多个表达式的列表,其中每个表达式代表数组的一个元素。当你使用数组字面值创建一个数组时,该数组将会以指定的值作为它的元素进行初始化,而其长度被设定为元素的个数。

下面的示例用3个元素生成数组coffees,它的长度是3。

var coffees = ["French Roast", "Colombian", "Kona"];

注意 这里的数组字面值也是一种对象初始化器。参考对象初始化器的使用

若在顶层(全局)脚本里用字面值创建数组,JavaScript语言会在每次对包含该数组字面值的表达式求值时解释该数组。另一方面,在函数中使用的数组,将在每次调用函数时被创建一次。

数组字面值同时也是数组对象。有关数组对象的详情请参见数组对象一文。

数组字面值中的多余逗号

(译注:声明时)你不必列举数组字面值中的所有元素。若你在同一行中连写两个逗号(,),数组中就会产生一个没被指定的元素,其初始值是undefined。以下示例创建了一个名为fish的数组:

var fish = ["Lion", , "Angel"];

这个数组中,有两个已被赋值的元素,和一个空元素(fish[0]是"Lion",fish[1]是undefined,而fish[2]是"Angel";译注:此时数组的长度属性fish.length是3)。

若你在元素列表的尾部添加了一个逗号(,),它会被忽略。在下面的例子中,该数组的长度是3。并不存在myList[3]这个元素(译注:这是指数组的第4个元素噢,作者是在帮大家复习数组元素的排序命名方法)。元素列表中所有其它的逗号都表示一个新元素(的开始)。(注意:尾部的逗号在早期版本的浏览器中会产生错误,因而编程时的最佳实践就是移除它们。译注:而“现代”的浏览器似乎鼓励这种方式,因为好多网页中都这么写

var myList = ['home', , 'school', ];

在下面的例子中,数组的长度是4,元素myList[0]myList[2]缺失(译注:没被赋值,因而是undefined)。

var myList = [ , 'home', , 'school'];

又一个例子,在这里该数组的长度是4,元素myList[1]myList[3]被漏掉了。(但是)只有最后的那个逗号被忽略。

var myList = ['home', , 'school', , ];

理解多余的逗号(在脚本运行时会被如何处理)的含义,对于从语言层面理解JavaScript是十分重要的。但是,你自己写代码时:显式地将缺失的元素声明为undefined,将大大增加你的代码的清晰度和可维护性。(译注:此段话的重要性甚至超过整篇文章。译者:还有为啥不举例说明呢?)

布尔字面值

(译注:即逻辑字面值)

布尔类型有两种字面值:truefalse

不要混淆(才怪!)作为布尔对象的真和假与布尔类型的原始值true和false。(译者:难懂,这分明让人抓狂嘛,为啥不立刻举例说明呢?)布尔对象是原始布尔数据类型的一个包装器。参见 布尔对象

整数

(译注:原文如此,没写成“整数字面值”)

整数可以被表示成十进制(基数为10)、十六进制(基数为16)以及八进制(基数为8)。

  • 十进制整数字组成的数字序列,不带前导0(零)。
  • 带前导0(零)的整数字面值表明它是八进制。八进制整数只能包括数字0-7。
  • 前缀0x或0X表示十六进制。十六进制整数,可以包含数字(0-9)和字母a~f或A~F。

八进制整数字面值在ECMA-262,第3版标准(严格模式下 中被弃用并移除。不过JavaScript 1.5为了后向兼容仍然保留了支持。

整数字面值例子如下:

0, 117 and -345 (decimal, base 10)
015, 0001 and -077 (octal, base 8) 
0x1123, 0x00111 and -0xF1A7 (hexadecimal, "hex" or base 16)

浮点数字面值

浮点数字面值可以有以下的组成部分:

  • 一个十进制整数,它可以带符号(即前面的“+”或“ - ”号),
  • 一个小数点(“.”),
  • 一个小数部分(由一串十进制数表示),
  • 一个指数部分。

指数部分是以“e”或“E”开头后面跟着一个整数,可以有正负号(即前面写“+”或“-”)。一个浮点数字面值必须至少有一位数字,后接小数点或者“e”(大写“E”也可)组成。

一些浮点数字面值的例子,如3.1415,-3.1E13,.1e12以及2E-12。

简言之,其语法是:

[digits][.digits][(E|e)[(+|-)]digits]

例如:

3.14
2345.789
.3333333333333333333

对象字面值

对象字面值是封闭在花括号对({})中的一个对象的零个或多个"属性名-值"对的(元素)列表。你不能在一条语句的开头就使用对象字面值,这将导致 错误或非你所预想的行为,因为此时左花括号({)会被认为是一个语句块的起始符号。(译者:这 里需要对语句statement、块block等基本名词的解释)

以下是一个对象字面值的例子。对象car的第一个元素(译注:即一个属性双值对)定义了属性myCar;第二个元素,属性getCar,引用了一个函数(即CarTypes("Honda"));第三个元素,属性special,使用了一个已有的变量(即Sales)。

var Sales = "Toyota";

function CarTypes(name) {
  return (name == "Honda") ?
    name :
    "Sorry, we don't sell " + name + "." ;
}

var car = { myCar: "Saturn", getCar: CarTypes("Honda"), special: Sales };

console.log(car.myCar);   // Saturn
console.log(car.getCar);  // Honda
console.log(car.special); // Toyota

更进一步的,你可以使用数字或字符串字面值作为属性的名字,或者在另一个字面值内嵌套上一个字面值。如下的示例中使用了这些可选项。

var car = { manyCars: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };

console.log(car.manyCars.b); // Jeep
console.log(car[7]); // Mazda

对象属性名字可以是任意字符串,包括空串。如果对象属性名字不是合法的javascript标识符,它必须用""包裹。属性的名字不合法,那么便不能用.访问属性值,而是通过类数组标记访问和赋值。

var unusualPropertyNames = {
  "": "An empty string",
  "!": "Bang!"
}
console.log(unusualPropertyNames."");   // SyntaxError: Unexpected string
console.log(unusualPropertyNames[""]);  // An empty string
console.log(unusualPropertyNames.!);    // SyntaxError: Unexpected token !
console.log(unusualPropertyNames["!"]); // Bang!

这里请注意:

var foo = {a: "alpha", 2: "two"};
console.log(foo.a);    // alpha
console.log(foo[2]);   // two
//console.log(foo.2);  // Error: missing ) after argument list
//console.log(foo[a]); // Error: a is not defined
console.log(foo["a"]); // alpha
console.log(foo["2"]); // two

字符串字面值

字符串字面值可以包含有零个或多个字符,由双引号(")对或单引号(‘)对包围。字符串被限定在同种引号之间;也即,必须是成对单引号或成对双引号。下面的例子都是字符串字面值:

  • "foo"
  • 'bar'
  • "1234"
  • "one line \n another line"
  • "John's cat"

你可以在字符串字面值上使用字符串对象的所有方法——JavaScript会自动将字符串字面值转换为一个临时字符串对象,调用该方法,然后废弃掉那个临时的字符串变量。你也能用对字符串字面值使用类似String.length的属性:

"John's cat".length

除非有特别需要使用字符串对象,你应当始终使用字符串字面值。要查看字符串对象的有关细节,请参见字符串对象

在字符串中使用的特殊字符

作为一般字符的扩展,你可以在字符串中使用特殊字符,如下例所示。

"one line \n another line"

以下表格列举了你能在JavaScript的字符串中使用的特殊字符。

表 2.1 JavaScript 特殊字符
CharacterMeaning
\0 空字节
\b Backspace
\f Form feed
\n New line
\r Carriage return
\t Tab
\v Vertical tab
\' Apostrophe or single quote
\" Double quote
\\ Backslash character (\).
\XXX The character with the Latin-1 encoding specified by up to three octal digits XXX between 0 and 377. For example, \251 is the octal sequence for the copyright symbol.
\xXX The character with the Latin-1 encoding specified by the two hexadecimal digits XX between 00 and FF. For example, \xA9 is the hexadecimal sequence for the copyright symbol.
\uXXXX The Unicode character specified by the four hexadecimal digits XXXX. For example, \u00A9 is the Unicode sequence for the copyright symbol. See Unicode escape sequences.

转义字符

对于那些未出现在表2.1中的字符,其所带的前导反斜线'\'将被忽略。但是,这一用法已被废弃,应当避免使用。

通过在引号前加上反斜线'\',可以在字符串中插入引号,这就是引号转义。例如:

var quote = "He read \"The Cremation of Sam McGee\" by R.W. Service.";
console.log(quote);

代码的运行结果为:

He read "The Cremation of Sam McGee" by R.W. Service.

要在字符串中插入'\'字面值,必须转义反斜线。例如,要把文件路径 c:\temp 赋值给一个字符串,可以采用如下方式:

var home = "c:\\temp";

也可以在换行之前加上反斜线以转义换行(译注:实际上就是一条语句拆成多行书写),这样反斜线和换行都不会出现在字符串的值中。

var str = "this string \
is broken \
across multiple\
lines."
console.log(str);   // this string is broken across multiplelines.

Javascript没有“heredoc”语法,但可以用行末的换行符转义和转义的换行来近似实现 

var poem = 
"Roses are red,\n\
Violets are blue.\n\
I'm schizophrenic,\n\
And so am I."

Unicode编码

Unicode是一种通用字符编码标准,用于世界上主要书面语言的交换和显示。它涵盖美洲,欧洲,中东,非洲,印度,亚洲和环太平洋地区的语言,还包括古文字和技术符号。 Unicode允许多语言文本的交换、处理和显示,以及通用的技术和数学符号的使用。它有望解决多语言计算的国际化问题,如不同国家的文字标准,以解决国际化问题。但目前,并非所有的现代或古老的文字都得到了支持。

Unicode字符集可用于所有已知的编码。 Unicode字符集是在ASCII(美国信息交换标准码)字符集后建立的,它为每个字符设定一个数值和名称。字符编码指定字符的本体(identity)和数值(编码位置),以及这个数值的位(bit)表示。 16位的数字值(编码值)定义为一个带前缀U的十六进制数,例如,U+0041代表A。这个值的唯一名称是大写的拉丁字母A。

注意:1.3 版本之前的JavaScript并不支持Unicode编码。

兼容于ASCII和ISO标准的Unicode编码

Unicode编码完全兼容ISO 10646的子集ISO/IEC 10646-1; 1993。

若干编码标准(包括UTF-8,UTF-16和ISO UCS-2)用于将Unicode表示为实际的二进制位。

Unicode的UTF-8编码与ASCII字符是兼容,并且被许多程序所支持。前128个Unicode字符与ASCII字符一一对应,并具有相同的字节值。从U+0020至U+007E的Unicode字符等价于从0x20到0x7E的ASCII字符。ASCII支持拉丁字母并使用7位字符集,而UTF-8的每个字符占用一到四个8位组(8位组octet,即1个字节或8位),这样可以表示数百万个字符。另一种编码标准,UTF-16,使用两个字节来表示Unicode字符。转义序列允许UTF-16用4个8位组表示Unicode字符, ISO UCS-2(通用字符集)则使用两个字节。

JavaScript和Navigator支持UTF-8/Unicode,这意味着你可以在Javascript程序中使用非拉丁、国际化或本地化的字符,以及特殊的技术符号。Unicode提供了一种标准的方式来编码多语言文本。由于UTF-8的Unicode编码与ASCII兼容,程序可以使用ASCII字符。您可以在Javascript的注释、字符串字面值、标识符和正则表达式中使用非ASCII的Unicode字符。

Unicode转义序列

你可以在字符串字面值、正则表达式和标识符中使用Unicode转义序列。转义序列由6个ASCII字符构成:\u和一个4位十六进制数字。例如,\u00A9表示版权符号。每一个Unicode转义序列在JavaScript中被解释为一个字符

下面的代码返回一个版权符号和字符串“Netscape Communications”。

var x = "\u00A9 Netscape Communications";

下表列出了常用特殊字符的Unicode值。

表 2.2 特殊字符的Unicode值
类别Unicode 值名称格式名称
空白字符 \u0009 Tab <TAB>
\u000B Vertical Tab <VT>
\u000C Form Feed <FF>
\u0020 Space <SP>
换行符 \u000A Line Feed <LF>
\u000D Carriage Return <CR>
其他Unicode转义序列 \u0008 Backspace <BS>
\u0009 Horizontal Tab <HT>
\u0022 Double Quote "
\u0027 Single Quote '
\u005C Backslash \

JavaScript中Unicode转义序列的用法和Java不同。在JavaScript中,转义序列绝不会首先被理解为一个特殊字符。例如,在一个字符串的换行符转义序列不终止字符串,它被解释的功能。Javascript忽略注释中的任何转义序列。在Java中,如果在单行注释中使用转义序列,则它被解释为一个Unicode字符。对于一个字符串字面量,Java编译器首先解释转义序列。例如,如果在JavaScript(译注:此处原文误作Java)中使用一个行结束符转义字符(例如,\u000A),它终止字符串文字。而在Java中这样做将导致一个错误,因为(Unicode)换行符不允许出现在字符串字面值中,必须使用\n换行。在JavaScript中,转义序列的效果和\n一样。

JavaScript文件中的Unicode字符

早期的Gecko默认使用Latin-1字符作为从XUL文件加载的JavaScript代码文件的编码。在Gecko 1.8之后,则根据XUL文件的编码来推断。请参考在XUL JavaScript中使用国际字符一文内的更多信息。

用Unicode编码显示字符

你可以使用Unicode显示不同语言的字符或技术符号。为了正确显示字符,客户端,如Mozilla Firefox或Netscape,必须支持Unicode。此外,客户端必须有可用的合适的Unicode字体,而且客户端平台必须支持Unicode。通常情况下,Unicode字体无法显示所有的Unicode字符。一些平台,如Windows 95,提供了对Unicode的部分支持。

要接收非ASCII字符的输入,客户端需要将输入作为Unicode来发送。使用标准的增强型键盘,客户端无法轻易地输入Unicode支持的附加字符。有时,输入Unicode字符的唯一办法就是使用Unicode转义序列。

From:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Grammar_and_types#Basics

posted @ 2016-02-20 17:26  AutismTune  阅读(670)  评论(0编辑  收藏  举报