一、流程控制语句
程序都是自上向下的顺序执行的,
通过流程控制语句可以改变程序执行的顺序,或者反复的执行某一段的程序。
1.条件分支语句
1.1 if语句
语法一: if(条件表达式)
{ 语句... }
执行流程:
if语句执行时,会先对条件表达式进行求值判断,
如果值为true,则执行if后的语句
如果值为false,则不执行
1.2 else-if语句
语法二:
if(条件表达式){
语句...
}else{
语句...
}
执行流程:
if…else语句执行时,会对条件表达式进行求值判断,
- 如果值为true,则执行if后的语句
- 如果值为false,则执行else后的语句
1.3 多else-if语句
语法三:
if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else{
语句...
}
执行流程
if…else if…else语句执行时,会自上至下依次对条件表达式进行求值判断,
- 如果判断结果为true,则执行当前if后的语句,执行完成后语句结束。
- 如果判断结果为false,则继续向下判断,直到找到为true的为止。
- 如果所有的条件表达式都是false,则执行else后的语句
switch语句
语法:
switch(条件表达式){
case 表达式:
语句...
break;
case 表达式:
语句...
break;
default:
语句...
break;
}
执行流程:
switch…case…语句在执行时,会依次将case后的表达式的值和switch后的表达式的值进行全等比较,
- 如果比较结果为false,则继续向下比较。如果比较结果为true,则从当前case处开始向下执行代码。
- 如果所有的case判断结果都为false,则从default处开始执行代码。
2.循环语句
通过循环语句可以反复执行某些语句多次
while循环
语法:
while(条件表达式){
语句...
}
执行流程:
while语句在执行时,会先对条件表达式进行求值判断,
- 如果判断结果为false,则终止循环
- 如果判断结果为true,则执行循环体
循环体执行完毕,继续对条件表达式进行求值判断,依此类推
2.1 do…while循环
语法:
do{
语句…
}while(条件表达式)
执行流程
do…while在执行时,会先执行do后的循环体,然后在对条件表达式进行判断,
如果判断判断结果为false,则终止循环。
如果判断结果为true,则继续执行循环体,依此类推
和while的区别:
while:先判断后执行
do…while: 先执行后判断
do…while可以确保循环体至少执行一次。
2.2 for循环
语法:
for(①初始化表达式 ; ②条件表达式 ; ④更新表达式){
③语句...
}
执行流程:
- 首先执行①初始化表达式,初始化一个变量
- 然后对②条件表达式进行求值判断,如果为false则终止循环
- 如果判断结果为true,则执行③循环体
- 循环体执行完毕,执行④更新表达式,对变量进行更新。
- 更新表达式执行完毕重复②
2.3 死循环
while(true){
}
for(;;){
}
二、对象(Object)
- 对象是JS中的引用数据类型
- 对象是一种复合数据类型,在对象中可以保存多个不同数据
- 类型的属性
使用typeof检查一个对象时,会返回object
1.对象的分类
1.1内建对象
- 由ES标准中定义的对象,在任何的ES的实现中都可以使用
- 比如:Math String Number Boolean Function Object….
1.2.宿主对象
- 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
- 比如 BOM DOM
1.3.自定义对象
- 由开发人员自己创建的对象
2.创建对象
方式一:
var obj = new Object();
方式二:
var obj = {};
3.向对象中添加属性
语法:
对象.属性名 = 属性值;
对象[“属性名”] = 属性值; //这种方式能够使用特殊的属性名
对象的属性名没有任何要求,不需要遵守标识符的规范,但是在开发中,尽量按照标识符的要求去写。
属性值也可以任意的数据类型。
4.读取对象中的属性
语法:
对象.属性名
对象[“属性名”] //“属性名”
可以使字符串常量,也可以是字符串变量
如果读取一个对象中没有的属性,它不会报错,而是返回一个undefined
5.删除对象中的属性
语法:
delete 对象.属性名
delete 对象[“属性名”]
6.遍历
使用in检查对象中是否含有指定属性
语法:
”属性名” in 对象
- 如果在对象中含有该属性,则返回true
- 如果没有则返回false
循环遍历对象自身的和继承的可枚举属性(不含Symbol属性).
var obj = {'0':'a','1':'b','2':'c'};
for(var i in obj) {
console.log(i,":",obj[i]);
}
使用对象字面量,在创建对象时直接向对象中添加属性
语法:
var obj = {
属性名:属性值,
属性名:属性值,
属性名:属性值
}
基本数据类型和引用数据类型
基本数据类型
String
Number
Boolean
Null
Undefined
引用数据类型
Object
基本数据类型的数据,变量是直接保存的它的值。
变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
引用数据类型的数据,变量是保存的对象的引用(内存地址)。
如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
比较两个变量时,对于基本数据类型,比较的就是值,
对于引用数据类型比较的是地址,地址相同才相同
三、函数(Function)
函数也是一个对象,也具有普通对象的功能(能有属性)
函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码
使用typeof检查一个函数时会返回function
1.创建函数
函数声明
function 函数名([形参1,形参2...形参N]){
语句...
}
函数表达式
var 函数名 = function([形参1,形参2...形参N]){
语句...
};
2.调用函数
语法:函数对象([实参1,实参2…实参N]);
fun() sum() alert() Number() parseInt()
当我们调用函数时,函数中封装的代码会按照编写的顺序执行
3.立即执行函数
函数定义完,立即被调用,这种函数叫做立即执行函数
立即执行函数往往只会执行一次
(function(a,b){
console.log("a = "+a);
console.log("b = "+b);
})(123,456);
4.遍历对象
for(var v in obj){
document.write("property:name ="+v+"value="+obj[v]+"<br/>" );
}
5.形参和实参
形参:形式参数
- 定义函数时,可以在()中定义一个或多个形参,形参之间使用,隔开
- 定义形参就相当于在函数内声明了对应的变量但是并不赋值,
- 形参会在调用时才赋值。
实参:实际参数
- 调用函数时,可以在()传递实参,传递的实参会赋值给对应的形参,
- 调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值。
- 如果实参的数量大于形参,多余实参将不会赋值,
- 如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined
6.返回值
就是函数执行的结果
使用return 来设置函数的返回值。
语法:return 值;
该值就会成为函数的返回值,可以通过一个变量来接收返回值
- return后边的代码都不会执行,一旦执行到return语句时,函 数将会立刻退出。
- return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象。
- 如果return后不跟值,或者是不写return则函数默认返回undefined。
7.break、continue和return
break 退出循环
continue 跳过当次循环
return 退出函数
参数,函数的实参也可以是任意的数据类型。
8.方法(method)
可以将一个函数设置为一个对象的属性,
当一个对象的属性是一个函数时,
我们称这个函数是该对象的方法。
对象.方法名();
函数名()
函数的属性和方法
call()
apply()
这两个方法都是函数对象的方法需要通过函数对象来调用
通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this
不同的是call是直接传递函数的实参而apply需要将实参封装到一个数组中传递
8.1 arguments
arguments和this类似,都是函数中的隐含的参数
arguments是一个类数组元素,它用来封装函数执行过程中的实参
所以即使不定义形参,也可以通过arguments来使用实参
arguments中有一个属性callee表示当前执行的函数对象
8.2 this(调用函数的那个对象)
this是函数的上下文对象,根据函数的调用方式不同会执向不同的对象
- 以函数的形式调用时,this是window
- 以方法的形式调用时,this是调用方法的对象
- 以构造函数的形式调用时,this是新建的那个对象
- 使用call和apply调用时,this是指定的那个对象
- 在全局作用域中this代表window
9.作用域
作用域简单来说就是一个变量的作用范围。
在JS中作用域分成两种:
9.1 全局作用域
直接在script标签中编写的代码都运行在全局作用域中
全局作用域在打开页面时创建,在页面关闭时销毁。
全局作用域中有一个全局对象window,window对象由浏览器提供,
可以在页面中直接使用,它代表的是整个的浏览器的窗口。
- 在全局作用域中创建的变量都会作为window对象的属性保存
- 在全局作用域中创建的函数都会作为window对象的方法保存
- 在全局作用域中创建的变量和函数可以在页面的任意位置访问。
- 在函数作用域中也可以访问到全局作用域的变量。
- 尽量不要在全局中创建变量
9.2 函数作用域
函数作用域是函数执行时创建的作用域,每次调用函数都会创建一个新的函数作用域。
函数作用域在函数执行时创建,在函数执行结束时销毁。
在函数作用域中创建的变量,不能在全局中访问。
当在函数作用域中使用一个变量时,它会先在自身作用域中寻找,
如果找到了则直接使用,如果没有找到则到上一级作用域中寻找,
如果找到了则使用,找不到则继续向上找,一直会
变量的声明提前
在全局作用域中,使用var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值。
所以我们可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。
在函数作用域中,也具有该特性,使用var关键字声明的变量会在函数所有的代码执行前被声明,
如果没有使用var关键字声明变量,则变量会变成全局变量
函数的声明提前
在全局作用域中,使用函数声明创建的函数(function fun(){}),会在所有的代码执行之前被创建,
也就是我们可以在函数声明前去调用函数,但是使用函数表达式(var fun = function(){})创建的函数没有该特性
在函数作用域中,使用函数声明创建的函数,会在所有的函数中的代码执行之前就被创建好了。
9.3 this(上下文对象)
我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。
使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。
指向当前对象
this的不同的情况:
- 以函数的形式调用时,this是window
- 以方法的形式调用时,this就是调用方法的对象
- 以构造函数的形式调用时,this就是新创建的对象
9.4 构造函数
构造函数是专门用来创建对象的函数
一个构造函数我们也可以称为一个类
通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例
通过同一个构造函数创建的对象,我们称为一类对象
构造函数就是一个普通的函数,只是他的调用方式不同,
如果直接调用,它就是一个普通函数
如果使用new来调用,则它就是一个构造函数
例子:
function Person(name , age , gender){
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = function(){
alert(this.name);
};
}
构造函数的执行流程:
- 创建一个新的对象
- 将新的对象作为函数的上下文对象(this)
- 执行函数中的代码
- 将新建的对象返回
instanceof 用来检查一个对象是否是一个类的实例
语法:
对象 instanceof 构造函数
如果该对象时构造函数的实例,则返回true,否则返回false
Object是所有对象的祖先,所以任何对象和Object做instanceof都会返回true
枚举对象中的属性
for…in
语法:
for(var 属性名 in 对象){
}
for…in语句的循环体会执行多次,对象中有几个属性就会执行几次,
每次讲一个属性名赋值给我们定义的变量,我们可以通过它来获取对象中的属性
10.※原型(prototype)
所有的 JavaScript 对象都会从一个 prototype(原型对象)中继承属性和方法:
Date 对象从 Date.prototype 继承。
Array 对象从 Array.prototype 继承
Person 对象从 Person.prototype 继承。
所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。
JavaScript 对象有一个指向一个原型对象的链。
创建一个函数以后,解析器都会默认在函数中添加一个数prototype
prototype属性指向的是一个对象,这个对象我们称为原型对象。
当函数作为构造函数使用,它所创建的对象中都会有一个隐含的属性执行该原型对象。
这个隐含的属性可以通过对象.__proto__来访问。
原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。
我们可以将对象中共有的属性和方法统一添加到原型对象中,
这样我们只需要添加一次,就可以使所有的对象都可以使用。
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
Date 对象, Array 对象, 以及 Person 对象从 Object.prototype 继承。
添加属性和方法
使用 prototype 属性就可以给对象的构造函数添加新的属性和方法。
有的时候我们想要在所有已经存在的对象添加新的属性或方法。
另外,有时候我们想要在对象的构造函数中添加属性或方法。
使用 prototype 属性就可以给对象的构造函数添加新的属性:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
}
Person.prototype.nationality = “English”;
当然我们也可以使用 prototype 属性就可以给对象的构造函数添加新的方法:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
}
Person.prototype.name = function() {
return this.firstName + " " + this.lastName;
};
hasOwnProperty()
这个方法可以用来检查对象自身中是否含有某个属性
语法:
对象.hasOwnProperty(“属性名”)
toString方法
当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值
如果我们希望在输出对象时不输出[object Object],可以为对象添加一个toString()方法
//修改Person原型的toString
Person.prototype.toString = function(){
return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]";
};
11.垃圾回收(GC)
就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾
这些垃圾积攒过多以后,会导致程序运行的速度过慢,
所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾
当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,
此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,
所以这种垃圾必须进行清理。
在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,
我们不需要也不能进行垃圾回收的操作
我们需要做的只是要将不再使用的对象设置null即可