函数、对象
1 函数
1.1 定义
函数(Function),也称为方法(Method)、过程(Procedure),是一段预定义好、可以被反复使用的代码块,包含多条可执行语句,本质上是功能完整的对象。分为系统函数和自定义函数;
定义:function func_name() {st1;st2;…}
参数:function func_name(参数列表) {};指定参数简称“形参”
返回值:return val;
如果没有return/有return、没有值,返回undefined;不会执行return后面的代码;可以返回任何类型的数据;
对比函数声明和函数表达式的区别:
函数声明存在函数提升;而函数表达式不存在函数提升,必须先创建再调用;
1.2 调用
调用带参数的函数时,可以传递直接量或是变量;
函数内可以调用本身或是其它函数;
1.3 变量的作用域
1)作用域是变量与函数的可访问范围,控制变量与函数的可见性和生命周期;
2)JS中函数作用域只在当前函数内可访问,全局作用域在该文件中任何地方都可以访问;
3)函数作用域中的变量称为局部变量,只能在当前函数访问;
4)全局作用域中的变量称为全局变量(在最外层定义),可以在代码任何位置访问,未使用var声明的变量是全局变量,但不推荐使用。
5)声明提前:JS程序在正式执行前会将所有声明的变量和函数预读到所在作用域的顶部,赋值依旧留在原位置随脚本解释执行。Eg.console.log(a);var a=100;不会报错,undefined
6)按值传递,将实参变量的值复制给调用函数的形参变量,JS都是按值传递。
7)原始数据类型的数据存储在栈内存中,调用函数传参会重新创建内存空间,把原来的值复制过去,和原来的值没有任何关系。
1.4 函数作用域
1)全局函数在最外层定义,局部函数在函数内部定义;
2)如果函数名称相同,后边的会覆盖前面的;
3)函数存储在堆内存中:
function fn(){}:fn存储的是函数在栈内存中的地址->生成一个16进制数字赋给栈内存,通过这个值可以访问堆内存中对应的函数;
4)使用var声明的变量和function声明的函数会被提前至当前作用域顶部;先提前函数声明,再提升变量声明,所以同名变量将覆盖该函数;
1.5 递归调用
递归:函数在其定义中直接或间接地调用本身,可以将复杂地问题转化为相似地较小问题来解决;减少了代码量,需要考虑执行速度。(可以在内部定义函数或变量,因为作为局部函数/变量,只在当前作用域内有效)
注意边界条件要在递归前进之前判断;
实现:边界条件、递归前进、递归返回
1.6 匿名函数
未直接指定名称的函数;function(val1, val2){};
分析:函数取名通常是为了方便下次使用,匿名函数适合只使用一次地函数(function(){})();
如果想继续调用,可以var func_name = function(){};
1.7 回调函数
将一个函数作为另一个函数的参数的参数;回调函数将匿名函数以实参的形式传递,形参的参数列表成为匿名函数的名称,在函数内部调用这些函数;
1.8 自调函数
定义匿名函数立即调用;形如:(function(val1, val2){})(100, 200);,第一个中括号表示匿名函数,第二个中括号表示立即调用
对于有相同名字的变量和函数,为避免全局污染,常使用匿名函数包含该函数再调用(自调函数);因为创建局部作用域,函数及其变量作用域不再是global,不能被外部访问
1.9 对象argument(实参)
-
每个函数对象都有argumets属性,只能在函数执行体内使用,保存当前函数接收到的所有实参,
可以使用arguments属性处理可变数量的参数:
-
- arguments.length:返回实际传入的参数个数;
- arguments.callee():返回当前函数的引用(匿名函数可以通过该属性实现递归调用)
1.10 全局函数概述
-
ECMAScript预定义了一组全局函数:
-
1.decodeURI():对已编码统一资源标识符URI进行解码,返回非编码形式
2.decodeURIComponent():对统一资源标识符的一个已编码组件进行解码,返回非编码形式
3.encodeURI():对URI进行编码,返回编码后的URI字符串
4.encodeURIComponent():对URI的有效组件进行编码,返回编码后的URI字符串
5.eval():计算字符串并执行以string形式出现的JavaScript代码;也可以将JSON字符串解析为JavaScript对象
6.isFinite():判断数字是否为有限值
7.isNaN():判断数字是否“非数字”
8.parseFloat():字符串转换为浮点数并返回
9.parseInt():字符串转换为整数并返回
2 对象Object
2.1 对象概述
- 对象概述
数据类型可分为值类型和引用类型:值类型数据保存在“栈内存”,引用(对象)类型数据保存在“堆内存”;
定义:对象是需求场景中的名词在程序中的表示;除了原生类型string、number、bool、null、undefined等值类型数据,其他数据都是对象。
ECMA-262标准中对象定义:属性的无序集合,每个属性存放一个原始值、对象或函数;对象是无特定顺序的值的数组;
对象是特殊的数据类型,包含多个成员(可以分为属性和方法两种):属性property即封装对象的数据,表示与对象有关的值,对象名.属性名;方法Method即封装对象的行为,表示对象可以执行的行为或实现的功能,对象名.方法名() - 对象分类
1.ES原生对象(Native Object),也称为内置对象,由ECCMA标准定义的17个对象:String、Boolean、Number、Object、Function;Array、Date、RegExp、Math;Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError;Global
2.宿主对象(Host Object),由JS解释器专门提供的扩展对象,不同JS解释器提供扩展对象存在较大差异,浏览器提供宿主对象可分为两类:
:1)BOM对象(Browser Object Model):Window、Navigator、Screen、History、Location;
:2)DOM对象(Document Object Model):Document、Anchor、Area、Base、Body、Button、Canvas、Event、Frame、Frameset、IFrame、Image、Link、Meta、Style、Form、Input Button、Input Checkbox、Input File、Input Hidden、Input Password、Input Radio、Input Reset、Input Submit、Input Text、Option、Select、Textarea、Table、TableCell、TableRow;
3.用户自定义对象,由开发者自己定义的对象,有三种创建方法:
:1)对象直接量;
:2)new Object();
:3)function对象模板
2.2 创建对象
-
对象直接量 由名/值对组成的映射表;名和值之间用冒号隔开,明值对之间用逗号分隔 创建不含任何成员的对象 var obj1={};var obj2 ={x:0, y:0};,对象属性名中包含“非法字符”必须使用引号括起来
-
使用new创建对象 使用new 关键字创建对象(系统对象、通用对象、自定义对象->自定义构造函数)var obj1 = new Date();关键字new就是在堆内存中分配新的存储空间; 通过Object创建通用对象var obj1 = new Object();obj1.name = “John”;obj1.age=50;
通过new创建对象,添加属性:book[‘price’];中括号里面如果没有引号,视为变量。
补充:var a=b;//b是一个对象
表示的是复制对象存储在栈内存中的地址;对a或原对象b里任何属性的改动都会影响另一个对象的属性,因为都指向堆内存中的对象。
2.3 属性
- 定义属性
对象可以声明多个属性property
//直接量方式声明对象属性
var book = {
“book name”: ‘Java编程’,
‘sub-title’: ‘掌握Java’,
“for”: “有基础人员”
author: {}
};//属性名包含空格、减号或是关键字需要加引号
//使用new创建的对象声明属性
var emp2 = new Object();
emp2.ename = ‘Mary’;
emp2[“salary”] = 3800;//[]内的表达式必须是string类型 - 访问属性
通过对象的引用,使用.或[]运算符访问对象属性 - 遍历属性
for (var attrName in [table_name]) {console.log(attrName+’:’+[table_name][attrName])};
//for … in遍历对象属性没有特定的顺序;只能遍历用户自定义的属性,不会枚举出预定义的属性和方法
访问遍历对象时,使用’[]‘而不是’.’,否则出现undefined; - 属性访问错误
访问未声明的变量->ReferenceError;访问未声明的属性->undefined;访问未声明属性的成员->TypeError
当不确定对象及其属性是否存在时,可以使用错误处理结构try … catch …来捕捉抛出的错误以避免程序异常终止 - 检测属性
四种方法检测对象中是否存在指定属性:undefined/null/0/""会自动转换为false
1.使用in关键字:if (‘ename’ in [table_name]) {};
2.使用对象的hasOwnProperty()方法:if ([table_name].hasOwnProperty(‘ename’)) {};
3.使用undefined判断:if ([table_name].ename === undefined) {};
4.条件语句:if ([table_name].ename) {};
2.4 方法
-
定义方法
对象可以实施的行为或者功能,两种定义方法:
1)在对象内部声明时即定义;
2)在对象内部声明,在外部定义;var rect = { width:20, height:10, getSize:function(){},//定义方法1 getPerimeter:perimeter//定义方法2,一定不能加() }; function perimeter() {return 2*(this.width + this.height)};
this指代当前对象
2. 调用方法
通过对象的引用调用对象的方法:rect.getSize();