1.JavaScript简介
JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。
在1995年时,由Netscape公司的Brendan Eich,在网景导航者浏览器上首次设计实现而成。因为Netscape与Sun合作,Netscape管理层希望它外观看起来像Java,因此取名为JavaScript。
发展初期,JavaScript的标准并未确定,同期有Netscape的JavaScript,微软的JScript和CEnvi的ScriptEase三足鼎立。1997年,在ECMA(欧洲计算机制造商协会-European Computer Manufactures Association)的协调下,由Netscape、Sun、微软、Borland组成的工作组确定统一标准:ECMA-262—定义一种名为ECMAScript(发音“ek-ma-script”)的新脚本语言的标准。
虽然JavaScript和ECMAScript通常被人们用来表达相同的含义,但是JavaScript的含义却比ECMAS-262中规定的要多得多。一个完整的JavaScript 实现应该有下列三个不同的部分组成
- 核心(ECMAScript)
- 文档对象模型(DOM)
- 浏览器对象模型(BOM)
ECMA-262标准规定了这门语言的下列组成部分:
- 语法
- 类型
- 语句
- 关键字
- 保留字
- 操作符
- 对象
ECMAScript就是对实现该标准规定的各个方面内容的语言的描述。JavaScript实现了ECMAScript。
在html中使用JavaScript
HTML 中的脚本必须位于 <script> 与 </script> 标签之间。
脚本可被放置在 HTML 页面的 <body> 和 <head> 部分中。
外部的 JavaScript
也可以把脚本保存到外部文件中。外部文件通常包含被多个网页使用的代码。外部 JavaScript 文件的文件扩展名是 .js。
如需使用外部文件,请在 <script> 标签的 "src" 属性中设置该 .js 文件:
<!DOCTYPE html>
<html>
<body>
<script src="myScript.js"></script>
</body>
</html>
JavaScript 操作符
JavaScript语言有多种类型的运算符:
类型 | 实例 | 描述 |
---|---|---|
赋值,算术和位运算符 | = + - * / | 在 JS 运算符中描述 |
条件,比较及逻辑运算符 | == != < > | 在 JS 比较运算符中描述 |
JavaScript 注释
JavaScript 不会执行注释。
我们可以添加注释来对 JavaScript 进行解释,或者提高代码的可读性。
单行注释以 // 开头。
JavaScript 多行注释
多行注释以/* 开始,以 */ 结尾。
HTML注释符号是以 **** 结束的。如果在此注释符号内编写 JavaScrip t脚本,对于不支持 JavaScript 的浏览器,将会把编写的 JavaScript 脚本作为注释处理。
<!-- 这是一个注释 -->
css的注释是以 /* 开始,以 */ 结尾。
JavaScript 字面量
在编程语言中,一般固定值称为字面量,如 3.14。
如:数字(Number)字面量 可以是整数或者是小数
3.14
1001
字符串(String)字面量 可以使用单引号或双引号:
"John Doe"
'John Doe'
数组(Array)字面量 定义一个数组:
[40, 100, 1, 5, 25, 10]
对象(Object)字面量 定义一个对象:
{firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"}
函数(Function)字面量 定义一个函数:
function myFunction(a, b) { return a * b;}
JavaScript 变量
在编程语言中,变量用于存储数据值。
JavaScript 使用关键字 var 来定义变量, 使用等号来为变量赋值:
var x;
x = 5;
变量的命名规则
- 变量必须以字母开头
- 变量也能以 $ 和 _ 符号开头(不过我们不推荐这么做)
- 变量名称对大小写敏感(y 和 Y 是不同的变量)
JavaScript let 和 const
ES2015(ES6) 新增加了两个重要的 JavaScript 关键字: let 和 const。
let 声明的变量只在 let 命令所在的代码块内有效。
const 声明一个只读的常量,一旦声明,常量的值就不能改变。
JavaScript 数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。
Object类型
ECMAScript中的对象其实就是一组数据和功能的集合。对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。
var o = new Object();
Object类型是所有它的实例的基础。换句话说,Object类型所具有的任何属性和方法也同样存在于更具体的对象中。
Object的每个实例都具有下列属性和方法
- constructor:保存着用于创建当前对象的函数。对于上面的例子而言,构造函数(constructor)就是Object()。
- hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中是否存在。其中,作为参数的属性名(propertyName)必须以字符串的形式指定(例如:0.hasOwnProperty("name"))。
- isPrototypeOf(object):用于检查传入的对象是否是当前对象的原型。
- propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。参数的属性名必须以字符串的形式指定。
- toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。
- toString():返回对象的字符串表示。
- valueOf():返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同。
JavaScript 拥有动态类型
JavaScript 拥有动态类型。这意味着相同的变量可用作不同的类型:
var x; // x 为 undefined
var x = 5; // 现在 x 为数字
var x = "John"; // 现在 x 为字符串
Undefined 和 Null
Undefined 这个值表示变量不含有值。
可以通过将变量的值设置为 null 来清空变量。
声明变量类型
当您声明新变量时,可以使用关键词 "new" 来声明其类型:
var carname=new String;
var x= new Number;
var y= new Boolean;
var cars= new Array;
var person= new Object;
JavaScript 变量均为对象。当您声明一个变量时,就创建了一个新的对象。
JavaScript 对象
JavaScript 对象是拥有属性和方法的数据。
对象定义
你可以使用字符来定义和创建 JavaScript 对象:
var person = {
firstName:"John",
lastName:"Doe",
age:50,
eyeColor:"blue"
};
对象属性
可以说 "JavaScript 对象是变量的容器"。
但是,我们通常认为 "JavaScript 对象是键值对的容器"。
键值对通常写法为 name : value (键与值以冒号分割)。
键值对在 JavaScript 对象通常称为 对象属性。
访问对象属性
你可以通过两种方式访问对象属性:
person.lastName;
person["lastName"];
对象方法
对象的方法定义了一个函数,并作为对象的属性存储。
对象方法通过添加 () 调用 (作为一个函数)。
该实例访问了 person 对象的 fullName() 方法:
name = person.fullName();
如果你要访问 person 对象的 fullName 属性,它将作为一个定义函数的字符串返回:
name = person.fullName;
访问对象方法
你可以使用以下语法创建对象方法:
methodName : function() { code lines }
你可以使用以下语法访问对象方法:
objectName.methodName()
通常 fullName() 是作为 person 对象的一个方法, fullName 是作为一个属性。
JavaScript 函数
JavaScript 函数语法
函数就是包裹在花括号中的代码块,前面使用了关键词 function来声明,后跟一组参数以及函数体
function functionname()
{
执行代码
}
当调用该函数时,会执行函数内的代码。
调用带参数的函数
在调用函数时,您可以向其传递值,这些值被称为参数。
这些参数可以在函数中使用。
您可以发送任意多的参数,由逗号 (,) 分隔:
myFunction(argument1,argument2)
当您声明函数时,请把参数作为变量来声明:
function myFunction(var1,var2)
{
代码
}
变量和参数必须以一致的顺序出现。第一个变量就是第一个被传递的参数的给定的值,以此类推。
<p>点击这个按钮,来调用带参数的函数。</p>
<button onclick="myFunction('Harry Potter','Wizard')">点击这里</button>
<script>
function myFunction(name,job){
alert("Welcome " + name + ", the " + job);
}
</script>
带有返回值的函数
ECMAScript中函数在定义时不必指定是否有返回值。
有时,我们会希望函数将值返回调用它的地方。
通过使用 return 语句就可以实现。
在使用 return 语句时,函数会停止执行,并返回指定的值。
语法
function myFunction()
{
var x=5;
return x;
}
上面的函数会返回值 5。
理解参数
ECMAScript函数的参数与大多数其他语言中函数的参数有所不同。ECMAScript函数不介意传递进来多少个参数,也不在乎传递进来的参数是什么数据类型。就是说,即使你定义的函数只接受两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个,三个、甚至不传。之所以会这样,原因是ECMAScript中的参数在内部是用一个数组来表示的。函数接收到的始终都是这个数组,而不关心数组中包含那些参数。实际上,在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数。
其实,arguments对象只是与数组类似(它并不是啊Array的实例),因为可以使用方括号访问它的每一个元素,使用length属性来确定传进来多少个参数。例如函数:
function sayHi(name,message) {
alert("Hello" + name + "," + message);
}
可以使用下面这样重写,即不显式的使用命名参数:
function sayHi() {
alert("Hello" + arguments[0] + "," + arguments[1]);
}
这个重写后的函数中不包含命名参数。虽然没有使用name和message标识符但是函数的功能依旧。这个事实说明了ECMAScript函数的一个重要特点:命名的参数只提供便利,但不是必需的。另外,在命名参数方面,其他语言可能需要事先创建一个函数签名,而将来的调用必须与该签名一致。但是在ECMAScript中,没有这些条条框框,解析器不会验证命名参数。
没有重载
ECMAScript函数不能像传统意义上那样实现重载。而在其他语言(如Java)中,可以为一个函数编写连个定义,只要这两个定义的标签不同即可。由于ECMAScript函数没有签名,因为其参数是由包含0或多个值的数组来表示的。而没后函数签名,真正的重载是不可能做到的。
如果在ECMAScript中定义了连个名字相同的函数,则该名字只属于后定义的函数。
函数声明与函数表达式
解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数的声明,并使其在执行任何代码之前可用(可以访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会被解释执行。
alert(sum(10,10));
function sum(num1,num2) {
return num1 + num2;
}
以上代码可以正常运行。因为在代码开始执行之前,解析器就已经通过一个名为函数声明提升的过程,读取并将函数声明添加到执行环境中。
如果把函数声明改为等价的函数表达式,就会在执行期间导致错误。
alert(sum(10,10)); //执行到此报错 “unexpected identifier”
var sum = function(num1,num2) {
return num1 + num2;
}
函数内部属性
在函数内部,有两个特殊的对象:arguments和this 。其中,arguments是一个类数组对象,包含这传入函数中的所有参数。虽然arguments的主要用途是保存函数的参数,但这个对象还有一个名叫callee的属性,该属性是一个指针,执行拥有这个arguments对象的函数。请看下面这个非常金典的阶乘函数。
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * factorial(num - 1);
}
}
如上代码所示,在函数有名字,而且名字以后也不会变的情况下,这样定义没有问题。但问题是这个函数的执行与函数名factorial紧紧耦合在了一起。为了消除这种紧密耦合的现象,可以像下面这样使用arguments.callee。
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
函数内部的另一个特殊对象是this,this引用的是函数执行的环境对象。
函数的属性和方法
ECMAScript中函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:length和prototype。其中length属性表示函数希望接收的命名参数的个数。
每个函数都包含两个飞继承而来的方法:apply()和call()。这两个方法的用途是在特定作用域中调用函数,实际上等于设置函数体内this对象的值。
JavaScript 字符串
字符串可以存储一系列字符,如 "John Doe"。
字符串可以是插入到引号中的任何字符。你可以使用单引号或双引号
你可以使用索引位置来访问字符串中的每个字符:
var carname = "Volvo XC60";
var character = carname[7];
字符串的索引从 0 开始,这意味着第一个字符索引值为 [0],第二个为 [1], 以此类推。
特殊字符
反斜杠是一个转义字符。 转义字符将特殊字符转换为字符串字符:
转义字符 (\) 可以用于转义撇号,换行,引号,等其他特殊字符。
下表中列举了在字符串中可以使用转义字符转义的特殊字符:
代码 | 输出 |
---|---|
' | 单引号 |
" | 双引号 |
\\ | 反斜杠 |
\n | 换行 |
\r | 回车 |
\t | tab(制表符) |
\b | 退格符 |
\f | 换页符 |
字符串可以是对象
通常, JavaScript 字符串是原始值,可以使用字符创建: var firstName = "John"
但我们也可以使用 new 关键字将字符串定义为一个对象: var firstName = new String("John")
var x = "John";
var y = new String("John");
(x === y) // 结果为 false,因为 x 是字符串,y 是对象
=== 为绝对相等,即数据类型与值都必须相等。
字符串属性和方法
原始值字符串,如 "John", 没有属性和方法(因为他们不是对象)。
原始值可以使用 JavaScript 的属性和方法,因为 JavaScript 在执行方法和属性时可以把原始值当作对象。
字符串属性
属性 | 描述 |
---|---|
constructor | 返回创建字符串属性的函数 |
length | 返回字符串的长度 |
prototype | 允许您向对象添加属性和方法 |
字符串方法
方法 | 描述 |
---|---|
charAt() | 返回指定索引位置的字符 |
charCodeAt() | 返回指定索引位置字符的 Unicode 值 |
concat() | 连接两个或多个字符串,返回连接后的字符串 |
fromCharCode() | 将 Unicode 转换为字符串 |
indexOf() | 返回字符串中检索指定字符第一次出现的位置 |
lastIndexOf() | 返回字符串中检索指定字符最后一次出现的位置 |
localeCompare() | 用本地特定的顺序来比较两个字符串 |
match() | 找到一个或多个正则表达式的匹配 |
replace() | 替换与正则表达式匹配的子串 |
search() | 检索与正则表达式相匹配的值 |
slice() | 提取字符串的片断,并在新的字符串中返回被提取的部分 |
split() | 把字符串分割为子字符串数组 |
substr() | 从起始索引号提取字符串中指定数目的字符 |
substring() | 提取字符串中两个指定的索引号之间的字符 |
toLocaleLowerCase() | 根据主机的语言环境把字符串转换为小写,只有几种语言(如土耳其语)具有地方特有的大小写映射 |
toLocaleUpperCase() | 根据主机的语言环境把字符串转换为大写,只有几种语言(如土耳其语)具有地方特有的大小写映射 |
toLowerCase() | 把字符串转换为小写 |
toString() | 字符串对象值 |
toUpperCase() | 把字符串转换为大写 |
trim() | 移除字符串首尾空白 |
valueOf() | 返回某个字符串对象的原始值 |
变量、作用域
基本类型和引用类型的值
变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象。
在将一个值赋值给变量时,解析器必须确定这个值是基本类型还是引用类型值。5种基本数据类型:Undefined、Null、Boolean、Number、和String。这5种基本数据类型是按值访问的,因为可以 操作保存在变量中的实际的值。
引用类型的值是保存在内存中的对象。与其他语言不同,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是操作对象的引用而不是实际的对象。
动态属性
定义基本类型和引用类型值的方式是类似的:创建一个变量并为该变量赋值。但是这个值保存到变量中后,对不同类型的值可以执行的操作则大不相同。对于引用类型的值,我们可以为其添加属性和方法,也可以改变和删除其属性和方法。
但是我们不能给基本数据类型的值添加属性,尽管这样做不会导致任何的错误。比如:
var name = "jack";
name.age = 27;
alert(name.age); //Undefined
复制变量的值
除了保存的方式不同之外,从一个变量像另一个变量复制基本数据类型值和引用类型值时,也存在不同。如果从一个变量像另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。
当从一个变量像另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份到新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上引用同一个对象。一次改变其中一个变量,就会影响另一个变量。
传递参数
EMCAScript中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。
没有块级作用域
JavaScript没有块级作用域。在其他类C语言中,由花括号封闭的代码块都有自己的作用域,因而支持根据条件来定义变量。例如下面的代码在JavaScript中并不会得到想象中的结果:
if (true) {
var color = "blue";
}
alert(color); //blue
这里是在一个if语句中定义了变量color。如果是C、C++,color会在if语句执行完毕后被销毁。但在JavaScript中,if语句中的变量声明会将变量添加到当前的执行环境(在这里是全局环境)中。在使用for语句时尤其要牢记这一差异,例如:
for (var i = 0; i < 10; i++) {
doSomething(i);
}
alert(i); //10
对于有块级作用域的语言来说,for语句初始化变量的表达式所定义的变量,只会存在于循环的环境之中。而对于JavaScript来说,for语句创建的变量i即使for循环执行结束后,也依旧存在于循环外部的执行环境中。
1.声明变量
使用var 声明的变量会自动被添加到最近的环境中,在函数内部,最接近的环境就是函数的局部环境;在with语句中,最接近的环境是函数环境。如果初始化变量时没有使用var 变量,该变量会自动被添加到全局环境。如下所示:
function add (num1,num2) {
var sum = num1 + num2;
return sum;
}
var result = add(10,20);
alert(sum); //由于sum不是有效的变量,因此会导致错误
以上代码中的函数add()定义了一个名为sum的局部变量,该变量包含加法操作的结果。虽然结果值从函数中返回了,但变量sum在函数外部是访问不到的。如果省略var关键字名,那么当add()执行完毕后,sum也将可以访问到:
function add (num1,num2) {
sum = num1 + num2;
return sum;
}
var result = add(10,20);
alert(sum); //30
这个例子中的变量sum在被初始化赋值时没有使用var关键字。于是,当调用完add()之后,添加到全局环境中的变量sum将继续存在;即使函数已经执行完毕,后面的代码依旧可以访问它。
JavaScript Array(数组) 对象
什么是数组?
数组对象是使用单独的变量名来存储一系列的值。
数组的每一项可以保存任何类型的数据。也就是说,可以用数组的第一个位置来保存字符串,第二个位置保存对象,第三个位置保存数值。
创建一个数组
创建一个数组,有三种方法。
下面的代码定义了一个名为 myCars的数组对象:
1: 常规方式:
var myCars=new Array();
myCars[0]="Saab";
myCars[1]="Volvo";
myCars[2]="BMW";
2: 简洁方式:
var myCars=new Array("Saab","Volvo","BMW");
3: 字面:
var myCars=["Saab","Volvo","BMW"];
访问数组
通过指定数组名以及索引号码,你可以访问某个特定的元素。
以下实例可以访问myCars数组的第一个值:
var name=myCars[0];
以下实例修改了数组 myCars 的第一个元素:
myCars[0]="Opel";
在读取和设置数组的值时,要使用方括号并提供相应值的基于0的数子索引,如下所示:
var colors = ["red","blue","green"];
alert(colors[0]); //显示第一项
colors[2] = "black"; //修改第三项
colors[3] = "brown"; //新增第四项
如果索引小于数组中的项数,则返回对应项的值。如果设置的索引超过了数组现有的项数,数组就会自动增加到该索引值加1的长度(就这个例子而言,索引是3,因此数组长度就是4)。
数组的length属性不是只读的。因此,通过设置这个属性,可以从数组的末尾移除项或向数组中添加新项。
var colors = ["red","blue","green"];
colors.length = 2;
alert(colors[2]); //Undefined
var colors = ["red","blue","green"];
colors.length = 4;
alert(colors[3]); //Undefined
栈方法
ECMASCript数组也提供了一种让数组的行为类似于其他数据结构的方法。具体来说,数组可以表现的像栈一样。栈是一种 LIFO(Last-In-First-Out,后进先出)的数据结构。而栈中的插入和移除,只发生在一个位置--栈的顶部。ECMASCript为数组专门提供了push()和pop()方法,以便实现类似栈的行为。
push()方法可以接受任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。而pop()方法则从数组末尾移除最后一项,减少数组的length值,然后返回移除的项。
var color = new Array();
var count = colors.push("red","green"); //推入两项
alert(count); //2
var item = colors.pop(); //取得自后一项
alert(item); //green
alert(colors.length); //1
队列方法
栈数据结构的访问规则是LIFO(后进先出),而队列数据结构的访问规则是FIFO(First-In-First-Out,先进先出);队列在列表的末端添加项,从列表的前端移除项。shift()它能够移除数组中饿第一个项并返回该项,同时数组长度减1。结合使用shift()和push()方法,可以像队列一样使用数组。
var color = new Array();
var count = colors.push("red","green"); //推入两项
alert(count); //2
count = colors.push("black"); //推入另一项
alert(count); //3
var item = colors.shift(); //取得第一项
alert(item); //red
alert(colors.length); //2
ECMASCript还为数组提供了unshift()方法。unshift()于shift()的用途相反:能在数组前端添加任意个项并返回数组长度。
重排序方法
数组中已经存在的两个直接用来排序的方法:reverse()和sort()。
reverse()方法会反转数组的顺序。
var values = [1,2,3,6,5,9,0];
values.reverse();
alert(values); //0,9,5,6,3,2,1
默认情况下,sort()方法按升序排列数组项,sort()方法会调用每个数组项的toString()转型方法,然后表得到的字符串,以确定如何排序。即使数组中的每一项都是数值,sort()方法比较的依然是字符串,如下所示:
var values = [0,1,5,10,15];
values.sort();
alert(values); //0,1,10,15,5
sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。
比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,相等返回0,第一个参数应该位于第二个之后则返回一个正数。以下是一个简单的比较函数:
function compare(value1,value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1
} else {
return 0;
}
}
这个比较函数可以适用于大多数数据类型,只要将其作为参数传递给sort()方法即可
var values = [0,1,5,10,15];
values.sort(compare);
alert(values); //0,1,5,10,15
操作方法
concat()方法:创建当前数组的一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。
var colors = ["red","blue","green"];
var colors2 = colors.concat("yellow",["black","brown"]);
alert(colors); // red ,green,blue
alert(colors2); // red ,green,blue,yellow,black,brown
slice()方法:能够基于当前数组中的一或多个项创建一个新数组。该方法可以接收一或两个参数,既要返回项的起始和结束位置。在只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。
var colors = ["red","green","blue","yellow","purple"];
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,4);
alert(colors2); // green,blue,yellow,purple
alert(colors2); // green,blue,yellow
splice()方法有多种用法,主要用途是像数组的中部插入项,但使用这种方法的方式则有如下3种。
-
删除:可以删除任意数量的项,只需指定2个参数:要删除的第一项的位置和要删除的项数。
例如,splice(0,2)会删除数组中的前两项。 - 插入:可以像指定位置插入任意数量的项,只需要提供3个参数:起始位置、0(要删除的项数)和要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。例如,splice(2,0,"red","green")会从当前数组的位置2开始插入字符串"red"和"green"。
-
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需要指定3个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必于删除的项数相等。例如,splice(2,1,"red","green")会删除当前数组位置2的项,然后在从位置2开始插入字符串"red"和"green"。
splice()始终都会返回一个数组,该数组中包含从原始数组中删除的项(没有删除则返回一个空数组)。
var colors = ["red","green","blue"];
var removed = colors.splice(0,1); //删除第一项
alert(colors); // green,blue
alert(removed); // red
removed = colors.splice(1,0,"yellow","orange"); //从位置1开始插入两项
alert(colors); // green,yellow,orange,blue
alert(removed); // 返回一个空数组
removed = colors.splice(1,1,"red","purple"); //插入两项,删除一项
alert(colors); // green,red,purple,orange,blue
alert(removed); //yellow,返回数组中只包含一项
位置方法
ECMAScript5为数组实例添加了两个位置方法:indexOf()和lastIndexOf()。这两个方法都接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中indexOf()方法从数组的开头位置0开始向后查找,lastIndexOf()方法则从数组的末尾开始向前查找。
这两个方法都返回要查找的项在数组中的位置,或在没找到的情况下返回-1.在比较第一个参数与数组中的每一项时,会使用全等操作符;要求查找的项必须严格相等。
var numbers = [1,2,3,4,5,4,3,2,1];
alert(numbers.indexOf(4)); //3
alert(numbers.lastIndexOf(4)); //5
alert(numbers.indexOf(4,4)); //5
alert(numbers.lastIndexOf(4,4)); //3
var person = {name: "Nicholas"};
var people = [{name: "Nicholas"}];
var morePeople = [person];
alert(people.indexOf(person)); //-1
alert(morePeople.indexOf(person)); //0
迭代方法
ECMAScript5为数组定义了5个迭代方法。每个方法都接收两个参数:要在每一项上运行的函数和运行该函数的作用域对象(可选的)--影响this的值。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。以下是5个迭代方法的作用。
- every():对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true 。
- filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组。
- forEach():对数组中的每一项运行给定函数,这个方法没有返回值。
- map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
- some():对数组中的每一项运行给定函数,如果该函数对任意一项返回true,则返回true。
以上方法都不会修改数组中包含的值。
在这些方法中,最相似的是every()和some(),它们都用于查询数组中的项是否满足某个条件。
var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item, index, array){
return (item > 2);
});
alert(everyResult); // false
var someResult = numbers.some(function (item,index,array) {
return (item > 2);
});
alert(someResult); // true
filter()函数实例:
var numbers = [1,2,3,4,5,4,3,2,1];
var filterResult = numbers.filter(function(item, index, array){
return (item > 2);
});
alert(filterResult); // [3,4,5,4,3]
map() 函数实例:
var numbers = [1,2,3,4,5,4,3,2,1];
var mapResult = numbers.filter(function(item, index, array){
return item * 2;
});
alert(mapResult); // [2,4,6,8,10,8,6,4,2]
最后的forEach(),它只是对数组中的每一项运行传入的函数。本质上与使用for循环迭代数组一样。
var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
//执行某些操作
});
归并方法
ECMAScript5还新增了两个归并数组的方法:reduce()和reduceRigth()。这两个方法都会迭代数组的所有项,然后构建一个最终返回值。其中reduce()方法从数组的第一项开始,逐个遍历到最后。而reduceRigth()则从数组的最后一项开始,向前遍历到第一项。
这两个方法都接收两个参数:一个在每一项上调用的函数和作为归并基础的初始值(可选的)。传给reduce()和educeRigth()的函数接收4个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。
使用reduce()方法可以执行求数组中所有值之和的操作,比如:
var values = [1,2,3,4,5];
var sum = values.reduce(function (prev, ucr, index, array) {
return prev + cur;
});
alert(sum); // 15
JavaScript 运算符
JavaScript 算术运算符
y=5,下面的表格解释了这些算术运算符:
运算符 | 描述 | 例子 | x 运算结果 | y 运算结果 | 在线实例 |
---|---|---|---|---|---|
+ | 加法 | x=y+2 | 7 | 5 | 实例 » |
- | 减法 | x=y-2 | 3 | 5 | 实例 » |
* | 乘法 | x=y*2 | 10 | 5 | 实例 » |
/ | 除法 | x=y/2 | 2.5 | 5 | 实例 » |
% | 取模(余数) | x=y%2 | 1 | 5 | 实例 » |
++ | 自增 | x=++y | 6 | 6 | 实例 » |
x=y++ | 5 | 6 | 实例 » | ||
-- | 自减 | x=--y | 4 | 4 | 实例 » |
x=y-- | 5 | 4 | 实例 » |
JavaScript 赋值运算符
赋值运算符用于给 JavaScript 变量赋值。
给定 x=10 和 y=5,下面的表格解释了赋值运算符:
运算符 | 例子 | 等同于 | 运算结果 | 在线实例 |
---|---|---|---|---|
= | x=y | x=5 | 实例 » | |
+= | x+=y | x=x+y | x=15 | 实例 » |
-= | x-=y | x=x-y | x=5 | 实例 » |
*= | x*=y | x=x*y | x=50 | 实例 » |
/= | x/=y | x=x/y | x=2 | 实例 » |
%= | x%=y | x=x%y | x=0 | 实例 » |
用于字符串的 + 运算符
+ 运算符用于把文本值或字符串变量加起来(连接起来)。
如需把两个或多个字符串变量连接起来,请使用 + 运算符。
如需把两个或多个字符串变量连接起来,请使用 + 运算符:
txt1="What a very";
txt2="nice day";
txt3=txt1+txt2;
txt3 运算结果如下:
What a verynice day
对字符串和数字进行加法运算
两个数字相加,返回数字相加的和,如果数字与字符串相加,返回字符串,如下实例:
x=5+5;
y="5"+5;
z="Hello"+5;
x,y, 和 z 输出结果为:
10
55
Hello5
规则: 如果把数字与字符串相加,结果将成为字符串!
JavaScript 比较 和 逻辑运算符
比较和逻辑运算符用于测试 true 或者 false。
比较运算符在逻辑语句中使用,以测定变量或值是否相等。
x=5,下面的表格解释了比较运算符:
运算符 | 描述 | 比较 | 返回值 | 实例 |
---|---|---|---|---|
== | 等于 | x==8 | false | 实例 » |
x==5 | true | 实例 » | ||
=== | 绝对等于(值和类型均相等) | x==="5" | false | 实例 » |
x===5 | true | 实例 » | ||
!= | 不等于 | x!=8 | true | 实例 » |
!== | 不绝对等于(值和类型有一个不相等,或两个都不相等) | x!=="5" | true | 实例 » |
x!==5 | false | 实例 » | ||
> | 大于 | x>8 | false | 实例 » |
< | 小于 | x<8 | true | 实例 » |
>= | 大于或等于 | x>=8 | false | 实例 » |
<= | 小于或等于 | x<=8 | true | 实例 » |
运算符
逻辑运算符用于测定变量或值之间的逻辑。
给定 x=6 以及 y=3,下表解释了逻辑运算符:
运算符 | 描述 | 例子 |
---|---|---|
&& | and | (x < 10 && y > 1) 为 true |
|| | or | (x==5 || y==5) 为 false |
! | not | !(x==y) 为 true |
条件语句
通常在写代码时,您总是需要为不同的决定来执行不同的动作。您可以在代码中使用条件语句来完成该任务。
在 JavaScript 中,我们可使用以下条件语句:
- if 语句 - 只有当指定条件为 true 时,使用该语句来执行代码
- if...else 语句 - 当条件为 true 时执行代码,当条件为 false 时执行其他代码
- if...else if....else 语句- 使用该语句来选择多个代码块之一来执行
- switch 语句 - 使用该语句来选择多个代码块之一来执行
JavaScript for 循环
avaScript 支持不同类型的循环:
- for - 循环代码块一定的次数
- for/in - 循环遍历对象的属性
- while - 当指定的条件为 true 时循环指定的代码块
- do/while - 同样当指定的条件为 true 时循环指定的代码块
JavaScript Break 和 Continue 语句
break 语句用于跳出循环。
continue 用于跳过循环中的一个迭代。
JavaScript typeof, null, 和 undefined
typeof 操作符
你可以使用 typeof 操作符来检测变量的数据类型。
typeof "John" // 返回 string
typeof 3.14 // 返回 number
typeof NaN // 返回 number
typeof false // 返回 boolean
typeof [1,2,3,4] // 返回 object
typeof {name:'John', age:34} // 返回 object
typeof new Date() // 返回 object
typeof function () {} // 返回 function
typeof myCar // 返回 undefined (如果 myCar 没有声明)
typeof null // 返回 object
在JavaScript中,数组是一种特殊的对象类型。 因此 typeof [1,2,3,4] 返回 object。
请注意:
- NaN 的数据类型是 number
- 数组(Array)的数据类型是 object
- 日期(Date)的数据类型为 object
- null 的数据类型是 object
- 未定义变量的数据类型为 undefined
如果对象是 JavaScript Array 或 JavaScript Date ,我们就无法通过 typeof 来判断他们的类型,因为都是 返回 object。
null
在 JavaScript 中 null 表示 "什么都没有"。
null是一个只有一个值的特殊类型。表示一个空对象引用。
用 typeof 检测 null 返回是object。
你可以设置为 null 来清空对象:
var person = null; // 值为 null(空), 但类型为对象
你可以设置为 undefined 来清空对象:
var person = undefined; // 值为 undefined, 类型为 undefined
undefined
在 JavaScript 中, undefined 是一个没有设置值的变量。
typeof 一个没有值的变量会返回 undefined。
var person; // 值为 undefined(空), 类型是undefined
任何变量都可以通过设置值为 undefined 来清空。 类型为 undefined.
person = undefined; // 值为 undefined, 类型是undefined
undefined 和 null 的区别
null 和 undefined 的值相等,但类型不等:
typeof undefined // undefined
typeof null // object
null === undefined // false
null == undefined // true
JavaScript 类型转换
Number() 转换为数字, String() 转换为字符串, Boolean() 转化为布尔值。
检测数据类型:typeof 与 instanceof
typeof 用以获取一个变量或者表达式的类型,typeof 一般只能返回如下几个结果:
number,boolean,string,function(函数),object(NULL,数组,对象),undefined。
instanceof
可通过 instanceof 操作符来判断对象的具体类型,语法格式:
var result = objectName instanceof objectType
返回布尔值,如果是指定类型返回 true,否则返回 false
JavaScript 错误 - throw、try 和 catch
JavaScript try 和 catch
try 语句允许我们定义在执行时进行错误测试的代码块。
catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
JavaScript 语句 try 和 catch 是成对出现的。
语法
try {
//在这里运行代码
} catch(err) {
//在这里处理错误
}
在下面的例子中,我们故意在 try 块的代码中写了一个错字。
catch 块会捕捉到 try 块中的错误,并执行代码来处理它。
var txt="";
function message()
{
try {
adddlert("Welcome guest!");
} catch(err) {
txt="本页有一个错误。\n\n";
txt+="错误描述:" + err.message + "\n\n";
txt+="点击确定继续。\n\n"; alert(txt);
}
}
Throw 语句
throw 语句允许我们创建自定义错误。
正确的技术术语是:创建或抛出异常(exception)。
如果把 throw 与 try 和 catch 一起使用,那么您能够控制程序流,并生成自定义的错误消息。
语法
throw exception
异常可以是 JavaScript 字符串、数字、逻辑值或对象。
本例检测输入变量的值。如果值是错误的,会抛出一个异常(错误)。catch 会捕捉到这个错误,并显示一段自定义的错误消息:
function myFunction() {
var message, x;
message = document.getElementById("message"); message.innerHTML = "";
x = document.getElementById("demo").value;
try {
if(x == "") throw "值为空";
if(isNaN(x)) throw "不是数字";
x = Number(x);
if(x < 5) throw "太小";
if(x > 10) throw "太大";
} catch(err) {
message.innerHTML = "错误: " + err;
}
}
JavaScript 变量提升
JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。
JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。
以下两个实例将获得相同的结果:
实例 1
x = 5; // 变量 x 设置为 5
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x; // 在元素中显示 x
var x; // 声明 x
实例 2
var x; // 声明 x
x = 5; // 变量 x 设置为 5
elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x; // 在元素中显示 x
要理解以上实例就需要理解 "hoisting(变量提升)"。
变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。
注意:JavaScript 只有声明的变量会提升,初始化的不会。
JavaScript 严格模式(use strict)
"use strict" 的目的是指定代码在严格条件下执行。
严格模式下你不能使用未声明的变量。
"use strict";
x = 3.14; // 报错 (x 未定义)
严格模式的限制
不允许使用未声明的变量
不允许删除变量或对象。
"use strict";
var x = 3.14;
delete x; // 报错
- 不允许删除函数。
"use strict";
function x(p1, p2) {};
delete x; // 报错
不允许变量重名
不允许使用八进制:
"use strict";
var x = 010; // 报错