面向 SAP ABAP 开发者的 JavaScript 基础知识(三)
九、对象
在 JavaScript 中,对象是一个无序的属性列表。属性由名称和值组成,也可以是函数。在这种情况下,该函数称为方法。本章涵盖了用 JavaScript 编码时需要熟悉的一些标准对象。它还提供了它们的属性和最可能使用它们的方法的例子。本章还介绍了数组、布尔对象、字符串对象和日期对象。
重新访问的对象
清单 9-1 给出了一个对象的简单例子。
清单 9-1。对象示例
<html>
<body>
<script>
var book = {novel: "Secret", author: "Rhonda Byrne", publicationDate: "Nov 2006"};
console.log(book.novel + " this book is of author " + book.author);
</script>
</body>
</html>
如本例所示,一个对象包含一个项目列表,列表中的每个项目都有一个名称-值对。这些属性的名称是 novel、author 和 publicationDate,每个属性都被赋予一个值。该代码的输出如图 9-1 所示。
图 9-1。输出
排列
正如您在本书前面看到的,数组对象允许您在一个变量名下存储多个值。索引号从 0 开始,数组的第一个元素表示为[0],第二个表示为[1],依此类推。
数组创建的语法是
var arrayName = [value1, value2, .... Valuen]
考虑清单 9-2 中数组文字的简单例子。
清单 9-2。数组文字示例
<html>
<body>
<script>
var countries = ["India", "Germany", "Scotland"];
console.log(countries);
</script>
</body>
</html>
此示例将变量 countries 声明为一个数组,它包含元素 India、Germany 和 Scotland。接下来,使用 console.log 方法打印 countries 数组。正如您所看到的,这个例子没有指定任何要打印的索引或元素。这段代码给出了一个数组的最大长度。
清单 9-2 的输出如图 9-2 所示。
图 9-2。输出
如果在 console.log 语句中没有指定数组的元素索引,则显示元素的总数,而不是每个元素的内容。
现在考虑清单 9-3 中带有索引的数组的相关示例。
清单 9-3。带索引的数组示例
<html>
<body>
<script>
var countries = ["India", "Germany", "Scotland"];
console.log(countries[0], countries[1], countries[2]);
</script>
</body>
</html>
使用与清单 9-2 中相同的起始基本代码,这个例子展示了如何通过指定数组索引号来访问数组的各个元素。该代码的输出如图 9-3 所示。
图 9-3。输出
数组也可以使用新的关键字来定义,如清单 9-4 中的例子所示。
清单 9-4。带有索引示例的新数组
<html>
<body>
<script>
var countries = new Array( "India", "Germany", "Scotland" );
console.log(countries[0], countries[1], countries[2]);
</script>
</body>
</html>
这采用了相同的初始示例,并添加了关键字 new。两个例子的工作方式完全相同;唯一的区别是清单 9-4 创建了一个新数组。该代码的输出如图 9-4 所示。
图 9-4。输出
注意
如果可能的话,创建没有新关键字的数组,这样会更快。
数组对象的属性
表 9-1 列出并描述了数组对象的三个最常用属性。
表 9-1。数组对象的属性
|财产
|
描述
| | --- | --- | | 构造器 | 返回数组函数 | | 指数 | 返回字符串中匹配项的从零开始的索引 | | 长度 | 给出数组的长度 |
接下来将更详细地描述构造函数和长度属性。
属性构造函数
构造函数属性的语法是
array.constructor
这将返回函数 Array(){[本机代码] }。清单 9-5 中显示了一个简单的例子。
清单 9-5。数组构造函数属性示例
<html>
<body>
<script>
var countries = new Array( "Germany", "India", "Scotland" );
console.log("countries.constructor is:" + countries.constructor);
</script>
</body>
</html>
此示例使用 new 关键字声明数组 countries,然后使用 console.log 显示 countries.constructor。此代码的输出如图 9-5 所示。
图 9-5。输出
属性长度
顾名思义,length 属性包含数组的长度。元素的数量以整数形式指定。长度属性的语法是
array.length
这将返回数组长度,即元素的总数。清单 9-6 提供了这个属性的一个工作实例。
清单 9-6。数组长度属性示例
<html>
<body>
<script>
var countries = new Array( "Germany", "India", "Scotland", "Austria" );
console.log("Length of array is:" + countries.length);
</script>
</body>
</html>
清单 9-6 的输出如图 9-6 所示。
图 9-6。输出
数组方法
数组对象包含许多方法,表 9-2 中列出并描述了其中一些方法。
表 9-2。数组对象的方法
|方法
|
描述
| | --- | --- | | concat() | 合并两个或多个数组并返回新数组。 | | forEach() | 对数组中的每个元素执行指定的函数。 | | 加入() | 将数组的元素组合成一个字符串。 | | lastIndexOf() | 返回在数组中找到给定元素的最后一个索引。如果元素不在数组中,则返回-1。 | | 流行() | 移除并返回数组的最后一个元素。 | | 推送() | 将一个或多个元素添加到数组末尾,并返回新的数组长度。 | | 反向() | 反转数组的顺序。 | | toString() | 以字符串形式返回数组的组成部分。 | | 排序() | 对数组元素进行排序。 | | shift() | 移除第一个元素并返回更新后的数组。 | | 切片() | 按照位置的指定剪切数组的一部分,并以字符串的形式返回数组。 |
下面是对 concat 和 pop 方法的更详细的描述。
方法串联
concat()方法的语法是
array.concat(arr1, arr2, ..., arrN);
这里,arr1 和 arr2 是数组的元素。这将返回另一个包含串联值的数组。清单 9-7 展示了一个使用这种方法的例子。
清单 9-7。Array concat()方法示例
<html>
<body>
<script>
var countries = ["Germany", "Scotland", "Austria"];
var continents = ["Europe", "Australia", "Africa"];
var world = countries.concat(continents);
console.log(" The world map has countries & continents:" + world);
</script>
</body>
</html>
此示例声明了两个数组,一个包含可变的国家,另一个包含可变的洲。然后使用 concat()方法组合这两个数组元素,形成一个新数组。
清单 9-7 的输出如图 9-7 所示。
图 9-7。输出
方法弹出
pop 方法从数组中移除最后一个元素并返回它的值。pop()方法的语法是
array.pop();
这将返回从数组中移除的元素或值。清单 9-8 提供了 pop()方法的一个例子。
清单 9-8。数组 pop()方法示例
<html>
<body>
<script>
var countries = ["Germany", "Scotland", "Austria"];
var value = countries.pop();
console.log(" Removed value from array is:" + value);
var value = countries.pop();
console.log(" Removed value from array is:" + value);
</script>
</body>
</html>
这个例子用一些数组元素声明变量 countries,然后使用 pop()方法。该值存储在变量值中,然后显示出来。该代码的输出如图 9-8 所示。
图 9-8。输出
布尔代数学体系的
布尔对象代表两个值:真或假。布尔值的语法是
Boolean (value)
清单 9-9 显示了布尔对象的一个例子。
清单 9-9。布尔对象示例
<html>
<body>
<script>
function myBoolean() {
console.log(10 < 15);
}
myBoolean();
</script>
</body>
</html>
此示例比较布尔值。如果 10 小于 15,代码返回 true 如果不是,则返回 false。清单 9-9 的输出如图 9-9 所示。
图 9-9。输出
布尔属性
布尔对象的属性在表 9-3 中列出并描述。
表 9-3。布尔属性
|财产
|
描述
| | --- | --- | | 构造器 | 对象的构造函数 | | 原型 | 允许开发人员添加属性和方法 |
布尔方法
现在让我们讨论布尔对象的一些有用的方法。
方法值
valueOf()方法的语法是
boolean.valueOf()
这将返回指定布尔对象的原始值。清单 9-10 显示了一个这样的例子。
清单 9-10。布尔值 Of()方法示例
<html>
<body>
<script>
var value = Boolean(10 < 15);
var num = value.valueOf();
console.log( "Value of Boolean is:" + num.valueOf() );
</script>
</body>
</html>
此示例分配变量值,然后使用 valueOf()方法检查布尔表达式是真还是假。输出如图 9-10 所示。
图 9-10。输出
线
在 string 对象中,可以存储一系列字符,如下例所示:
var textString = "JavaScript language" or 'JavaScript language'
如图所示,您可以用单引号或双引号来编写这个系列。
弹簧属性
表 9-4 列出并描述了字符串对象的一些属性。
表 9-4。String 对象的属性
|财产
|
描述
| | --- | --- | | 长度 | 字符串的长度 | | 构造器 | 返回对字符串函数的引用 | | 原型 | 允许开发人员向对象添加属性和方法 |
下面是对长度属性的更详细的描述。
属性长度
属性长度的语法是
string.length
这给出了字符串中的字符数,包括空格和空白。考虑清单 9-11 中的简单例子。
清单 9-11。字符串长度属性示例
<html>
<body>
<script>
var text = "JavaScript Object";
var strLength = text.length;
console.log( "The string length is:" + strLength );
</script>
</body>
</html>
这个例子显示了字符串的长度。它声明了变量 text 并给它分配了一个字符串。然后,使用属性 length 确定给定字符串中的字符数。该代码的输出如图 9-11 所示。
图 9-11。输出
字符串方法
表 9-5 中列出并描述了字符串方法。
表 9-5。字符串方法
|方法
|
描述
| | --- | --- | | concat() | 组合两个或多个字符串。 | | 索引() | 在字符串中搜索给定文本和主字符串中的起始位置。如果搜索不成功,它返回-1。 | | 匹配() | 根据正则表达式匹配字符串时,返回“匹配字符串”。 | | 替换() | 检查正则表达式后,用新字符串替换一个字符串。 | | 夏拉特() | 返回给定位置的字符。 | | 切片() | 基于指定的开始和结束位置移除字符并提取字符串的一部分(不包括结束字符)。 | | 拆分() | 根据给定的分隔符(如“,”)将字符串分成多个子字符串,并以数组形式返回它们。 | | 搜索() | 在字符串中搜索值或正则表达式。如果找到,则返回匹配的位置。 | | toUpperCase() | 转换为大写。 | | toLowerCase() | 转换为小写。 | | substr() | 也用于提取。但是,起始位置和要提取的字符数是指定的。 | | 包括() | 检查字符串是否包含某个字符或一组字符。 | | endsWith() | 检查字符串是否以某个字符或一组字符结尾。 |
下面将更详细地描述 chartAt、repeat 和 slice 方法。
方法特征
方法 charAt()的语法是
String.charAt(ind)
这将返回给定位置的字符。考虑清单 9-12 中的 chartAt()例子。
清单 9-12。String charAt()方法示例
<html>
<body>
<script>
var text = "JavaScript Object";
var char = text.charAt(2);
console.log( "The character at position 2 is:" + char );
</script>
</body>
</html>
我们现在使用同一个例子来展示 charAt()方法,它标识给定索引号处的字符。(注意数组的基数是 0,所以如果你把 2 作为索引,你会得到第三个字符。)
列表 9-12 的输出如图 9-12 所示。
图 9-12。输出
方法重复
方法 repeat 的语法是
String.repeat(n)
这里,字符串内容重复的次数是通过数字 n 指定的。这将返回包含重复文本的字符串。为了更好地理解这是如何工作的,考虑清单 9-13 中的例子。
清单 9-13。字符串重复()方法示例
<html>
<body>
<script>
var text = "JavaScript Object";
var string = text.repeat(2);
console.log( "The string repeats twice:" + string );
</script>
</body>
</html>
在这种情况下,声明的字符串“JavaScript Object”通过方法 repeat()写了两次。该代码的输出如图 9-13 所示。
图 9-13。输出
方法切片
方法切片的语法是
string.slice( startslice [, endSlice] );
这里,startslice 是在移除之前要提取的部分的起始位置编号,endslice 是可选的,用于从右侧移除字符串的一部分。索引(位置)是从字符串的右侧指定的(即从字符串的末尾向左计数)。之后的所有内容都被删除,不作为返回字符串的一部分发送。这个数字作为负号传递。所以,-4 表示最后四个字符。
考虑清单 9-14 中切片方法的例子。
清单 9-14。String slice()方法示例
<html>
<body>
<script>
var text = "JavaScript is also Object oriented";
var string = text.slice(4, -4);
console.log( "The new string is:" + string );
</script>
</body>
</html>
此示例声明变量 text,并为其分配字符串。起始和结束索引号在 slice 方法中指定,代码将从字符串中提取它们之间的字符。输出如图 9-14 所示。
图 9-14。输出
日期
日期对象帮助我们处理日期和时间。有四种方法可以创建该对象:
new Date( )
new Date(milliseconds)
new Date(datestring)
new Date(year,month,date[,hour,minute,second,millisecond ])
日期属性
表 9-6 中列出并描述了日期属性。
表 9-6。日期属性
|财产
|
描述
| | --- | --- | | 构造器 | 构造器 | | 原型 | 允许开发人员添加属性和方法 |
属性构造函数
constructor 属性返回创建 date 对象原型的函数。构造函数的语法是
date.constructor
考虑清单 9-15 中的构造函数属性的例子。
清单 9-15。日期构造函数属性示例
<html>
<body>
<script>
var tdyDate = new Date();
console.log(tdyDate.constructor);
</script>
</body>
</html>
这个例子用一个新的日期声明了变量 tdyDate。构造函数属性返回函数日期。输出如图 9-15 所示。
图 9-15。代码输出
日期方法
表 9-7 中列出并描述了日期对象的一些常用方法。
表 9-7。日期对象的方法
|方法
|
描述
| | --- | --- | | getDate() | 给出日期中的某一天(例如 1,2,3,… 31) | | getDay() | 以数字的形式给出星期几(例如,从 0,1,2,… 6) | | getFullYear() | 返回日期中的年份(如 1978 年) | | getHours() | 给出日期的小时(例如,0,1,… 23) | | getMinutes() | 返回日期的分钟数(例如,0,1,2,… 59) | | getMonth() | 给出日期对象的月份(例如,0,1,2,11) | | getSeconds() | 返回秒数(例如,0,1,2,3,… 59) |
对于表 9-7 中除 getDay()之外的所有方法,都有对应的 set 方法,如 setDate、setFullYear 等。
现在让我们看几个例子。
通过 getDay()方法使用属性原型
如前所述,prototype 属性允许您向对象添加属性和方法,无论它是布尔值、字符串、日期还是其他。使用 prototype 属性的语法是
Object.prototype.name = value
清单 9-16 展示了如何向日期对象添加一个新方法。
清单 9-16。日期原型属性示例
<html>
<body>
<script>
function myDay() {
var tdyDay = new Date();
tdyDay.today();
console.log(tdyDay.Day);
}
Date.prototype.today = function() {
switch (this.getDay()) {
case 0:
this.Day = "Sunday";
break;
case 1:
this.Day = "Monday";
break;
case 2:
this.Day = "Tuesday";
break;
case 3:
this.Day = "Wednesday";
break;
case 4:
this.Day = "Thursday";
break;
case 5:
this.Day = "Friday";
break;
case 6:
this.Day = "Saturday";
break;
}
};
myDay();
</script>
</body>
</html>
本示例向 date 对象添加一个新函数 today。在这个函数中,首先 getDay 函数使用。基于此,将显示一天的名称,例如 0 表示星期一,1 表示星期二,依此类推。在函数 myDay 中,定义了一个新的日期,并调用了 today 方法。
列表 9-16 的输出如图 9-16 所示。
图 9-16。输出
方法 setMonth
setMonth()方法的语法是
Date.setMonth(monthValue[, dayValue])
这里,monthValue 表示从 1 月到 12 月的月份,但是为它传递的整数值必须是从 0 到 11,其中 0 表示 1 月,以此类推。dayValue 参数是可选的,表示一个月中的日期,例如 1,2,3 … 31。
清单 9-17 展示了如何在程序中使用这个方法。
清单 9-17。Date setMonth()方法示例
<html>
<body>
<script>
var d1 = new Date( "March 23, 2017 11:35:00" );
d1.setMonth( 1 );
console.log( "The date is set to: " + d1 );
</script>
</body>
</html>
此示例声明日期 d1,并使用 new 关键字为其赋值。然后它调用方法 setMonth()并传递值 1。这表示日期的新月份值。本示例将二月的新值设置为 1。
该代码的输出如图 9-17 所示。
图 9-17。程序输出
摘要
本章介绍了使用 JavaScript 时会遇到的几个基本对象,包括数组、布尔值、字符串和日期。它描述了一些与它们相关的属性和方法,并向您展示了如何使用它们来编写 JS 代码。
在第十章,你将探索 JSON 格式。
十、JavaScript 对象符号(JSON)
本章介绍了使用 JavaScript 对象符号的各种方法。它从 JSON 的概述开始,然后深入到 JSON 中使用的数据类型的细节。然后您将看到 JSON 数组和对象如何在 JS 程序中工作。最后,您将看到 JSON 对象的两个有用的方法,parse 和 stringify。
JSON:概述
JSON 是一种数据表示形式,允许您以有组织的方式安排可互换的信息。JSON 是文本形式的(人类可读的),驻留在一个文件中。与 json 文件相关联的常用文件扩展名是. JSON。
注意
除了 JavaScript,JSON 还可以用于 Java、Python、Perl 等。JSON 可以用来在浏览器和服务器之间交换数据。
JSON 的语法是 JavaScript 语法的一个子集,由具有名称和值对的数据组成。
对象包含在大括号{}中,用逗号分隔,而对象和每个名称后跟冒号(:)。数组包含在方括号[]中,值用逗号分隔。
var Employee = { "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" }
var Company = { "Employee": [
{ "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" },
{ "name":"John", "empid":4536, "position":"Associate", "city":"Denver" }
] }
考虑清单 10-1 中的例子。
清单 10-1。JSON 示例
<html>
<body>
<script>
var empObj;
empObj = { "name":"Kelvin Desouza", "empId":17924, "designation":"Trainer", "city":"London" };
console.log(empObj.name + " " + empObj.empId);
</script>
</body>
</html>
在这段代码中,您可以看到使用类似 JSON 的语法用 JavaScript 创建一个对象。该示例声明名为 empObj 的变量,为其分配一些名称/值对,然后使用点标记法访问对象的值。在 console.log 方法中只指定了雇员姓名和 ID,因此只有这两个值会显示在 web 浏览器控制台中。
清单 10-1 的输出如图 10-1 所示。
图 10-1。输出
JSON 数据类型
JSON 有以下数据类型:
-
数字:JSON 中的数字不能出现在引号内,通常是整数或者浮点。例如:
{ "empid": 123 } -
String : JSON 字符串写在双引号里。例如:
{ "empname": "Twinkle" } -
Boolean :值可以是真,也可以是假。例如:
{ "Pass":true } -
Object:JSON 对象可以是任意一组值对。例如:
{ "Employee": { "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" } } -
数组 : -值可以被分组到一个数组中。例如:
{ "Employee": [ "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" ] } -
Null :空值或无值。例如:
{ "value":null }
JSON 对象
JSON 对象的语法是
var Employee = { "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" }
如前所述,JSON 对象在大括号{}中,包含由冒号(:)分隔的键值对。在对象的情况下,键也总是一个在双引号内的字符串。与这些键相关的值可以是任何数据类型(如数字、字符串、数组等)。
有两种方法可以访问对象值:使用点(。)符号,如 Employee.name,或者将值放在括号中,如 Employee["name"]。
通过 JS 编码创建 JSON 对象有三种方式:
-
创建一个空对象:
var myEm = {}; -
创建新对象:
var myEm = new Object(); -
用键/值对创建一个 JSON 对象:
var myEm = { "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" }
清单 10-2 展示了一个完全可行的例子。
清单 10-2。JSON 对象示例
<html>
<body>
<script>
var product, val;
product = { "prname":"Smart Phone", "price":20000, "company":"Sony", "camera":null };
console.log( "Product name is: " + product["prname"] + " company: " + product["company"] );
</script>
</body>
</html>
该代码与清单 10-1 中显示的代码相同。此示例通过使用方括号来访问值。在这种情况下,将访问产品名称和公司,因此所需的输出将是产品名称和公司。清单 10-2 的输出如图 10-2 所示。
图 10-2。输出
JSON 数组
与 JavaScript 中一样,这些值采用数组的形式。值放在方括号[]中,数组值可以是任何数据类型(数字、字符串、数组、对象、布尔值或 null)。
{
"soldin" : [ "US", "UK" ]
}
要访问数组值,请使用如下所示的索引号:
soldin[1];
为了更好地理解这个概念,请考虑清单 10-3 。
清单 10-3。JSON 数组示例
<html>
<body>
<script>
var sellingitem;
sellingitem = {
"itemname":"Smart Phone",
"itemprice":20000,
"soldin":[ "US","UK" ]
};
console.log( "Product " + sellingitem.itemname +
" is sold in " + sellingitem.soldin[0] + ' and ' +
sellingitem.soldin[1] );
</script>
</body>
</html>
这个例子有一个变量 sellingitem,它代表一个对象,并被赋予合适的值。在这个对象中有一个数组 soldin,它包含销售商品的国家。console.log 方法用于在控制台中打印产品名称和国家。清单 10-3 的输出如图 10-3 所示。
图 10-3。输出
在本例中,我们为具有不同属性的关键价值公司定义了一个 JSON 数组,如 Sony、Apple、Lenovo 和 Samsung。现在,为了访问这个数组值,我们使用一个对象的索引号。因此,通过这种方式,我们可以从 JSON 数组中识别产品品牌名称。
JSON 解析方法
parse 方法允许您将接收到的字符串形式的数据流(即 JSON 形式的信息)转换为 JS 对象。为了更好地理解该方法的用法,考虑一个场景,其中有一个字符串,包含一个雇员的姓名、ID、职位和培训师数据。解析方法将如下使用它:
var Employee = JSON.parse('{ "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" }');
parse 方法将以字符串形式表示的整个 JSON 作为输入。该方法执行的结果将以 employee 对象的形式返回。
这个例子的完整代码如清单 10-4 所示。
清单 10-4。JSON 解析方法示例
<html>
<body>
<script>
var Employee;
Employee = JSON.parse('{ "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" }');
console.log( "Employee name:" + Employee.name + " Position:" + Employee.position );
</script>
</body>
</html>
这个示例声明了变量 Employee,并使用 JavaScript 函数 JSON.parse()定义了文本。给定的文本被转换成 JavaScript 对象。清单 10-4 的输出如图 10-4 所示。
图 10-4。输出
JSON 字符串方法
与 parse 方法相反,stringify 方法执行相反的过程。该方法将程序中定义的 JS 对象(如前一个示例中的 Employee 对象)作为输入。
var Employee = { "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" };
然后,这个 employee 对象将被转换成 JSON 字符串形式。
考虑清单 10-5 中所示的 stringify 方法的例子。
清单 10-5。JSON stringify 方法示例
<html>
<body>
<script>
var Employee, EmpStrg;
Employee = { "name":"Twinkle", "empid":1234, "position":"Trainer", "city":"London" };
EmpStrg = JSON.stringify(Employee);
console.log( EmpStrg );
</script>
</body>
</html>
这个示例声明了两个变量 Employee 和 EmpStrg,然后定义了 JavaScript 对象并将其赋给变量 Employee。接下来,使用 JavaScript 函数 JSON.stringify(),将给定的对象转换为字符串格式。清单 10-5 的输出如图 10-5 所示。
图 10-5。输出
摘要
本章介绍了 JSON 的基础知识和 JSON 中使用的数据类型。它讲述了 JSON 数组和对象是如何工作的,讨论了 JSON 对象的有用的方法 parse 和 stringify,以及代码示例。
下一章也是最后一章介绍了编写更好的 JS 代码的最佳实践,以及一些需要避免的典型错误。
十一、杂项主题
本章涵盖了非常有用的主题,但这些主题并不适合前面的章节。它首先概述了严格模式及其对语法检查的影响,以及 JavaScript 中的错误处理。接下来,将为您提供与代码格式相关的提示以及使用变量命名约定的建议。一个单独的部分解释了 JS 程序的调试和故障排除。最后但同样重要的是,本章提供了 JS 编程的最佳实践,并提供了一些提高性能的技巧。
严格模式
使用严格模式使开发人员能够向 JavaScript 代码添加严格的语法检查。例如,使用严格模式时,不能有未显式声明的变量,也不能使用 with 关键字。大多数新版本的浏览器都实现了严格模式。
激活严格模式最简单的方法是在程序或函数的开头加上“use strict”。程序中严格模式适用的区域取决于“使用严格”插入的位置。如果您在函数外部插入“use strict ”(即全局插入),将检查程序的整个代码是否为严格模式。另一方面,如果将它插入到函数的代码中,使用严格的模式规则只检查函数中的代码。
使用严格模式的代码示例如图 11-1 所示。
图 11-1。严格模式的使用
如您所见,代码试图在不使用 var 声明的情况下定义变量 num。因为激活了严格模式,所以代码会给出如下所示的错误。
现在,考虑在图 11-2 所示的函数中使用严格模式的例子。
图 11-2。在函数中使用严格模式
这里,严格模式仅适用于函数 my()。虽然两个对象 myObj 和 myObj1 都包含属性 att1 的副本,但对于函数中的对象,只显示一个错误。在函数外部定义的第一个对象不会产生错误。
使用严格模式有以下优点:
-
它不允许可能使代码难以理解的编程。因此,它使程序更容易理解和维护。
-
它有助于在开发的早期阶段识别使用起来不太安全或者可能在代码执行时出现异常的错误。
严格模式中不允许的一些构造有:
-
属性的重复:不允许在一个对象文字中有一个属性的多个定义。考虑以下情况,其中包括属性 att1 两次:
var myObj = { att1: 10, att2: 15, att1: 20 }; alert(myObj.att1);这段没有严格模式的代码编译并在浏览器警告框中显示 20。如果使用“use strict ”,此代码将生成一个错误。
-
重复的函数参数:在严格模式下,一个函数不允许多次使用一个参数名(形参)。考虑以下示例:
function myFunc(p1, p1){ return p1; }; alert(myFunc(10, 10));如果没有严格模式,此代码显示 10。然而,当使用严格模式时,会产生如图 11-3 所示的错误。
图 11-3。参数名重复导致语法错误
-
代码块中的函数声明:使用严格模式时,不允许用一个代码块声明函数。在严格模式下,函数只能在程序的顶层或函数体中定义。不允许以下示例:
"use strict" for (var i = 0; i < 10; i++) { function myfunc() { } } -
使用 with 语句:在严格模式下,不允许使用 with 语句。
调试 JavaScript
和所有语言一样,JavaScript 需要调试。本节演示了如何在 Google Chrome 浏览器中调试程序,以防运行程序时浏览器中没有直接显示错误。
考虑代码:
<html>
<body>
<script>
var num1 = 10;
alert(num1) ;
num = 1;
</script>
</body>
</html>
如您所见,num 没有声明。然而,当代码在浏览器中执行时,警告框仍然被显示(即,直到代码不再正确的点)。
要在 Chrome 浏览器中打开并浏览调试器,请按照以下步骤操作:
-
按 Ctrl+Shift+I。这将打开浏览器右侧的控制台选项卡。
-
单击源选项卡。这显示了控制台中的程序代码,红色圆圈中有一个白色的×标识错误的行(见图 11-4 )。有问题的代码下面还有一条红色的曲线。
图 11-4。源代码错误
-
点击控制台选项卡查看错误文本,如图 11-5 所示。
图 11-5。语法错误
假设你的程序没有语法错误,但是有一定的逻辑错误,你不确定到底是什么原因。在这种情况下,您首先需要找到一个合适的位置来放置断点,然后需要查看各种语句的执行以及所使用的变量的内容。
若要启动调试器,请按 Ctrl+Shift+I,然后选择“源代码”选项卡。单击要放置断点的行号。确保您单击的是行号,而不是代码本身。断点显示为行号上方的蓝色高亮箭头,如图 6 行的图 11-6 所示。
图 11-6。浏览器控制台中的断点
接下来,重新运行 HTML 页面。这将重新运行 JS 代码,调试器将在断点处停止;屏幕左侧会显示“调试器暂停”,如图 11-6 的左下窗格所示。
要查看变量的内容,请在屏幕的右下窗格中,单击“监视”选项卡。单击+按钮。在弹出的小文本框中,输入需要查看其内容的变量的名称,在本例中为 a1。这将在观察区显示 a1 的值,如图 11-6 所示。
您可以使用以下功能继续:
-
若要单步执行下一个函数调用,请按下 F10。
-
若要单步执行下一个函数调用,请按 F11。
-
若要退出当前功能,请按 Shift+F11。
为了存在变量调试器,按 F8。要取消所有断点,请按 CTRL+F8。
正如您将看到的,一旦您在代码中继续执行,当前正在执行的行将会以蓝色突出显示。
代码格式提示
本节提供了关于 JS 代码格式的建议。这些提示将使您的代码更容易理解,并且不会影响语法检查结果。
在每条语句的末尾使用分号
例如,考虑以下语句:
int = int + 1
这条语句编译得很好,给出了以下内容。但是,语句末尾缺少分号。该语句的推荐形式是
int = int + 1;
空白的使用
不要在代码中的括号前后使用任何空格。这些包括任何函数参数以及函数参数。考虑下面的例子:
<html>
<body>
<script>
function mult( a, b ) {
return a * b;
}
var a1 = mult( 10,10);
alert ( a1 );
</script>
</body>
</html>
在 mult 函数中,参数 a 和 b 前后会出现不必要的空格。同样,在调用 mult 函数时会出现多余的空格。甚至 alert 函数调用也包含多余的空格。必须避免这种编码。以下是上一个示例的正确形式:
function mult(a,b) {
return a * b;
}
var a1 = mult(10,10);
alert (a1);
在 switch、while、for、if、else、try、catch 和 finally 之后总是使用空格。此外,在花括号后面、运算符旁边,甚至在连接逗号(如函数参数)之后,都要使用空格。
比较运算符的用法
你应该经常使用!== and ===代替== and!=,分别为。
函数花括号
确保 if、else、for 和 switch 语句以及函数调用的左花括号({)与语句关键字或函数(以适用者为准)位于同一行。
例如,考虑以下情况:
function mult(a,b)
{
return a * b;
}
正确的形式是
function mult(a,b) {
return a * b;
}
格式正确的代码示例
一个包含所有上述提示的格式正确的代码示例如下所示:
function myfunction(a1, a2) {
var b2 = a1 / a2;
if (b2 === 1) {
b2--;
}
for (var a = 0; a < b2; a++) {
alert(b2);
}
function func2(a1, b2) {
return (b2 * a1) + b2;
}
return func2(2, 4);
}
变量的命名约定
我强烈建议您对 JavaScript 变量使用一致的命名约定。变量的前缀必须表示变量的类型。我还推荐使用 camelCase 命名约定,前缀用小写,然后继续用大写。我推荐使用表 11-1 中所示的命名约定示例。
表 11-1。命名约定示例
|类型
|
例子
| | --- | --- | | 线 | 名字 | | 布尔代数学体系的 | 装满 | | 日期 | 昨天 | | 目标 | oDomObj | | 浮动 | 货运 | | 正则表达式 | 研究模式 | | 功能 | fnDivide | | 功能参数 | 因素 | | 排列 | 进入 |
注意
您可能需要遵循基于公司/项目代码标准的命名约定,这与我在这里提出的不同。重要的是在整个项目中使用一致的命名约定。
运行时错误和异常处理
异常(有时也称为运行时错误)可能在程序执行期间发生;也就是编译后。例如,以下行会导致异常:
<html>
<body>
<script>
abc("message");
</script>
</body>
</html>
在这种情况下,语法是正确的。然而,在执行时,代码试图调用一个不存在的函数。
异常可以通过 try 来捕获...捕捉...最后屏蔽。使用块,您可以捕获开发人员生成的异常和运行时异常。然而,使用这种方法可能无法捕捉 JS 语法错误。
典型尝试的语法...捕捉...这里显示了最后一个块:
<script>
try {
// code to be executed
}
catch ( e ) {
// Code to be executed when exception happens
}
[ finally {
// this part of code is run irrespective of whether an exception happens or not
}]
</script>
编码时,第一个块是 try 块。在这之后,您可能有一个 catch 块或一个 finally 块(或者两者都有)。finally 块是可选的。如果 try 块中出现异常,它将被放置在 error 对象 e 中,并且运行 catch 块中的代码。
catch 块由 error 对象提供,该对象包含有关已发生错误的相关信息。错误对象有三个属性:
-
名称:错误名称
-
消息:错误消息
-
描述:错误的描述
此外,错误名称可能是几种类型之一;这里展示了几个重要的例子:
-
ReferenceError:非法引用
-
类型错误: 类型错误
-
范围错误:数字不在范围内
-
错误语法:错误语法
在 try/catch 之后,无论是否发生异常,finally 块中的任何代码都会运行。
现在您已经对 JS 领域中的异常处理有了一些了解,您已经准备好查看一些运行中的异常处理代码。假设您有以下代码块:
<html>
<body>
<script>
abcd("This message");
</script>
</body>
</html>
正如你所看到的,程序调用了一个不存在的名为 abcd 的函数。
这段代码导致运行时错误。要更改此程序以捕捉异常并在警告框中显示错误描述,可以使用以下代码:
<html>
<body>
<script>
try {
abcd("This message");
}
catch ( exception ) {
alert("An exception occurred, the description of which is: " + exception.description );
}
</script>
</body>
</html>
尝试 abcd 函数调用的代码放在 try 块中。警告框代码放在 catch 块中。异常对象将包含有关所发生错误的必要信息。该信息将显示在一个警告框中。
程序的输出如图 11-7 所示。
图 11-7。处理的异常
JavaScript 的最佳实践
本节概述了在使用 JavaScript 语言时要实现的一些最佳实践。这些技巧包括避免使用全局变量和闭包,为参数分配默认值,以及在 switch 语句中始终使用 default 子句。
避免使用全局变量
建议在 JS 中避免使用全局变量。当你有选择的时候,使用局部变量。永远不要全局定义数据和对象以及函数。作为默认行为,JS 将所有声明置于顶层。但是,请确保在编码时将数据声明写在程序的顶部。
始终将数据声明放在代码的顶部。这包括将数据保存在主程序或任何使用的函数的顶部。通过遵循这种做法,代码不仅看起来整洁干净,而且易于更改,因为所有声明的数据都在顶部。以下示例展示了这种做法。
var myPlayerName, myWeight, myHeight;
myPlayerName = "James";
myWeight = 201.1;
myHeight = 85;
即使对于循环,也要确保使用的所有变量都在顶部声明:
var a;
for (a = 0; a < 10; a++) {
}
永远不要为数字、字符串或布尔值声明对象
为数字、字符串或布尔值声明对象可能会对性能产生负面影响,并且可能不会产生正确的结果。
考虑以下情况,其中比较返回 false:
var myString1 = "James";
var myString2 = new String("James");
console.log((myString1===myString2)); // false
现在考虑下面的例子:
var myString1 = new String("James");
var myString2 = new String("James");
console.log((myString1==myString2)); // false
console.log((myString1===myString2)); // false
两个比较语句都返回 false,因为您不能比较对象(在本例中是字符串对象)。
switch 语句中 default 子句的使用
使用 switch control 语句时,请始终使用 default 子句。考虑以下示例:
switch (num) {
case 0:
value = "Off";
break;
case 1:
value = "On";
break;
}
在这种情况下,只有两种结果是可能的;不包括默认条款。因此,当 num 的值既不是 0 也不是 1 时,你不会知道发生了什么。我建议使用默认条款,即使你认为没有必要。
这个例子的正确形式是
switch (num) {
case 0:
value = "Off";
break;
case 1:
value = "On";
break;
default:
value = "Unknown";
}
当 num 的值既不是 0 也不是 1 时,default 子句将该值作为 Unknown 传递。
在参数中分配默认值
为函数中的参数分配默认值(初始值)是一个很好的做法,这与您预计可能具有未定义值的参数相对应。
考虑以下示例:
function function1(a,b) {
..
}
在这种情况下,如果在调用函数 1 时没有为参数 b 传递值,则输出如下:
function1(10);
因为没有为 b 传递值,function1 可能会崩溃和/或导致异常。
因此,建议您在功能代码的开头为这些参数分配默认值/初始值:
function function1(a,b) {
if (b === undefined) {
b = 1;
}
.....
}
使用===比较
做比较的时候建议用===而不是==来代替。===运算符执行值和类型比较,而==运算符只执行值比较(内容检查)。
为了更好地理解这种差异,请考虑以下几点:
<html>
<body>
<script>
console.log(8=="8"); // true
console.log(8==="8"); // false
console.log(0==false); // true
console.log(1==true); // true
console.log(0===false); // false
console.log(1===true); // false
</script>
</body>
</html>
在这里,==和===运算符用于比较布尔值 true 和 false。程序的输出如图 11-8 所示。
图 11-8。程序输出
避免使用闭包
出于性能原因,也建议不要使用闭包。
请考虑以下几点:
Player.obj = function() {
this.method1 = function() {
};
}
每次创建 Player.obj 的实例时,都会为 method1 创建一个函数和相应的闭包。
或者,更好的方法是
Player.obj = function() {
};
Player.obj.prototype.method1 = function() {
};
使用这种方法,不管创建多少个 Player.obj 实例,都会为 method1 创建一个没有任何闭包的函数。
摘要
这最后一章汇集了各种各样的 JS 主题,可以帮助你改进你的程序。它首先概述了严格模式及其对语法检查的影响。接下来,您看到了如何在 JavaScript 中实现错误和异常处理。接下来介绍了 JS 程序的调试和故障排除。本章最后总结了 JS 编程的最佳实践以及性能改进技巧。