函数
函数的概念以及作用
概念:函数由一个或多个语句块组成,具备相对的独立性。
作用:通过函数可以封装任意多条语句,以便在任何地方、任何时候调用;
将代码编写在函数中,就可以避免在非必要情况下调用该代码。
函数的创建方式
- 声明式函数,使用function声明一个函数
- 声明式函数,使用function声明一个函数
函数的好处
- 使用函数可以程序过程进行封装、隐藏细节
- 函数有很好的复用性
- 函数可以被事件触发执行
- 可以隔离作用域,避免作用域污染
参数的传递
参数的传递 fn(传参)
arguments对象
每个函数对象都有一个arguments属性;此属性只能在函数执行体内使用。
- arguments属性中保存这当前函数接受到的所有实际参数,故可以使用arguments属性处理可变数量的参数。(可以获取传入的参数)
- arguments对象具有如下属性:
- length:返回实际传入的参数的个数
- callee:返回当前函数的引用
function fn (){ console.log(arguments)//[Arguments] {'0':1,'1':2,'2':3,'3':4,'4':5} console.log(arguments[0])//1 console.log(arguments[1])//2 console.log(arguments.length)//5 console.log(arguments.callee)//[Function: fn] } fn(1,2,3,4,5)//传入5个参数
返回值returm
- 函数可以设置返回值也可以没有返回值•
- 当函数没有返回值时默认返回undefined
- 使用return语句为函数设置返回值
- 函数的返回值可以是任意数据类型,且只能有一个返回值
- 当return执行时,跳出函数体的执行
- return语句也常被用来终止或跳出函数执行
- 调用有返回值的函数时,可以使用变量接收返回值
JS的编译和执行
JS的编译和执行分为两个阶段
一、编译阶段
对于常见编译型语言(例如:Java)来说,编译步骤分为:词法分析->语法分析->语义检查->代码优化和字节生成。对于解释型语言(例如JavaScript)来说,通过词法分析和语法分析得到语法树后,就可以开始解释执行了。
(1)词法分析是将字符流(char stream)转换为记号流(token stream),就像英文句子一个个单词独立翻译,举例:代码:varresult=testNum1-testNum2;词法分析后:NAME"result"EQUALSNAME"testNum1"MINUSNAME"testNum2"SEMICOLON
(2)语法分析得到语法树,举例:条件语句if(typeofa== “undefined” ){ a= 0; } else{ a= a; } alert(a);当JavaScript解释器在构造语法树的时候,如果发现无法构造,就会报语法错误,并结束整个代码块的解析。
(3)“预编译”(并非完全的顺序执行)“function函数”是一等公民!编译阶段,会把定义式的函数优先执行,也会把所有var变量创建,默认值为undefined,以提高程序的执行效率!总结:当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理!并且是先预声明变量,再预定义函数!
二、JavaScript执行过程
在解释过程中,JavaScript引擎是严格按着作用域机制(scope)来执行的。JavaScript语法采用的是词法作用域(lexcicalscope),也就是说JavaScript的变量和函数作用域是在定义时决定的,而不是执行时决定的,由于词法作用域取决于源代码结构,所以JavaScript解释器只需要通过静态分析就能确定每个变量、函数的作用域,这种作用域也称为静态作用域(static scope)。补充:但需要注意,with和eval的语义无法仅通过静态技术实现,实际上,只能说JS的作用域机制非常接近lexical scope。
JavaScript中的变量作用域在函数体内有效,无块作用域;JavaScript引擎在执行每个函数实例时,都会创建一个执行环境(execution context)。执行环境中包含一个调用对象(call object), 调用对象是一个scriptObject结构(“运行期上下文”),用来保存内部变量表varDecls、内嵌函数表funDecls、父级引用列表upvalue等语法分析结构(注意:varDecls和funDecls等信息是在语法分析阶段就已经得到,并保存在语法树中。函数实例执行时,会将这些信息从语法树复制到scriptObject上)。scriptObject是与函数相关的一套静态系统,与函数实例的生命周期保持一致,函数执行完毕,该对象销毁。
JavaScript引擎通过作用域链(scope chain)把多个嵌套的作用域串连在一起,并借助这个链条帮助JavaScript解释器检索变量的值。这个作用域链相当于一个索引表,并通过编号来存储它们的嵌套关系。当JavaScript解释器检索变量的值,会按着这个索引编号进行快速查找,直到找到全局对象(global object)为止,如果没有找到值,则传递一个特殊的undefined值。
递归
递归函数就是在函数体内调用本函数;
变量的作用域
- 全局作用域—一旦定义在程序任何地方都可以访问
- 函数作用域—指在函数中定义的变量只能在函数内部访问
- 只要函数内定义了一个局部变量,函数在解析的时候都会将这个变量“提前声明”:
作用域链
当一个函数创建后,它实际上保存一个作用域链,并且作用域链会被创建此函数的作用域中可访问的数据对象填充
在函数fn创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量
当js需要查找变量x的值的时候(它会从链的第一个对象开始查找,如果这个对象有一个名为x的属性,则会直接使用这个属性的值,如果第一个对象中没有名为x的属性,js会继续查找链上的下一个对象。如果第二个对象依然没有名为x的属性,则会继续查找下一个,以此类推。
如果作用域链上没有任何一个对象含有属性x,那么就认为这段代码的作用域链上不存在x,并最终抛出一个引用错误(ReferenceError)异常。
匿名函数
匿名函数,就是定义时未直接指定名称的函数
匿名函数的应用
回调函数,将一个函数作为另一个函数的参数叫做回调函数。
- 事件
- 对象
- 回调函数
匿名函数的优点
- 因为非匿名函数在定义时,就已经创建函数对象和作用域链对象。所以,即使未调用,也占用内存空间。
- 匿名函数,仅在调用时,才临时创建函数对象和作用域链对象。调用完,立刻释放
- 所以,匿名函数比非匿名函数更节省内存空间
事件与函数的关系
事件的触发需要满足以下条件
- 事件源
- 监听的事件
- 事件处理函数
数组API
Array.push(value,...)
添加到数组尾部的值,可以是一个或多个。(修改原数组)
Array.pop()
删除array的最后一个元素,把数组长度减1,并且返回它删除的元素的值。(修改原数组)
Array.unshift(value,...)
将把它的参数插入array的头部(修改原数组)
Array.shift()
删除array的第一个元素,把数组长度减1,并且返回它删除的元素的值。(修改原数组)
Array.concat(value,...)
要增加到array中的值,可以是任意多个。(不修改原数组)
Array.join(连接符)
每个数组元素转换成一个字符串(不修改原数组)
Array.slice(start[开始下标],end[结束下标])
返回的数组包含从start 开始到end之间的所有元素,但是不包括end所指的元素。(截取数组,不修改原数组)
Array.splice(start[开始下标],number[删除个数],value,...)
删除,替换(修改原数组)
Math
Math对象是ECMAScript提供的一个全局对象,它主要封装了一些常用的数学函数和常数
abs(x)返回数的绝对值
ceil(x)对数进行上舍入
log(x)返回数的自然对数
floor(x)对数进行下舍入
max(x,y)返回x和y中的最高值
min(x,y)返回x和y中的最低值
pow(x,y)返回x的y次幂
round(x)把数四舍五入为最接近的整数
sqrt(x)返回数的平方根
Math对象的方法(随机数)
Math.random() : 返回0~1之间的随机数;
Date对象
Date对象用于对时期和时间进行存储和计算
new Date()
获取时间
可以使用下述方法获取Date对象中的时间信息
getDay()返回Date对象“星期”部分数值(0~6)
getFullYear()返回Date对象“年份”部分实际数值
getHours()返回Date对象“小时”部分数值(0~23)
getMilliseconds()返回Date对象“毫秒”部分数值(0~999)
getMinutes()返回Date对象“分钟”部分数值(0~59)
getMonth()返回Date对象“月份”部分数值(0~11)getSeconds()返回Date对象“秒”部分数值(0~59)
getTime()返回Date对象与UTC时间1970年1月1日午间之间相差的毫秒数
getTimezoneOffset()返回本地时间与格林威治标准时间(GMT)的分钟差
BOM
BOM:Brower Object Model浏览器对象模型,用来访问和操作浏览器窗口,使JS有能力与浏览器交互
window对象是BOM的根对象,其它对象其实都是window对象的属性,window对象的属性和方法都可以省略“window.”
navigator包含有关浏览器的信息
screen包含有关客户端显示屏幕的信息
history包含用户(在浏览器窗口中)访问过的
URLlocation包含有关URL的信息
document包含当前浏览器加载的文档信息
event包含当前所触发的事件对象
window对象常用属性
innerHeight返回窗口的文档显示区的高度
innerWidth返回窗口的文档显示区的宽度
name设置或返回窗口名称
pageXOffset设置或返回当前页面相对于窗口显示区左上角的x位置
pageYOffset设置或返回当前页面相对于窗口显示区左上角的y位置
outerHeight返回窗口的外部高度
outerWidth返回窗口的外部宽度
定时器
周期性定时器
setInterval(exp,time)
:周期性触发代码exp
- exp:执行语句•time:时间周期,单位为毫秒
- 返回已经启动的定时器ID
clearInterval(tID)
:停止启动的定时器
- . tID:启动的定时器对象
一次性定时器
setTimeout(exp,time)
:一次性触发代码exp
- exp:执行语句•time:时间周期,单位为毫秒
- 返回已经启动的定时器ID
clearTimeout(tID):停止启动的定时器
- tID:启动的定时器对象
DOM
DOM:Document Object Model文档对象模型,用来操作当前HTML文档的内容•定义了访问和操作HTML文档的标准方法•通过对DOM树的操作,实现对HTML文档树据的操作•W3C指定了相关标准
HTML DOM:针对HTML文档的对象模型
当网页被加载时,浏览器会创建页面的文档对象模型
通过DOM,可以访问所有的HTML元素,连同它们所包含的文本和属性
可以对其中的内容进行修改和删除,同时也可以创建新的元素•文档中的所有节点组成了一个文档树
document对象是一颗文档树的根
W3C DOM标准被分为3个不同的部分:
- 核心DOM 针对任何结构化文档的标准模型
- XML DOM 针对XML文档的标准模型
- HTML DOM针对HTML文档的标准模型
document对象
4. 浏览器内置的JS解释器会为载入的每个HTML文档创建一个对应的document对象
5. 通过使用document对象,可以从脚本中对HTML页面中的所有元素进行访问
DOM操作
getElementById()
通过ID获取
getElementsByName()
通过name属性
getElementsByTagName()
通过标签名
getElementsByClassName()
通过类名
querySelector()
通过选择器获取一个元素
appendChild()
添加
removeChild()
删除
replaceChild()
替换
insertBefore()
插入
createAttribute()
创建属性节点
createElement()
创建元素节点
createTextNode
创建文本节点
获取到的元素.innerHTML=添加的内容
元素开始和结束标签之间的HTML
节点
文档中的元素、属性、文本、注释等都被看作一个节点。
事件处理
- HTML事件处理:
- 直接添加到HTML结构中
- DOM0级事件处理:
- 把一个函数赋值给一个事件处理程序属性
- DOM2级事件处理:
addEventListener(“事件名”,”事件处理函数”,”布尔值”);
- true:事件捕获
- false:事件冒泡
removeEventListener(“事件名”,事件处理函数);//移除事件
- IE事件处理程序(IE版本小于等于8)
- attachEvent(“事件名”,”事件处理函数”)
- detachEvent(“事件名”,”事件处理函数”)
事件的处理周期
解释器创建一个event对象后,会按如下过程将其在HTML元素间进行传播:
第一阶段:事件的捕获,事件对象沿DOM树向下传播
第二阶段:目标触发,运行事件监听函数
第三阶段:事件冒泡,事件沿DOM树向上传播
注:IE的事件中没有“捕获”阶段
阻止事件冒泡
event.cancelBubble = true;//IE
event.stopPropagation( ); //DOM
event对象
- 任何事件触发后将会产生一个event对象
- event对象记录事件发生时的鼠标位置、键盘按键状态和触发对象等信息,事件对象的常用属性:
type:事件类型srcElement(IE)、target:事件源对象
clientX、offsetX、pageX、screenX:事件发生的X坐标
clientY、offsetY、pageY、screenY:事件发生的y坐标
阻止事件的默认行为
事件的默认的行为:如submit按钮默认就可以提交表单、input只要键盘一按下默认就会把内容显示在输入框中…
可以使用下述方法阻止事件的默认行为:
event.returnValue = false;//IE
event.preventDefault( );//DOM
正则
匹配(判断)用户输入
正则表达式中有些字符有特殊的语法含义,是不能直接使用的,必须使用\进行转义后才能使用:
. / * ? + [ ] ( ) { } ^ | $
正则表达式使用如下语法匹配一个范围内的字符
[abc]
匹配指定集合内的任一个字符
[^abc]
匹配不在指定集合内的任一个字符
[0-9]
匹配任一个数字
[a-z]
匹配任一个小写字符
[A-Z]
匹配任一个大写字符
[A-z]
匹配大写A到小写z的所有字符
正则表达式中可以使用如下元字符引用来进行简化
\d
匹配一个数字
\D
匹配一个非数字
\w
匹配一个数字/字母/下划线
\W
匹配一个非数字/字母/下划线
\s
匹配一个空白符
\S
匹配一个非空白符.匹配除了回车和换行外的任何单个字符
正则表达式中可以使用如下特殊字符定义字符的出现频次–量词元字符
n?
匹配零次或一次字符n
n*
匹配零次或多次字符nn+匹配一次或多次字符n
n{x}
匹配字符n出现x次
n{x,y}
匹配字符n出现x到y次
n{x,}
匹配字符n的出现次数>=x次
可以使用如下字符进行指定位置的匹配
^
匹配字符串的开头
$
匹配字符串的结尾
\b
匹配单词的边界
\B
匹配单词的非边界
?=x
匹配其后紧接x的字符串
?!x
匹配其后没有紧接x的字符串
创建RegExp对象
创建正则表达式对象有两种方法:
直接量语法:
var regexp =/abc/attribnnutes;
调用RegExp构造方法:
var regexp = new RegExp('abc','attribute');
RegExp对象具有如下属性:
global
只读)RegExp对象是否具有g修饰符
ignoreCase
(只读)RegExp对象是否具有i修饰符
multiline
(只读)RegExp对象是否具有m修饰符
lastIndex
用于设置/获取下次匹配的起始位置(没有指定g修饰符的RegExp
对象不能使用lastIndex属性)
source
(只读)返回模式匹配所使用的文本
$1....$9
指代最近一次搜索中某个子表达式匹配的文本
RegExp对象具有如下方法
exec()
检索字符串中指定的值。返回找到的值,并确定其位置
test()
检索字符串中指定的值。返回true或false;