JavaScript web 开发人员必须学习的 3 门语言中的一门:
JavaScript 是一种轻量级的编程语言。
JavaScript 是可插入 HTML 页面的编程代码。
JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。
JavaScript 很容易学习。
HTML 中的脚本必须位于 标签之间。
脚本可被放置在 HTML 页面的 和
部分中。
通常的做法是把函数放入 head部分中,或者放在页面底部。这样就可以把它们安置到同一处位置,不会干扰页面的内容。
也可以把脚本保存到外部文件中。外部文件通常包含被多个网页使用的代码。
外部 JavaScript 文件的文件扩展名是 .js。
如需使用外部文件,请在 script 标签的 “src” 属性中设置该 .js 文件。
JavaScript 可以通过不同的方式来输出数据:
JavaScript 语句定义两种类型的值:混合值和变量值。
混合值被称为字面量(literal)。变量值被称为变量。
在编程语言中,一般固定值称为字面量,如 3.14。
数字(Number)字面量 可以是整数或者是小数,或者是科学计数(e)。
字符串(String)字面量 可以使用单引号或双引号。
表达式字面量 用于计算。
数组(Array)字面量 定义一个数组。
对象(Object)字面量 定义一个对象。
函数(Function)字面量 定义一个函数。
在编程语言中,变量用于存储数据值。
JavaScript 使用 var 关键词(用于标识被执行的动作)来声明变量。(声明之后,变量是没有值的。(技术上,它的值是 undefined。))
= 号用于为变量赋值。
var x;
x = 7;
可以在一条语句中声明许多变量。以 var 作为语句的开头,并以逗号分隔变量:
var person = "Bill Gates", carName = "porsche", price = 15000;
JavaScript 算数运算符
算数运算符用于对数字执行算数运算:
运算符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* |
乘法 |
/ | 除法 |
% | 系数(返回除法的余数) |
++ | 递加 |
– | 递减 |
** |
幂(第一个操作数提升到第二个操作数的幂。产生的结果与 Math.pow(x,y) 相同) |
var x = 5;
var z = x ** 2; // 结果是 25
运算符优先级:乘法(*)
和除法(%)比加法(+)和减法(-)拥有更高的优先级。同时,(就像在学校的数学中那样)能够通过使用括号来改变优先级。当多个运算拥有相同的优先级时(比如加法和减法),对它们的计算是从左向右的。
JavaScript 赋值运算符
赋值运算符向 JavaScript 变量赋值。
运算符 | 例子 | 等同于 |
---|---|---|
= | x = y | x = y |
+= | x += y | x = x + y |
-= | x -= y | x = x - y |
*= | x *= y | x = x * y |
/= | x /= y | x = x / y |
%= | x %= y | x = x % y |
JavaScript 比较运算符
运算符 | 描述 |
---|---|
== | 等于(等值) |
=== | 等值等型 |
!= | 不相等 |
!== | 不等值或不等型 |
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
? | 三元运算符 |
JavaScript 逻辑运算符
运算符 | 描述 |
---|---|
&& | 逻辑与 |
|| |
逻辑或 |
! | 逻辑非 |
JavaScript 类型运算符
运算符 | 描述 |
---|---|
typeof | 返回变量的类型。 |
instanceof | 返回 true,如果对象是对象类型的实例。 |
表达式是值、变量和运算符的组合,计算结果是值,表达式也可包含变量值,值可以是多种类型,比如数值和字符串。
x * 10
"Bill" + " " + "Gates"
如果把要给数值放入引号中,其余数值会被视作字符串并被级联(在用于字符串时,+ 运算符被称为级联运算符。)。
相加两个数字,将返回和,但对一个数字和一个字符串相加将返回一个字符串。
var x = "8" + 3 + 5;
输出为:835
var x = 3 + 5 + "8";
输出为:88
双斜杠//
或/* 与 */
之间的代码被视为注释。
所有 JavaScript 变量必须以唯一的名称的标识。这些唯一的名称称为标识符。
在 JavaScript 中,标识符用于命名变量(以及关键词、函数和标签)。
在大多数编程语言中,合法名称的规则大多相同。
构造变量名称(唯一标识符)的通用规则是:
JavaScript 中不能使用连字符。它是为减法预留的。
下划线:
first_name, last_name, master_card, inter_city.
驼峰式大小写(Camel Case):
FirstName, LastName, MasterCard, InterCity.
JavaScript 程序员倾向于使用以小写字母开头的驼峰大小写。
JavaScript 变量能够保存多种数据类型:数值、字符串值、数组、对象等等。JavaScript 拥有动态类型。这意味着相同变量可用作不同类型。
var cars = ["Porsche", "Volvo", "BMW"];
数组索引基于零,这意味着第一个项目是 [0],第二个项目是 [1],以此类推。
var person = {firstName:"Bill", lastName:"Gates", age:62, eyeColor:"blue"};
例中的对象(person)有四个属性:firstName、lastName、age 以及 eyeColor。
typeof "Bill Gates" // 返回 "string"
typeof 3.14 // 返回 "number"
typeof 运算符对数组返回 “object”,因为在 JavaScript 中数组属于对象。
var person; // 值是 undefined,类型是 undefined
任何变量均可通过设置值为 undefined 进行清空。其类型也将是 undefined。
person = undefined; // 值是 undefined,类型是 undefined
var car = ""; // 值是 "",类型是 "string"
var person = null; // 值是 null,但是类型仍然是对象
typeof undefined // undefined
typeof null // object
null === undefined // false
null == undefined // true
JavaScript 函数是被设计为执行特定任务的代码块。
JavaScript 函数会在某代码调用它时被执行。
JavaScript 函数通过 function 关键词进行定义,其后是函数名和括号 ()。
函数名可包含字母、数字、下划线和美元符号(规则与变量名相同)。
圆括号可包括由逗号分隔的参数,由函数执行的代码被放置在花括号中:{}
function name(参数 1, 参数 2, 参数 3,...) {
要执行的代码
}
函数参数(Function parameters)是在函数定义中所列的名称。
函数参数(Function arguments)是当调用函数时由函数接收的真实的值。
在函数中,参数是局部变量。
在其他编程语言中,函数近似程序(Procedure)或子程序(Subroutine)。
函数中的代码将在其他代码调用该函数时执行:
当 JavaScript 到达 return 语句,函数将停止执行。
如果函数被某条语句调用,JavaScript 将在调用语句之后“返回”执行代码。
函数通常会计算出返回值。这个返回值会返回给调用者:
var x = myFunction(4, 3); // 调用函数,返回值被赋值给 x
function myFunction(a, b) {
return a * b; // 函数返回 a 和 b 的乘积
}
结果:12
myFunction引用的是函数对象,而 myFunction() 引用的是函数结果。 访问没有 () 的函数将返回函数定义。
函数的使用方法与变量一致,在所有类型的公式、赋值和计算中。
var x = toCelsius(77);
var text = "The temperature is " + x + " Celsius";
var text = "The temperature is " + toCelsius(77) + " Celsius";
在 JavaScript 函数中声明的变量,会成为函数的局部变量。局部变量只能在函数内访问。
由于局部变量只能被其函数识别,因此可以在不同函数中使用相同名称的变量。局部变量在函数开始时创建,在函数完成时被删除。
对象也是变量。但是对象包含很多值。
JavaScript 对象无法进行对比,比较两个对象 JavaScript 将始终返回 false。
把多个值(porsche, 911, white)赋给名为 car 的变量:
var car = {type:"porsche", model:"911", color:"white"};
值以名称:值对的方式来书写(名称和值由冒号分隔)。
JavaScript 对象是被命名值的容器。
(JavaScript 对象中的)名称:值对被称为属性。
对象也可以有方法。方法是在对象上执行的动作。方法以函数定义被存储在属性中。方法是作为属性来存储的函数。
var person = {
firstName: "Bill",
lastName : "Gates",
id : 678,
fullName : function() {
return this.firstName + " " + this.lastName;
}
};
在函数定义中,this 引用该函数的“拥有者”。
在上面的例子中,this 指的是“拥有” fullName 函数的 person 对象。
换言之,this.firstName 的意思是 this 对象的 firstName 属性。
够以两种方式访问属性:
能够通过如下语法访问对象方法:objectName.methodName()。
如果通过关键词 “new” 来声明 JavaScript 变量,则该变量会被创建为对象:
var x = new String(); // 把 x 声明为 String 对象
var y = new Number(); // 把 y 声明为 Number 对象
var z = new Boolean(); // 把 z 声明为 Boolean 对象
避免字符串、数值或逻辑对象。他们会增加代码的复杂性并降低执行速度。
HTML 事件是发生在 HTML 元素上的“事情”。
当在 HTML 页面中使用 JavaScript 时,JavaScript 能够“应对”这些事件。
HTML 事件可以是浏览器或用户做的某些事情。
下面是 HTML 事件的一些例子:
使用单引号:
使用双引号:
例子:
改变了 id="demo" 的元素的内容:
使用 this.innerHTML改变其自身元素的内容:
常见的 HTML 事件
事件 | 描述 |
---|---|
onchange | HTML元素已被改变 |
onclick | 用户点击了 HTML 元素 |
onmouseover | 用户把鼠标移动到 HTML 元素上 |
onmouseout | 用户把鼠标移开 HTML 元素 |
onkeydown | 用户按下键盘按键 |
onload | 浏览器已经完成页面加载 |
JavaScript 字符串用于存储和操作文本。JavaScript 字符串是引号中的零个或多个字符。
var txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var sln = txt.length;
var y = "中国是瓷器的故乡,因此 china 与"China(中国)"同名。"
代码 | 结果 | 描述 |
---|---|---|
’ | ’ | 单引号 |
" | " | 双引号 |
\ | \ |
反斜杠 |
\b | 退格键 | |
\f | 换页 | |
\n | 新行 | |
\r | 回车 | |
\t | 水平制表符 | |
\v | 垂直制表符 |
后六个转义字符最初设计用于控制打字机、电传打字机和传真机。它们在 HTML 中没有任何意义。
字符串可通过关键词 new 定义为对象:var firstName = new String(“Bill”)。
但注意请不要把字符串创建为对象。它会拖慢执行速度。new 关键字使代码复杂化。也可能产生一些意想不到的结果。
字符串方法帮助您处理字符串。
原始值,比如“Bill Gates”,无法拥有属性和方法(因为它们不是对象)。
但是通过 JavaScript,方法和属性也可用于原始值,因为在执行方法和属性时 JavaScript 将原始值视为对象。
var str = "The full name of China is the People's Republic of China.";
var pos = str.indexOf("China");
结果为17。
(0 是字符串中的第一个位置,1 是第二个,2 是第三个 ...)
lastIndexOf() 方法返回指定文本在字符串中最后一次出现的索引。
如果未找到文本, indexOf() 和 lastIndexOf() 均返回 -1。
两种方法都接受作为检索起始位置的第二个参数。
lastIndexOf() 方法向后进行检索(从尾到头),这意味着:假如第二个参数是 50,则从位置 50 开始检索,直到字符串的起点:
var str = "The full name of China is the People's Republic of China.";
var pos = str.lastIndexOf("China", 50);
检索字符串中的字符串:search() 方法搜索特定值的字符串,并返回匹配的位置。
两种方法,indexOf() 与 search(),作用是相似的。
这两种方法是不相等的。区别在于:
提取部分字符串:
有三种提取部分字符串的方法:
替换字符串内容 :replace() 方法用另一个值替换在字符串中指定的值,不会改变调用它的字符串。它返回的是新字符串。默认地,replace() 只替换首个匹配。replace() 对大小写敏感。如需执行大小写不敏感的替换,请使用正则表达式 /i(大小写不敏感):
str = "Please visit Microsoft!";
var n = str.replace(/MICROSOFT/i, "W3School");
如需替换所有匹配,请使用正则表达式的 g 标志(用于全局搜索):
str = "Please visit Microsoft and Microsoft!";
var n = str.replace(/Microsoft/g, "W3School");
两行是等效的:
var text = "Hello" + " " + "World!";
var text = "Hello".concat(" ","World!");
var str = "HELLO WORLD";
str.charAt(0); // 返回 H
var str = "HELLO WORLD";
str.charCodeAt(0); // 返回 72
var str = "HELLO WORLD";
str[0]; // 返回 H
使用属性访问有点不太靠谱:
不适用 Internet Explorer 7 或更早的版本
它让字符串看起来像是数组(其实并不是)
如果找不到字符,[ ] 返回 undefined,而 charAt() 返回空字符串。
它是只读的。str[0] = “A” 不会产生错误(但也不会工作!)
var txt = "a,b,c,d,e"; // 字符串
txt.split(","); // 用逗号分隔
txt.split(" "); // 用空格分隔
txt.split("|"); // 用竖线分隔
JavaScript 数值始终是 64 位的浮点数。
与许多其他编程语言不同,JavaScript 不会定义不同类型的数,比如整数、短的、长的、浮点的等等。
JavaScript 数值始终以双精度浮点数来存储,根据国际 IEEE 754 标准。
此格式用 64 位存储数值,其中 0 到 51 存储数字(片段),52 到 62 存储指数,63 位存储符号。
整数(不使用指数或科学计数法)会被精确到 15 位。
var x = 999999999999999; // x 将是 999999999999999
var y = 9999999999999999;// y 将是 10000000000000000
小数的最大数是 17 位,但是浮点的算数并不总是 100% 精准:
var x = 0.2 + 0.1; // x 将是 0.30000000000000004
用乘除法有助于解决上面的问题:
var x = (0.2 * 10 + 0.1 * 10) / 10; // x 将是 0.3
JavaScript 字符串可以拥有数字内容。
在所有数字运算中,JavaScript 会尝试将字符串转换为数字:
var x = "100";
var y = "10";
var z = x / y; // z 将是 10
但加法不可以:
var x = "100";
var y = "10";
var z = x + y; // z 不会是 110(而是 10010)
JavaScript 用 + 运算符对字符串进行了级联。
NaN 属于 JavaScript 保留词,指示某个数不是合法数。
尝试用一个非数字字符串进行除法会得到 NaN(Not a Number):
var x = 100 / "Apple"; // x 将是 NaN(Not a Number)
可使用全局 JavaScript 函数 isNaN() 来确定某个值是否是数:
var x = 100 / "Apple";
isNaN(x); // 返回 true,因为 x 不是数
要小心 NaN。假如在数学运算中使用了 NaN,则结果也将是 NaN。
var x = NaN;
var y = 5;
var z = x + y; // z 将是 NaN
var x = NaN;
var y = "5";
var z = x + y; // z 将是 NaN5
NaN 是数,typeof NaN 返回 number。
Infinity (或 -Infinity)是 JavaScript 在计算数时超出最大可能数范围时返回的值。除以 0(零)也会生成 Infinity。
Infinity 是数:typeOf Infinity 返回 number。
JavaScript 会把前缀为 0x 的数值常量解释为十六进制。
绝不要用前导零写数字(比如 07)。
一些 JavaScript 版本会把带有前导零的数解释为八进制。
默认地,Javascript 把数显示为十进制小数。
但是您能够使用 toString() 方法把数输出为十六进制、八进制或二进制。
Number 方法帮助处理数值。
所有数字方法可用于任意类型的数字(字面量、变量或表达式)
var x = 9.656;
x.toFixed(0); // 返回 10
x.toFixed(2); // 返回 9.66
x.toFixed(4); // 返回 9.6560
x.toFixed(6); // 返回 9.656000
toFixed(2) 非常适合处理金钱。
var x = 9.656;
x.toPrecision(); // 返回 9.656
x.toPrecision(2); // 返回 9.7
x.toPrecision(4); // 返回 9.656
x.toPrecision(6); // 返回 9.65600
var x = 123;
x.valueOf(); // 从变量 x 返回 123
(123).valueOf(); // 从文本 123 返回 123
(100 + 23).valueOf(); // 从表达式 100 + 23 返回 123
可用于把 JavaScript 变量转换为数值:
x = true;
Number(x); // 返回 1
x = false;
Number(x); // 返回 0
x = new Date();
Number(x); // 返回 1404568027739(把日期转换为数字)
x = "10"
Number(x); // 返回 10
x = "10 20"
Number(x); // 返回 NaN
parseInt("10"); // 返回 10
parseInt("10.33"); // 返回 10
parseInt("10 20 30"); // 返回 10
parseInt("10 years"); // 返回 10
parseInt("years 10"); // 返回 NaN
parseFloat("10"); // 返回 10
parseFloat("10.33"); // 返回 10.33
parseFloat("10 20 30"); // 返回 10
parseFloat("10 years"); // 返回 10
parseFloat("years 10"); // 返回 NaN
属性 | 描述 |
---|---|
MAX_VALUE | 返回 JavaScript 中可能的最大数。 |
MIN_VALUE | 返回 JavaScript 中可能的最小数。 |
NEGATIVE_INFINITY | 表示负的无穷大(溢出返回-Infinity)。 |
NaN | 表示非数字值(“Not-a-Number”)。 |
POSITIVE_INFINITY | 表示无穷大(溢出返回Infinity)。 |
数字属性不可用于变量。
JavaScript 数组是一种特殊的变量,用于在单一变量中存储多个值,并且还可以通过引用索引号来访问这些值。
var array-name = [item1, item2, ...];
var cars = ["Saab", "Volvo", "BMW"];
空格和折行并不重要。声明可横跨多行。不要最后一个元素之后写逗号(比如 “BMW”,)。可能存在跨浏览器兼容性问题。
访问 cars 中的首个元素的值:
var name = cars[0];
修改 cars 中的首个元素:
cars[0] = "Opel";
引用数组名来访问完整数组:
var cars = ["Saab", "Volvo", "BMW"];
document.getElementById("demo").innerHTML = cars;
length 属性返回数组的长度(数组元素的数目)。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.length; // fruits 的长度是 4
访问最后一个数组元素:
fruits = ["Banana", "Orange", "Apple", "Mango"];
var last = fruits[fruits.length - 1];
遍历数组元素:
遍历数组的最安全方法是使用 “for” 循环。
var fruits, text, fLen, i;
fruits = ["Banana", "Orange", "Apple", "Mango"];
fLen = fruits.length;
text = "";
for (i = 0; i < fLen; i++) {
text += "- " + fruits[i] + "
";
}
text += "
";
document.getElementById("demo").innerHTML = text;
也可以使用 Array.foreach() 函数(Array.forEach() 为每个数组元素调用函数。)。
var fruits, text;
fruits = ["Banana", "Orange", "Apple", "Mango"];
text = "";
fruits.forEach(myFunction);
text += "
";
document.getElementById("demo").innerHTML = text;
function myFunction(value) {
text += "" + value + " ";
添加数组元素
向数组添加新元素的最佳方法是使用 push() 方法:
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.push("Lemon"); // 向 fruits 添加一个新元素 (Lemon)
也可以使用 length 属性向数组添加新元素:
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits[fruits.length] = "Lemon"; // 向 fruits 添加一个新元素 (Lemon)
注意:添加最高索引的元素可在数组中创建未定义的“洞”:
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits[6] = "Lemon"; // 向 fruits 添加一个新元素 (Lemon)
则fruits[4]与fruits[5]为undefined。
在 JavaScript 中,数组使用数字索引。对象使用命名索引。数组是特殊类型的对象,具有数字索引。
何时使用数组,何时使用对象?
如果希望元素名为字符串(文本)则应该使用对象。
如果希望元素名为数字则应该使用数组。
避免 new Array():
没有必要使用 JavaScript 的内建数组构造器 new Array()。
使用 [] 取而代之!
new 关键词只会使代码复杂化。它还会产生某些不可预期的结果。
如何识别数组
由于typeof 运算符返回 “object”,因为 JavaScript 数组属于对象。
因此定义了新方法 :
Array.isArray(fruits); // 返回 true
function isArray(x) {
return x.constructor.toString().indexOf("Array") > -1;
}
假如参数为数组,则上面的函数始终返回 true。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
document.getElementById("demo").innerHTML = fruits instanceof Array;
var fruits = ["Banana", "Orange","Apple", "Mango"];
document.getElementById("demo").innerHTML = fruits.join(" * ");
Banana * Orange * Apple * Mango
Popping 和 Pushing
在处理数组时,删除元素和添加新元素是很简单的。
Popping 和 Pushing 指的是:
从数组弹出项目,或向数组推入项目。
pop() 方法从数组中删除最后一个元素,返回“被弹出”的值。
push() 方法(在数组结尾处)向数组添加一个新的元素,返回新数组的长度。
位移元素
位移与弹出等同,但处理首个元素而不是最后一个。
shift() 方法:会删除首个数组元素,并把所有其他元素“位移”到更低的索引,返回被“位移出”的字符串。
unshift() 方法:(在开头)向数组添加新元素,并“反向位移”旧元素,返回新数组的长度。
删除元素
既然 JavaScript 数组属于对象,其中的元素就可以使用 JavaScript delete 运算符来删除。
使用 delete 会在数组留下未定义的空洞。请使用 pop() 或 shift() 取而代之。
拼接数组
splice() 方法:可用于向数组添加新项,也可用于删除元素。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2, 0, "Lemon", "Kiwi");
第一个参数(2)定义了应添加新元素的位置(拼接)。
第二个参数(0)定义应删除多少元素。
其余参数(“Lemon”,“Kiwi”)定义要添加的新元素。
splice() 方法返回一个包含已删除项的数组。
var arr1 = ["Cecilie", "Lone"];
var arr2 = ["Emil", "Tobias", "Linus"];
var arr3 = ["Robin", "Morgan"];
var myChildren = arr1.concat(arr2, arr3); // 将arr1、arr2 与 arr3 连接在一起
var arr1 = ["Cecilie", "Lone"];
var myChildren = arr1.concat(["Emil", "Tobias", "Linus"]);
数组排序
sort() 方法以字母顺序对数组进行排序。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort(); // 对 fruits 中的元素进行排序
反转函数
reverse() 方法反转数组中的元素,使用它以降序对数组进行排序。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort(); // 对 fruits 中的元素进行排序
fruits.reverse(); // 反转元素顺序
数字排序
默认地,sort() 函数按照字符串顺序对值进行排序。
该函数很适合字符串(“Apple” 会排在 “Banana” 之前)。
不过,如果数字按照字符串来排序,则 “25” 大于 “100”,因为 “2” 大于 “1”。
正因如此,sort() 方法在对数值排序时会产生不正确的结果。
可以通过一个比值函数来修正此问题:
var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a - b});
比值函数
比较函数的目的是定义另一种排序顺序。
比较函数应该返回一个负,零或正值,这取决于参数:
function(a, b){return a-b}
当 sort() 函数比较两个值时,会将值发送到比较函数,并根据所返回的值(负、零或正值)对这些值进行排序。
例如:
当比较 40 和 100 时,sort() 方法会调用比较函数 function(40,100)。
该函数计算 40-100,然后返回 -60(负值)。
排序函数将把 40 排序为比 100 更低的值。
以随机顺序排序数组
var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return 0.5 - Math.random()});
查找最高(或最低)的数组值
JavaScript 不提供查找数组中最大或最小数组值的内建函数。
不过,在对数组进行排序之后,能够使用索引来获得最高或最低值。
但如果仅仅需要找到最高或最低值,对整个数组进行排序是效率极低的方法。
因此,可以使用 Math.max.apply 来查找数组中的最高值:
function myArrayMax(arr) {
return Math.max.apply(null, arr);
}
Math.max.apply([1, 2, 3]) 等于 Math.max(1, 2, 3)。
使用 Math.min.apply 来查找数组中的最低值:
function myArrayMin(arr) {
return Math.min.apply(null, arr);
}
Math.min.apply([1, 2, 3]) 等于 Math.min(1, 2, 3)。
排序对象数组
JavaScript 数组经常会包含对象:
var cars = [
{type:"Volvo", year:2016},
{type:"Saab", year:2001},
{type:"BMW", year:2010}];
解决方法是通过比较函数来对比属性值:
cars.sort(function(a, b){return a.year - b.year});
比较字符串属性会稍复杂:
cars.sort(function(a, b){
var x = a.type.toLowerCase();
var y = b.type.toLowerCase();
if (x < y) {return -1;}
if (x > y) {return 1;}
return 0;
});
数组迭代方法对每个数组项进行操作。
Array.forEach()
forEach() 方法为每个数组元素调用一次函数(回调函数)。
该函数接受 3 个参数:项目值,项目索引,数组本身。
Array.map()
map() 方法通过对每个数组元素执行函数来创建新数组,方法不会对没有值的数组元素执行函数,方法不会更改原始数组。
将每个数组值乘以2:
var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);
function myFunction(value, index, array) {
return value * 2;
}
该函数接受 3 个参数:项目值,项目索引,数组本身。
Array.filter()
filter() 方法创建一个包含通过测试的数组元素的新数组。
用值大于 18 的元素创建一个新数组:
var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);
function myFunction(value, index, array) {
return value > 18;
}
该函数接受 3 个参数:项目值,项目索引,数组本身。
Array.reduce()
reduce() 方法在每个数组元素上运行函数,以生成(减少它)单个值,不会减少原始数组,方法在数组中从左到右工作。
确定数组中所有数字的总和:
var numbers1 = [45, 4, 9, 16, 25];
var sum = numbers1.reduce(myFunction);
function myFunction(total, value, index, array) {
return total + value; //99
}
此函数接受 4 个参数:总数(初始值/先前返回的值),项目值,项目索引,数组本身。
reduce() 方法能够接受一个初始值:
var numbers1 = [45, 4, 9, 16, 25];
var sum = numbers1.reduce(myFunction, 100); //199
function myFunction(total, value) {
return total + value;
}
Array.reduceRight()与reduce()相同,只是在数组中是从右到左工作。
Array.every()
every() 方法检查所有数组值是否通过测试。
检查所有数组值是否大于 18:
var numbers = [45, 4, 9, 16, 25];
var allOver18 = numbers.every(myFunction);
function myFunction(value, index, array) {
return value > 18;
} //false
该函数接受 3 个参数:项目值,项目索引,数组本身。
Array.some()
some() 方法检查某些数组值是否通过了测试。
检查某些数组值是否大于 18:
var numbers = [45, 4, 9, 16, 25];
var someOver18 = numbers.some(myFunction);
function myFunction(value, index, array) {
return value > 18;
} //true
该函数接受 3 个参数:项目值,项目索引,数组本身。
Array.indexOf()
indexOf() 方法在数组中搜索元素值并返回其位置。
检索数组中的项目 "Apple":
var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");
语法:array.indexOf(item, start)
Array.lastIndexOf():Array.lastIndexOf() 与 Array.indexOf() 类似,但是从数组结尾开始搜索。
Array.find()
find() 方法返回通过测试函数的第一个数组元素的值。
查找(返回)大于 18 的第一个元素的值:
var numbers = [4, 9, 16, 25, 29];
var first = numbers.find(myFunction);
function myFunction(value, index, array) {
return value > 18;
}
此函数接受 3 个参数:项目值,项目索引,数组本身。
Array.findIndex()
findIndex() 方法返回通过测试函数的第一个数组元素的索引。
此函数接受 3 个参数:项目值,项目索引,数组本身。
创建 Date 对象
Date 对象由新的 Date() 构造函数创建。
有 4 种方法创建新的日期对象:
var d = new Date("October 13, 2014 11:13:00");
日期方法
日期方法允许使用本地时间或 UTC(通用或 GMT)时间来获取和设置日期对象的年、月、日、小时、分钟、秒和毫秒。
d = new Date();
document.getElementById("demo").innerHTML = d;
等同于:
d = new Date();
document.getElementById("demo").innerHTML = d.toString();
JavaScript(默认情况下)将以全文本字符串格式输出日期:
Wed Mar 25 2015 08:00:00 GMT+0800 (中国标准时间)
toUTCString() 方法将日期转换为 UTC 字符串(一种日期显示标准)。
显示为:Mon, 24 Feb 2020 04:57:29 GMT
toDateString() 方法将日期转换为更易读的格式。
显示为:Mon Feb 24 2020
有四种 JavaScript 日期输入格式:
类型 | 实例 |
---|---|
ISO 日期 | “2018-02-19” (国际标准) |
短日期 | “02/19/2018” 或者 “2018/02/19” |
长日期 | “Feb 19 2018” 或者 “19 Feb 2019” |
完整日期 | “Monday February 25 2015” |
日期方法允许您获取并设置日期值(年、月、日、时、分、秒、毫秒)。
日期获取方法
获取方法用于获取日期的某个部分(来自日期对象的信息)。下面是最常用的方法(以字母顺序排序):
方法 | 描述 |
---|---|
getDate() | 以数值返回天(1-31) |
getDay() | 以数值获取周名(0-6) |
getFullYear() | 获取四位的年(yyyy) |
getHours() | 获取小时(0-23) |
getMilliseconds() | 获取毫秒(0-999) |
getMinutes() | 获取分(0-59) |
getMonth() | 获取月(0-11) |
getSeconds() | 获取秒(0-59) |
getTime() | 获取时间(从 1970 年 1 月 1 日至今)返回自 1970 年 1 月 1 日以来的毫秒数 |
UTC 日期方法
UTC 日期方法用于处理 UTC 日期(通用时区日期,Univeral Time Zone dates):
上述方法基础上,在get后面加UTC。
使用“设置日期”方法可以设置日期对象的日期值(年、月、日、小时、分钟、秒、毫秒)。
日期设置方法
设置方法用于设置日期的某个部分。下面是最常用的方法(按照字母顺序排序):
方法 | 描述 |
---|---|
setDate() | 以数值(1-31)设置日(setDate() 方法也可用于将天数添加到日期–d.setDate(d.getDate() + 50) |
setFullYear() | 设置年(可选月和日) |
setHours() | 设置小时(0-23) |
setMilliseconds() | 设置毫秒(0-999) |
setMinutes() | 设置分(0-59) |
setMonth() | 设置月(0-11) |
setSeconds() | 设置秒(0-59) |
setTime() | 设置时间(从 1970 年 1 月 1 日至今的毫秒数) |
比较日期
var today, someday, text;
today = new Date();
someday = new Date();
someday.setFullYear(2049, 0, 16);
if (someday > today) {
text = "今天在 2049 年 1 月 16 日之前";
} else {
text = "今天在 2049 年 1 月 16 日之后";
}
document.getElementById("demo").innerHTML = text;
JavaScript Math 对象允许对数字执行数学任务。
Math 对象方法
方法 | 描述 |
---|---|
abs(x) | 返回 x 的绝对值 |
acos(x) | 返回 x 的反余弦值,以弧度计 |
asin(x) | 返回 x 的反正弦值,以弧度计 |
atan(x) | 以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。 |
atan2(y,x) | 返回从 x 轴到点 (x,y) 的角度 |
ceil(x) | 对 x 进行上舍入 |
cos(x) | 返回 x 的余弦 |
exp(x) | 返回 Ex 的值 |
floor(x) | 对 x 进行下舍入 |
log(x) | 返回 x 的自然对数(底为e) |
max(x,y,z,…,n) | 返回最高值 |
min(x,y,z,…,n) | 返回最低值 |
pow(x,y) | 返回 x 的 y 次幂 |
random() | 返回 0 ~ 1 之间的随机数 |
round(x) | 把 x 四舍五入为最接近的整数 |
sin(x) | 返回 x(x 以角度计)的正弦(以弧度计的角度 = (以度数计的角度) * PI / 180。) |
sqrt(x) | 返回 x 的平方根 |
tan(x) | 返回角的正切 |
Math 属性(常量)
JavaScript 提供了可由 Math 对象访问的 8 个数学常量:
Math.E // 返回欧拉指数(Euler's number)
Math.PI // 返回圆周率(PI)
Math.SQRT2 // 返回 2 的平方根
Math.SQRT1_2 // 返回 1/2 的平方根
Math.LN2 // 返回 2 的自然对数
Math.LN10 // 返回 10 的自然对数
Math.LOG2E // 返回以 2 为底的 e 的对数(约等于 1.414)
Math.LOG10E // 返回以 10 为底的 e 的对数(约等于0.434)
Math 构造器
与其他全局对象不同,Math对象没有构造函数。方法和属性是静态的。
可以在不首先创建Math对象的情况下使用所有方法和属性(常量)。
JavaScript 随机整数
Math.random() 与 Math.floor() 一起使用用于返回随机整数。
一个适当的随机函数
JavaScript 函数始终返回介于 min(包括)和 max(不包括)之间的随机数:
function getRndInteger(min, max) {
return Math.floor(Math.random() * (max - min) ) + min;
}
JavaScript 函数始终返回介于 min 和 max(都包括)之间的随机数:
function getRndInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1) ) + min;
}
JavaScript 布尔(逻辑)代表两个值之一:true 或 false。
Boolean() 函数
可以使用 Boolean() 函数来确定表达式(或变量)是否为真:
Boolean(10 > 9) // 返回 true
所有具有“真实”值的即为 True
100 是 true
3.14 是 true
-15 是 true
任何(非空)字符串是 true
即使字符串 'false' 也是 true
任何表达式(除了零)是 true
所有不具有“真实”值的即为 False
0(零)的布尔值为 false
-0 (负零)的布尔值为 false
""(空值)的布尔值为 false
undefined 的布尔值是 false
null 的布尔值是 false
false 的布尔值(正如您猜到的)是 false
NaN 的布尔值是 false
布尔可以是对象
var x = false;
var y = new Boolean(false);
// typeof x 返回 boolean
// typeof y 返回 object
不要创建布尔对象。它会拖慢执行速度。
new 关键词会使代码复杂化,并产生某些意想不到的结果
比较运算符
比较运算符在逻辑语句中使用,以判定变量或值是否相等。
给定 x = 5,下表中解释了比较运算符:
运算符 | 描述 | 比较 | 返回 |
---|---|---|---|
== | 等于 | x == 8 | false |
x == 5 | true | ||
x == “5” | true | ||
=== | 值相等并且类型相等 | x === 5 | true |
x === “5” | false | ||
!= | 不相等 | x != 8 | true |
!== | 值不相等或类型不相等 | x !== 5 | false |
x !== “5” | true | ||
x !== 8 | true | ||
> | 大于 | x > 8 | false |
< | 小于 | x < 8 | true |
>= | 大于或等于 | x >= 8 | false |
<= | 小于或等于 | x <= 8 | true |
逻辑运算符
逻辑运算符用于判定变量或值之间的逻辑。
给定 x = 6 且 y = 3,下表解释了逻辑运算符:
运算符 | 描述 | 例子 |
---|---|---|
&& | 与 | (x < 10 && y > 1) 为 true |
|| |
或 | (x == 5 || y == 5) 为 false |
! | 非 | !(x == y) 为 true |
条件(三元)运算符
JavaScript 也包含了可基于某些条件向变量赋值的条件运算符。
语法
variablename = (condition) ? value1:value2
var a=(age<18)?"未成年":"成年";
比较不同的类型
比较不同类型的数据也许会出现不可预料的结果。
如果将字符串与数字进行比较,那么在做比较时 JavaScript 会把字符串转换为数值。空字符串将被转换为 0。非数值字符串将被转换为始终为 false 的 NaN。
条件语句
在 JavaScript 中,可使用如下条件语句:
if 语句
使用 if 语句来规定假如条件为 true 时被执行的 JavaScript 代码块。
语法:
if (条件) {
如果条件为 true 时执行的代码
}
else 语句
请使用 else 语句来规定假如条件为 false 时的代码块。
if (条件) {
条件为 true 时执行的代码块
} else {
条件为 false 时执行的代码块
}
else if 语句
使用 else if 来规定当首个条件为 false 时的新条件。
if (条件 1) {
条件 1 为 true 时执行的代码块
} else if (条件 2) {
条件 1 为 false 而条件 2 为 true 时执行的代码块
} else {
条件 1 和条件 2 同时为 false 时执行的代码块
}
switch语句
使用 switch 语句来选择多个需被执行的代码块之一。
switch(表达式) {
case n:
代码块
break;
case n:
代码块
break;
default:
默认代码块
}
代码解释:
break 关键词
如果 JavaScript 遇到 break 关键词,它会跳出 switch 代码块。
此举将停止代码块中更多代码的执行以及 case 测试。
如果找到匹配,并完成任务,则随机中断执行(break)。无需更多测试。
break 能够节省大量执行时间,因为它会“忽略” switch 代码块中的其他代码的执行。
不必中断 switch 代码块中的最后一个 case。代码块在此处会自然结束。
default 关键词
default 关键词规定不存在 case 匹配时所运行的代码。
常见的代码块
有时会需要不同的 case 来使用相同的代码。
case 4 和 5 分享相同的代码块,而 0 和 6 分享另一段代码块:
switch (new Date().getDay()) {
case 4:
case 5:
text = "周末快到了:)";
break;
case 0:
case 6:
text = "今天是周末~";
break;
default:
text = "期待周末!";
}
Switching 的细节
如果多种 case 匹配一个 case 值,则选择第一个 case。
如果未找到匹配的 case,程序将继续使用默认 label。
如果未找到默认 label,程序将继续 switch 后的语句。
严格的比较
Switch case 使用严格比较(===)。
值必须与要匹配的类型相同。
只有操作数属于同一类型时,严格比较才能为 true。
在这个例子中,x 将不匹配:
var x = "0";
switch (x) {
case 0:
text = "Off";
break;
case 1:
text = "On";
break;
default:
text = "No value found";
}
输出:No value found
JavaScript 支持不同类型的循环:
For 循环
for (语句 1; 语句 2; 语句 3) {
要执行的代码块
}
语句 1 在循环(代码块)开始之前执行(可以在语句 1 中初始化多个值(由逗号分隔),还可以省略语句 1)。
语句 2 定义运行循环(代码块)的条件。(可以省略)
语句 3 会在循环(代码块)每次被执行后执行。(可以省略)
For/In 循环
JavaScript for/in 语句遍历对象的属性:
var person = {fname:"Bill", lname:"Gates", age:62};
var text = "";
var x;
for (x in person) {
text += person[x];
}
While 循环
while 循环会一直循环代码块,只要指定的条件为 true。
while (条件) {
要执行的代码块
}
Do/While 循环
do/while 循环是 while 循环的变体。在检查条件是否为真之前,这种循环会执行一次代码块,然后只要条件为真就会重复循环。
do {
要执行的代码块
}
while (条件);
Break 语句
break 语句“跳出”循环,break 语句会中断循环,并继续执行循环之后的代码(如果有)。
Continue 语句
continue 语句中断(循环中)的一个迭代,如果发生指定的条件。然后继续循环中的下一个迭代。
本例跳过值 3 :
for (i = 0; i < 10; i++) {
if (i === 3) { continue; }
text += "数字是 " + i + "
";
}
JavaScript 标签
如需标记 JavaScript 语句,请将标签名和冒号置于语句之前:
label:
statements
break 和 continue 语句是仅有的可“跳出”代码块的 JavaScript 语句。
break labelname;
continue labelname;
continue 语句(不论有无标签引用)只能用于跳过一个迭代。
break 语句,如果没有标签引用,只能用于跳出一个循环或一个 switch。
如果有标签引用,则 break 语句可用于跳出任意代码块:
var cars = ["BMW", "Volvo", "Saab", "Ford"];
list: {
text += cars[0] + "
";
text += cars[1] + "
";
text += cars[2] + "
";
break list;
text += cars[3] + "
";
text += cars[4] + "
";
text += cars[5] + "
";
}
Number() 转换数值,String() 转换字符串,Boolean() 转换布尔值。
constructor 属性
返回所有 JavaScript 变量的构造器函数。
"Bill".constructor // 返回 "function String() { [native code] }"
(3.14).constructor // 返回 "function Number() { [native code] }"
false.constructor // 返回 "function Boolean() { [native code] }"
[1,2,3,4].constructor // 返回 "function Array() { [native code] }"
{name:'Bill', age:62}.constructor // 返回" function Object() { [native code] }"
new Date().constructor // 返回 "function Date() { [native code] }"
function () {}.constructor // 返回 "function Function(){ [native code] }"
可以通过检查 constructor 属性来确定某个对象是否为数组(包含单词 “Array”)/是否为日期(包含单词 “Date”)。
function isArray(myArray) {
return myArray.constructor === Array;
}
function isDate(myDate) {
return myDate.constructor === Date;
}
JavaScript 位运算符
运算符 | 名称 | 描述 |
---|---|---|
& | AND | 如果两位都是 1 则设置每位为 1 |
| |
OR | 如果两位之一为 1 则设置每位为 1 |
^ | XOR | 如果两位只有一位为 1 则设置每位为 1 |
~ | NOT | 反转所有位 |
<< | 零填充左位移 | 通过从右推入零向左位移,并使最左边的位脱落。 |
>> | 有符号右位移 | 通过从左推入最左位的拷贝来向右位移,并使最右边的位脱落。 |
>>> | 零填充右位移 | 通过从左推入零来向右位移,并使最右边的位脱落。 |
JavaScript 使用 32 位按位运算数
上面的例子使用 4 位无符号二进制数。所以 ~ 5 返回 10。
由于 JavaScript 使用 32 位有符号整数,JavaScript 将返回 -6。
00000000000000000000000000000101 (5)
11111111111111111111111111111010 (~5 = -6)
有符号整数使用最左边的位作为减号。
负数是正数的二进制补码加 1。
进制转换
把十进制转换为二进制:
function dec2bin(dec){
return (dec >>> 0).toString(2);
}
把二进制转换为十进制:
function bin2dec(bin){
return parseInt(bin, 2).toString(10);
}
什么是正则表达式?
正则表达式是构成搜索模式(search pattern)的字符序列。
当搜索文本中的数据时,可使用搜索模式来描述搜索的内容。
正则表达式可以是单字符,或者更复杂的模式。
正则表达式可用于执行所有类型的文本搜索和文本替换操作。
语法
/pattern/modifiers;
实例
var patt = /w3school/i;
例子解释:
/w3school/i 是一个正则表达式。
w3school 是模式(pattern)(在搜索中使用)。
i 是修饰符(把搜索修改为大小写不敏感)。
使用字符串方法
在 JavaScript 中,正则表达式常用于两个字符串方法:search() 和 replace()。
search() 方法使用表达式来搜索匹配,然后返回匹配的位置。
replace() 方法返回模式被替换处修改后的字符串。
在字符串方法 search() 中使用正则表达式:
使用正则表达式执行搜索字符串中 "w3school" 的大小写不敏感的搜索:
var str = "Visit W3School";
var n = str.search(/w3school/i);
结果:6
正则表达式修饰符
修饰符可用于大小写不敏感的更全局的搜素:
修饰符 | 描述 |
---|---|
i | 执行对大小写不敏感的匹配。 |
g | 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。 |
m | 执行多行匹配。 |
正则表达式模式
括号用于查找一定范围的字符串:
表达式 | 描述 |
---|---|
[abc] | 查找方括号之间的任何字符。 |
[0-9] | 查找任何从 0 至 9 的数字。 |
(x| y) |
查找由| 分隔的任何选项。 |
元字符(Metacharacter)是拥有特殊含义的字符:
元字符 | 描述 |
---|---|
\d | 查找数字。 |
\s | 查找空白字符。 |
\b | 匹配单词边界。(/\bW3/g–在字符串中单词的开头或结尾处对“W3”进行全局搜索。) |
\uxxxx | 查找以十六进制数 xxxx 规定的 Unicode 字符。 |
Quantifiers 定义量词:
量词 | 描述 |
---|---|
n+ | 匹配任何包含至少一个 n 的字符串。 |
n* |
匹配任何包含零个或多个 n 的字符串。 |
n? | 匹配任何包含零个或一个 n 的字符串。 |
使用 RegExp 对象
在 JavaScript 中,RegExp 对象是带有预定义属性和方法的正则表达式对象。
https://www.w3school.com.cn/jsref/jsref_obj_regexp.asp
使用 test()
test() 是一个正则表达式方法。它通过模式来搜索是否有字符串,然后根据结果返回 true 或 false。
/e/.test("The best things in life are free!");
使用 exec()
通过指定的模式(pattern)搜索字符串,并返回已找到的文本。如果未找到匹配,则返回 null。
try 语句能够测试代码块中的错误。
catch 语句允许处理错误。
throw 语句允许创建自定义错误。
finally 能够执行代码,在 try 和 catch 之后,无论结果如何。
JavaScript try 和 catch
try 语句允许您定义一个代码块,以便在执行时检测错误。
catch 语句允许你定义一个要执行的代码块,如果 try 代码块中发生错误。
JavaScript 语句 try 和 catch 成对出现:
try {
供测试的代码块
}
catch(err) {
处理错误的代码块
}
JavaScript 抛出错误
当发生错误时,JavaScript 通常会停止并产生错误消息。
技术术语是这样描述的:JavaScript 将抛出异常(抛出错误)。
JavaScript 实际上会创建带有两个属性的 Error 对象:name 和 message。
throw 语句
throw 语句允许创建自定义错误。
从技术上讲开发人员能够抛出异常(抛出错误)。
异常可以是 JavaScript 字符串、数字、布尔或对象。
finally 语句
try {
供测试的代码块
}
catch(err) {
处理错误的代码块
}
finally {
无论 try / catch 结果如何都执行的代码块
}
Error 对象
JavaScript 拥有当错误发生时提供错误信息的内置 error 对象。
error 对象提供两个有用的属性:name 和 message。
Error Name Values
error 的 name 属性可返回六个不同的值:
错误名 | 描述 |
---|---|
EvalError | 已在 eval() 函数中发生的错误(更新版本的 JavaScript 不会抛出任何 EvalError。请使用 SyntaxError 代替。) |
RangeError | 已发生超出数字范围的错误 |
ReferenceError | 已发生非法引用 |
SyntaxError | 已发生语法错误 |
TypeError | 已发生类型错误 |
URIError | 在 encodeURI() 中已发生的错误 |
作用域指的是有权访问的变量集合。
JavaScript 函数作用域
在 JavaScript 中有两种作用域类型:
局部 JavaScript 变量
在 JavaScript 函数中声明的变量,会成为函数的局部变量, 局部变量的作用域是局部的:只能在函数内部访问它们。
由于只能在函数内部识别局部变量,因此能够在不同函数中使用同名变量。在函数开始时会创建局部变量,在函数完成时会删除它们。
函数参数也是函数内的局部变量。
全局 JavaScript 变量
函数之外声明的变量,会成为全局变量。
全局变量的作用域是全局的:网页的所有脚本和函数都能够访问它。
在 HTML 中,全局作用域是 window。所有全局变量均属于 window 对象。
JavaScript 变量
在 JavaScript 中,对象和函数也是变量。
作用域决定了从代码不同部分对变量、对象和函数的可访问性。
自动全局
如果为尚未声明的变量赋值,此变量会自动成为全局变量。
myFunction();
// 此处的代码能够使用 carName 变量
function myFunction() {
carName = "porsche";
}
JavaScript 变量的有效期
JavaScript 变量的有效期始于其被创建时。
局部变量会在函数完成时被删除。
全局变量会在关闭页面时被删除。
注意
除非有意为之,否则请勿创建全局变量。
全局变量(或函数)能够覆盖 window 变量(或函数)。
任何函数,包括 window 对象,能够覆盖您的全局变量和函数。
提升(Hoisting)是 JavaScript 将声明移至顶部的默认行为。
JavaScript 声明会被提升
在 JavaScript 中,可以在使用变量之后对其进行声明。
换句话说,可以在声明变量之前使用它。
let 和 const 关键字
用 let 或 const 声明的变量和常量不会被提升!
JavaScript 初始化不会被提升
JavaScript 只提升声明,而非初始化。
例子 1 与例子 2 的结果不相同:
例子 1:
var x = 5; // 初始化 x
var y = 7; // 初始化 y
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y; // 显示 x 和 y
例子 2:
var x = 5; // 初始化 x
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y; // 显示 x 和 y
var y = 7; // 初始化 y
“use strict”; 定义 JavaScript 代码应该以“严格模式”执行。
"use strict" 指令
“use strict” 是 JavaScript 1.8.5 中的新指令(ECMAScript version 5)。
它不算一条语句,而是一段文字表达式,更早版本的 JavaScript 会忽略它。
“use strict”; 的作用是指示 JavaScript 代码应该以“严格模式”执行。
在严格模式中,无法,例如,使用未声明的变量。
声明严格模式
通过在脚本或函数的开头添加 “use strict”; 来声明严格模式。
在脚本开头进行声明,拥有全局作用域(脚本中的所有代码均以严格模式来执行)
"use strict";
x = 3.14; // 这会引发错误,因为 x 尚未声明
在函数中声明严格模式,拥有局部作用域(只有函数中的代码以严格模式执行):
x = 3.14; // 这不会引发错误
myFunction();
function myFunction() {
"use strict";
y = 3.14; // 这会引发错误
}
为什么使用严格模式?
严格模式使我们更容易编写“安全的” JavaScript。
严格模式把之前可接受的“坏语法”转变为真实的错误。
举例来说,在普通的 JavaScript 中,错打变量名会创建新的全局变量。在严格模式中,此举将抛出错误,这样就不可能意外创建全局变量。
在普通 JavaScript 中,如果向不可写属性赋值,开发者不会得到任何错误反馈。
在严格模式中,向不可写的、只能读取的、不存在的属性赋值,或者向不存在的变量或对象赋值,将抛出错误。
严格模式中不允许的事项
JavaScript this 关键词指的是它所属的对象。
它拥有不同的值,具体取决于它的使用位置:
方法中的 this
在对象方法中,this 指的是此方法的“拥有者”。
单独的 this
在单独使用时,拥有者是全局对象,因此 this 指的是全局对象。在浏览器窗口中,全局对象是 [object Window]。
函数中的 this(默认)
在 JavaScript 函数中,函数的拥有者默认绑定 this。
因此,在函数中,this 指的是全局对象 [object Window]。
函数中的 this(严格模式)
JavaScript 严格模式不允许默认绑定。
因此,在函数中使用时,在严格模式下,this 是未定义的(undefined)。
事件处理程序中的 this
在 HTML 事件处理程序中,this 指的是接收此事件的 HTML 元素。
显式函数绑定
call() 和 apply() 方法是预定义的 JavaScript 方法。
它们都可以用于将另一个对象作为参数调用对象方法。
var person1 = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var person2 = {
firstName:"Bill",
lastName: "Gates",
}
person1.fullName.call(person2); // 会返回 "Bill Gates"
ES2015 引入了两个重要的 JavaScript 新关键词:let 和 const。
这两个关键字在 JavaScript 中提供了块作用域(Block Scope)变量(和常量)。
JavaScript 块作用域
通过 var 关键词声明的变量没有块作用域。
在块 {} 内声明的变量可以从块之外进行访问。
在 ES2015 之前,JavaScript 是没有块作用域的。
可以使用 let 关键词声明拥有块作用域的变量。
在块 {} 内声明的变量无法从块外访问。
重新声明变量
使用 var 关键字重新声明变量会带来问题。
在块中重新声明变量也将重新声明块外的变量:
var x = 10;
// 此处 x 为 10
{
var x = 6;
// 此处 x 为 6
}
// 此处 x 为 6
使用 let 关键字重新声明变量可以解决这个问题。
在块中重新声明变量不会重新声明块外的变量:
var x = 10;
// 此处 x 为 10
{
let x = 6;
// 此处 x 为 6
}
// 此处 x 为 10
循环作用域
在循环中使用 var:
var i = 7;
for (var i = 0; i < 10; i++) {
// 一些语句
}
// 此处,i 为 10
在循环中使用 let:
let i = 7;
for (let i = 0; i < 10; i++) {
// 一些语句
}
// 此处 i 为 7
在第一个例子中,在循环中使用的变量使用 var 重新声明了循环之外的变量。
在第二个例子中,在循环中使用的变量使用 let 并没有重新声明循环外的变量。
如果在循环中用 let 声明了变量 i,那么只有在循环内,变量 i 才是可见的。
函数作用域
在函数内声明变量时,使用 var 和 let 很相似。
它们都有函数作用域
全局作用域
如果在块外声明声明,那么 var 和 let 也很相似。
它们都拥有全局作用域
HTML 中的全局变量
使用 JavaScript 的情况下,全局作用域是 JavaScript 环境。
在 HTML 中,全局作用域是 window 对象。
通过 var 关键词定义的全局变量属于 window 对象。
通过 let 关键词定义的全局变量不属于 window 对象。
重新声明
允许在程序的任何位置使用 var 重新声明 JavaScript 变量。
在相同的作用域,或在相同的块中,通过 let 重新声明一个 var 变量是不允许的。
在相同的作用域,或在相同的块中,通过 let 重新声明一个 let 变量是不允许的。
在相同的作用域,或在相同的块中,通过 var 重新声明一个 let 变量是不允许的。
在不同的作用域或块中,通过 let 重新声明变量是允许的。
提升
通过 var 声明的变量会提升到顶端,可以在声明变量之前就使用它。
通过 let 定义的变量不会被提升到顶端。
在声明 let 变量之前就使用它会导致 ReferenceError。
变量从块的开头一直处于“暂时死区”,直到声明为止。
通过 const 定义的变量与 let 变量类似,但不能重新赋值。
const PI = 3.141592653589793;
PI = 3.14; // 会出错
PI = PI + 10; // 也会出错
块作用域
在块作用域内使用 const 声明的变量与 let 变量相似,,x 在块中声明,不同于在块之外声明的 x。
在声明时赋值
JavaScript const 变量必须在声明时赋值:
const PI = 3.14159265359;
不是真正的常数
关键字 const 有一定的误导性。
它没有定义常量值。它定义了对值的常量引用。
因此,我们不能更改常量原始值,但我们可以更改常量对象的属性。
原始值
如果我们将一个原始值赋给常量,我们就不能改变原始值。
常量对象可以更改
// 可以创建 const 对象:
const car = {type:"porsche", model:"911", color:"Black"};
// 可以更改属性:
car.color = "White";
// 可以添加属性:
car.owner = "Bill";
但是无法重新为常量对象赋值:
const car = {type:"porsche", model:"911", color:"Black"};
car = {type:"Volvo", model:"XC60", color:"White"}; // ERROR
常量数组可以更改
可以更改常量数组的元素,同常量对象相似。
重新声明
在同一作用域或块中,不允许将已有的 var 或 let 变量重新声明或重新赋值给 const。
在同一作用域或块中,为已有的 const 变量重新声明声明或赋值是不允许的
在另外的作用域或块中重新声明 const 是允许的
提升
通过 const 定义的变量不会被提升到顶端。const 变量不能在声明之前使用。
JavaScript 调试器
查找编程代码中的错误被称为代码调试。
调试并不简单。但幸运地是,所有现代浏览器都有内置的调试器。
内置的调试器可打开或关闭,强制将错误报告给用户。
通过调试器,也可以设置断点(代码执行被中断的位置),并在代码执行时检查变量。
通常通过 F12 键启动浏览器中的调试器,然后在调试器菜单中选择“控制台”。
console.log() 方法
如果浏览器支持调试,那么可以使用 console.log() 在调试窗口中显示 JavaScript 的值。
设置断点
在调试窗口中,可在 JavaScript 代码中设置断点。
在每个断点中,JavaScript 将停止执行,以使能够检查 JavaScript 的值。
在检查值之后,可以恢复代码执行。
debugger 关键词
debugger 关键词会停止 JavaScript 的执行,并调用(如果有)调试函数。
这与在调试器中设置断点的功能是一样的。
如果调试器不可用,debugger 语句没有效果。
JavaScript 代码约定
代码约定(Coding conventions)指的是编程的样式指导方针。这些原则大体上包括:
运算符周围的空格
请始终在运算符( = + - * / )周围以及逗号之后添加空格。
代码缩进
请始终使用对代码块缩进使用 4 个空格,请不要对缩进使用制表符。不同的编辑器对 tab 的解释也不尽相同。
语句规则
对象规则
行长度小于 80
为了提高可读性,请避免每行的长度超过 80 个字符。
如果 JavaScript 语句超过一行的长度,换行的最佳位置是运算符或逗号之后。
命名约定
文件扩展名
HTML 文件应该使用 .html 扩展名(而非 .htm)。
CSS 文件应该使用 .css 扩展名。
JavaScript 文件应该使用 .js 扩展名。
使用小写文件名
大多数 web 服务器(Apache、Unix)对文件名的大小写敏感:
london.jpg 无法视作 London.jpg 进行访问。
其他 web 服务器(微软的 IIS)对大小写不敏感:
london.jpg 能够以 London.jpg 或 london.jpg 来访问。
如果混合使用大小写,则必须严格保持连续和一致。
如果将站点从大小写不敏感的服务器转移至对大小写敏感的服务器,即使这种小错误也可能破坏网站。
为了避免这些问题,请始终使用小写文件名(如果可能)。
请避免全局变量、new、===、eval()
避免全局变量
请尽量少地使用全局变量。
它包括所有的数据类型、对象和函数。
全局变量和函数可被其他脚本覆盖。
请使用局部变量替代,并学习如何使用闭包。
始终声明局部变量
所有在函数中使用的变量应该被声明为局部变量。
局部变量必须通过 var 关键词来声明,否则它们将变成全局变量。
严格模式不允许未声明的变量。
在顶部声明
把所有声明放在每段脚本或函数的顶部。
初始化变量
在声明变量时对其进行初始化是个好习惯。
请不要声明数值、字符串或布尔对象
请始终将数值、字符串或布尔值视作原始值。而非对象。
如果把这些类型声明为对象,会拖慢执行速度,并产生讨厌的副作用。
请勿使用 new Object()
使用 === 比较
== 比较运算符总是在比较之前进行类型转换(以匹配类型)。
=== 运算符会强制对值和类型进行比较。
使用 Parameter Defaults
如果调用函数时缺少一个参数,那么这个缺失参数的值会被设置为 undefined。
undefined 值会破坏您的代码。为参数设置默认值是一个好习惯。
用 default 来结束 switch
使用使用 default 来结束的 switch 语句。
避免使用 eval()
eval() 函数用于将文本作为代码来允许。在几乎所有情况下,都没有必要使用它。
因为允许任意代码运行,它同时也意味着安全问题。
码约定确保质量:
运算符周围的空格
请始终在运算符( = + - * / )周围以及逗号之后添加空格。
代码缩进
请始终使用对代码块缩进使用 4 个空格,请不要对缩进使用制表符。不同的编辑器对 tab 的解释也不尽相同。
语句规则
对象规则
行长度小于 80
为了提高可读性,请避免每行的长度超过 80 个字符。
如果 JavaScript 语句超过一行的长度,换行的最佳位置是运算符或逗号之后。
命名约定
文件扩展名
HTML 文件应该使用 .html 扩展名(而非 .htm)。
CSS 文件应该使用 .css 扩展名。
JavaScript 文件应该使用 .js 扩展名。
使用小写文件名
大多数 web 服务器(Apache、Unix)对文件名的大小写敏感:
london.jpg 无法视作 London.jpg 进行访问。
其他 web 服务器(微软的 IIS)对大小写不敏感:
london.jpg 能够以 London.jpg 或 london.jpg 来访问。
如果混合使用大小写,则必须严格保持连续和一致。
如果将站点从大小写不敏感的服务器转移至对大小写敏感的服务器,即使这种小错误也可能破坏网站。
为了避免这些问题,请始终使用小写文件名(如果可能)。
请避免全局变量、new、===、eval()
避免全局变量
请尽量少地使用全局变量。
它包括所有的数据类型、对象和函数。
全局变量和函数可被其他脚本覆盖。
请使用局部变量替代,并学习如何使用闭包。
始终声明局部变量
所有在函数中使用的变量应该被声明为局部变量。
局部变量必须通过 var 关键词来声明,否则它们将变成全局变量。
严格模式不允许未声明的变量。
在顶部声明
把所有声明放在每段脚本或函数的顶部。
初始化变量
在声明变量时对其进行初始化是个好习惯。
请不要声明数值、字符串或布尔对象
请始终将数值、字符串或布尔值视作原始值。而非对象。
如果把这些类型声明为对象,会拖慢执行速度,并产生讨厌的副作用。
请勿使用 new Object()
使用 === 比较
== 比较运算符总是在比较之前进行类型转换(以匹配类型)。
=== 运算符会强制对值和类型进行比较。
使用 Parameter Defaults
如果调用函数时缺少一个参数,那么这个缺失参数的值会被设置为 undefined。
undefined 值会破坏您的代码。为参数设置默认值是一个好习惯。
用 default 来结束 switch
使用使用 default 来结束的 switch 语句。
避免使用 eval()
eval() 函数用于将文本作为代码来允许。在几乎所有情况下,都没有必要使用它。
因为允许任意代码运行,它同时也意味着安全问题。