在 HTML
中使用 JavaScript
- 在包含外部
JavaScript
文件时,必须将src
属性设置为指向相应文件的URL
。而这个文件既可
以是与包含它的页面位于同一个服务器上的文件,也可以是其他任何域中的文件。 - 所有
<script>
元素都会按照它们在页面中出现的先后顺序依次被解析。在不使用defer
和
async
属性的情况下,只有在解析完前面<script>
元素中的代码之后,才会开始解析后面
<script>
元素中的代码。 - 由于浏览器会先解析完不使用
defer
属性的<script>
元素中的代码,然后再解析后面的内容,
所以一般应该把<script>
元素放在页面最后,即主要内容后面,</body>
标签前面。 - 使用
defer
属性可以让脚本在文档完全呈现之后再执行。延迟脚本总是按照指定它们的顺序执行。 - 使用
async
属性可以表示当前脚本不必等待其他脚本,也不必阻塞文档呈现。不能保证异步脚
本按照它们在页面中出现的顺序执行。 - 另外,使用
<noscript>
元素可以指定在不支持脚本的浏览器中显示的替代内容。但在启用了脚本
的情况下,浏览器不会显示<noscript>
元素中的任何内容。
变量
//定义变量时要使用var操作符,后跟变量名,如下所示:
var message;
//设置变量的值,如下所示:
var message = "hi";
//定义多个变量
var message = "hi",
found = false,
age = 29;
注意:即用
var
操作符定义的变量将成为定义该变量的作用域中的局部变量。也就是说,
如果在函数中使用var
定义一个变量,那么这个变量在函数退出后就会被销毁。
数据变量
Undefined
类型
Undefined
类型只有一个值,即特殊的 undefined
。在使用 var
声明变量但未对其加以初始化时,
这个变量的值就是 undefined
,例如:
var message;
alert(message == undefined); //true
对未声明的变量执行 typeof
操作符同样也会返回 undefined
值。
// 下面这个变量并没有声明
// var age
alert(typeof age); // "undefined"
Null
类型
Null
类型是第二个只有一个值的数据类型,这个特殊的值是 null
。从逻辑角度来看,null
值表
示一个空对象指针,而这也正是使用 typeof
操作符检测 null
值时会返回"object
"的原因.
var car = null;
alert(typeof car); // "object"
Boolean
类型
Boolean
类型只有两个字面值:true
和 false
。这两个值与数字值不是一回事,因此 true
不一定等于 1,而 false
也不一定等于 0。以下是为变量赋Boolean
类型值的例子:
var found = true;
var lost = false;
需要注意的是,Boolean
类型的字面值 true
和 false
是区分大小写的。也就是说,True
和 False
(以及其他的混合大小写形式)都不是 Boolean
值,只是标识符。
转换为对应的 Boolean
值
可以调用转型函数 Boolean()
,如下例所示:
var message = "Hello world!";
var messageAsBoolean = Boolean(message);
Number
类型
Number
类型可用来表示整数和浮点数值。
var intNum = 55; // 整数
//八进制字面值的第一位必须是零(0),然后是八进制数字序列(0~7)。
var octalNum1 = 070; // 八进制的 56
var octalNum2 = 079; // 无效的八进制数值——解析为 79
var octalNum3 = 08; // 无效的八进制数值——解析为 8
//十六进制字面值的前两位必须是 0x,后跟任何十六进制数字(0~9 及 A~F)。其中,字母 A~F可以大写,也可以小写。
var hexNum1 = 0xA; // 十六进制的 10
var hexNum2 = 0x1f; // 十六进制的 31
数值范围
ECMAScript
能够表示的最小数值保存在Number.MIN_VALUE
中——在大多数浏览器中,这个值是 5e-324;能够表示的最大数值保存在Number.MAX_VALUE
中——在大多数浏览器中,这个值是 1.7976931348623157e+308。如果某次计算的结果得到了一个超出JavaScript
数值范围的值,如果这个数值是负数,则会被转换成-Infinity
(负无穷),如果这个数值是正数,则会被转
换成Infinity
(正无穷)。
要想确定一个数值是不是有穷的,可以使用isFinite()
函数。这个函数在参数位于最小与最大数值之间时会返回true
。
NaN
NaN
,即非数值(Not a Number
)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)。例如,在其他编程语言中,任何数值除以 0都会导致错误,从而停止代码执行。但在 ECMAScript
中,任何数值除以 0会返回 NaN
,因此不会影响其他代码的执行。
任何涉及
NaN
的操作(例如NaN/10
)都会返回NaN
。
NaN
与任何值都不相等,包括NaN
本身。
isNaN()
函数可以帮我们确定参数是否“不是数值”。
alert(isNaN(NaN)); //true
alert(isNaN(10)); //false(10 是一个数值)
alert(isNaN("10")); //false(可以被转换成数值 10)
alert(isNaN("blue")); //true(不能转换成数值)
alert(isNaN(true)); //false(可以被转换成数值 1)
数值转换
有 3 个函数可以把非数值转换为数值:Number()
、parseInt()
和 parseFloat()
。第一个函数,即转型函数 Number()
可以用于任何数据类型,而另两个函数则专门用于把字符串转换成数值。
1. Number()
函数的转换规则如下。
- 如果是
Boolean
值,true
和false
将分别被转换为 1 和 0。 - 如果是数字值,只是简单的传入和返回。
- 如果是
null
值,返回 0。 - 如果是
undefined
,返回 NaN。 - 如果是字符串,遵循下列规则:
- 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即"1"
会变成 1,"123"会变成 123,而"011"会变成 11(注意:前导的零被忽略了); - 如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(同样,也会忽
略前导零); - 如果字符串中包含有效的十六进制格式,例如"0xf",则将其转换为相同大小的十进制整
数值; - 如果字符串是空的(不包含任何字符),则将其转换为 0;
- 如果字符串中包含除上述格式之外的字符,则将其转换为
NaN
。 - 如果是对象,则调用对象的
valueOf()
方法,然后依照前面的规则转换返回的值。如果转换
的结果是NaN
,则调用对象的toString()
方法,然后再次依照前面的规则转换返回的字符
串值。
var num1 = Number("Hello world!"); //NaN
var num2 = Number(""); //0
var num3 = Number("000011"); //11
var num4 = Number(true); //1
2. parseInt()
函数在转换字符串时,更多的是看其是否符合数值模式。它会忽略字符串前面的空格,直至找到第一个非空格字符。如果第一个字符不是数字字符或者负号,parseInt()
就会返回 NaN
;
var num1 = parseInt("1234blue"); // 1234
var num2 = parseInt(""); // NaN
var num3 = parseInt("0xA"); // 10(十六进制数)
var num4 = parseInt(22.5); // 22
var num5 = parseInt("070"); // 56(八进制数)
var num6 = parseInt("70"); // 70(十进制数)
var num7 = parseInt("0xf"); // 15(十六进制数)
//如果知道要解析的值是十六进制格式的字符串,那么指定基数 16 作为第二个参数,可以保证得到正确的结果,例如:
var num = parseInt("0xAF", 16); //175
**3. parseFloat()
**也是从第一个字符(位置 0)开始解析每个字符。而且也是一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止。也就是说,字符串中的第一个小数点是有效的,而第二个小数点就是无效的了,因此它后面的字符串将被忽略。
var num1 = parseFloat("1234blue"); //1234 (整数)
var num2 = parseFloat("0xA"); //0
var num3 = parseFloat("22.5"); //22.5
var num4 = parseFloat("22.34.5"); //22.34
var num5 = parseFloat("0908.5"); //908.5
var num6 = parseFloat("3.125e7"); //31250000
String
类型
String
类型用于表示字符串。字符串可以由双引号(")或单引号(’)表示。ECMAScript 中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量
转换为字符串
- 调用被转换数据类型的
toString()
方法,该方法不会影响到原变量,只会将转换的结果返回。但是null
和undefined
没有toString()
方法
var age = 11;
var ageAsString = age.toString(); // 字符串"11"
var found = true;
var foundAsString = found.toString(); // 字符串"true"
2.在不知道要转换的值是不是 null
或 undefined
的情况下,还可以使用转型函数 String()
,这个
函数能够将任何类型的值转换为字符串。
String()
函数遵循下列转换规则:
- 如果值有
toString()
方法,则调用该方法(没有参数)并返回相应的结果; - 如果值是
null
,则返回"null"; - 如果值是
undefined
,则返回"undefined"。
var value1 = 10;
var value2 = true;
var value3 = null;
var value4;
alert(String(value1)); // "10"
alert(String(value2)); // "true"
alert(String(value3)); // "null"
alert(String(value4)); // "undefined"
Object
类型
Object
类型,即对象其实就是一组数据和功能的集合。
//新建对象
var obj = new Object();
//添加对象属性
obj.name = "Name";
obj.gender = "Man/Woman";
obj.age = "Number";
//读取对象属性
console.log(obj.age);
console.log(obj);
//修改对象属性
obj.name = "English Name"
//删除对象属性
delete obj.gender;
变量的存储特点
- 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中;
- 从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本;
- 引用类型的值是对象,保存在堆内存中;
- 包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针;
- 从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象;
- 确定一个值是哪种基本类型可以使用 typeof 操作符,而确定一个值是哪种引用类型可以使用instanceof 操作符。
位操作符
按位非(NOT)
按位非操作符由一个波浪线(~)表示,执行按位非的结果就是返回数值的反码。按位非操作的本质:操作数的负值减 1。
var num1 = 25; // 二进制 00000000000000000000000000011001
var num2 = ~num1; // 二进制 11111111111111111111111111100110
alert(num2); // -26
按位与(AND)
按位与操作符由一个和号字符(&)表示,从本质上讲,按位与操作就是将两个数值的每一位对齐,然后根据下表中的规则,对相同位置上的两个数执行 AND 操作:
按位或(OR)
按位或操作符由一个竖线符号(|)表示,同样也有两个操作数。按位或操作遵循下面这个真值表。
按位异或(XOR)
按位异或操作符由一个插入符号(^)表示,也有两个操作数。以下是按位异或的真值表。
左移
左移操作符由两个小于号(<<)表示,这个操作符会将数值的所有位向左移动指定的位数。例如,如果将数值 2(二进制码为 10)向左移动 5 位,结果就是 64(二进制码为 1000000),代码如下所示:
var oldValue = 2; // 等于二进制的 10
var newValue = oldValue << 5; // 等于二进制的 1000000,十进制的 64
注意,左移不会影响操作数的符号位。换句话说,如果将2 向左移动 5 位,结果将是 64,而非 64。
有符号的右移
有符号的右移操作符由两个大于号(>>)表示,这个操作符会将数值向右移动,但保留符号位(即
正负号标记)。有符号的右移操作与左移操作恰好相反,即如果将 64 向右移动 5 位,结果将变回 2:
var oldValue = 64; // 等于二进制的 1000000
var newValue = oldValue >> 5; // 等于二进制的 10 ,即十进制的 2
无符号右移
无符号右移操作符由 3 个大于号(>>>)表示,这个操作符会将数值的所有 32 位都向右移动。对正
数来说,无符号右移的结果与有符号右移相同。仍以前面有符号右移的代码为例,如果将 64 无符号右
移 5 位,结果仍然还是 2:
var oldValue = 64; // 等于二进制的 1000000
var newValue = oldValue >>> 5; // 等于二进制的 10 ,即十进制的 2
语句
for-in
语句
for-in
语句是一种精准的迭代语句,可以用来枚举对象的属性。对象中有几个属性,循环就会执行几次,每次执行时,会将对象中的一个属性名字赋值给变量以下是 for-in
语句的语法:
var person = {fname:"John", lname:"Doe", age:25};
var text = "";
var x;
for (x in person) {
text += person[x] + " ";
}
// text 输出结果为:John Doe 25
for(var n in obj){
console.log('属性名:'+n);
console.log('属性值:'+n);
}
label
语句
使用 label
语句可以在代码中添加标签,以便将来使用。以下是 label
语句的语法:
label: statement
start: for (var i=0; i < count; i++) {
alert(i);
}
这个例子中定义的 start
标签可以在将来由 break
或 continue
语句引用。加标签的语句一般都
要与 for
语句等循环语句配合使用。
with语句
with
语句的作用是将代码的作用域设置到一个特定的对象中。with
语句的语法如下:
with (expression) statement;
定义 with
语句的目的主要是为了简化多次编写同一个对象的工作,如下面的例子所示:
var qs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href;
上面几行代码都包含 location
对象。如果使用 with
语句,可以把上面的代码改写成如下所示:
with(location){
var qs = search.substring(1);
var hostName = hostname;
var url = href;
}
由于大量使用
with
语句会导致性能下降,同时也会给调试代码造成困难,因此在开发大型应用程序时,不建议使用with
语句。
函数
通过函数可以封装任意多条语句,而且可以在任何地方、任何时候调用执行。
//创建函数对象(一般不用)
var fun = new Function("console.log('函数1');");
//调用函数
fun();
//使用函数声明来创建函数
function sum(a,b){
var c = a+b;
return c;
}
//调用
var d = sum(10,11);
console.log(d);
//使用函数表达式创建函数
var fun3 = function(){
console.log('匿名函数');
};
//调用
fun3();
理解参数
ECMAScript
函数的参数与大多数其他语言中函数的参数有所不同。ECMAScript
函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型。没有传递值的命名参数将自动被赋予 undefined
值。
作用域
全局作用域
直接编写在
script
标签中的JS代码,都在全局作用域,全局作用域在页面打开时创建,在页面关闭时销毁。在全局作用域中,有一个全局对象window
,它代表的是一个浏览器的窗口,由浏览器创建,可直接使用。在全局作用域中,创建的变量都会作为window
对象的属性保存,创建的函数都会作为window
对象的方法保存。全局作用域中的变量是全局变量,在页面的任意位置都可以访问到。
函数作用域
调用函数时创建函数作用域,函数执行完毕后销毁。每调用一次创建一个新的函数作用域,他们之间相互独立。在函数作用域中可访问到全局作用域的变量,反之不可以。在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用,没有则向上一级作用域中寻找,直到找到全局作用域,若依然没有则会报错。在函数中访问全局变量可使用
window
对象。