函数表达式
- 一种是函数声明
function functionName(arg0, arg1, arg2) {
//函数体
}
重要特征: 就是函数声明提升
- 第二种创建函数的方式
var functionName = function(arg0, arg1, arg2){
//函数体
};
- 匿名函数(anonymous function)
因为 function 关键字后面没有标识符。(匿名函数有时候也叫拉姆达函数。)匿名函数的 name 属性是空字符串。
sayHi(); //错误:函数还不存在
var sayHi = function(){
alert("Hi!");
};
递归
arguments.callee
是一个指向正在执行的函数的指针,因此可以用它来实现对函数
的递归调用,
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * arguments.callee(num-1);
}
}
闭包
闭包是指有权访问另一个函数作用域中的变量的函数。
-
作用域
[[scope]]
:每个javascript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供javascript引擎存取,[[scope]]
就是其中一个。[[scope]]
:指的就是我们所说的作用域,其中存储了运行期上下文的集合。- 作用域链:
[[scope]]
中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。 - 运行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行.上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行,上下文被销毁。
- 查找变量:从作用域链的顶端依次向下查找。
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(num){
return function(){
return num;
};
}(i);
}
return result;
}
立即自行函数解决闭包问题
function(){
//这里是块级作用域
}(); //出错!
(function(){
//这里是块级作用域
})();
- 即使 JavaScript 中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过公有方法可以访问在包含作用域中定义的变量。
- 有权访问私有变量的公有方法叫做特权方法。
- 可以使用构造函数模式、原型模式来实现
自定义类型的特权方法
,也可以使用模块模式、增强的模块模式来实现单例的特权方法
。
BOM
8.1 window 对象
1.全局作用域
全局变量不能通过 delete
操作符删除,而直接在 window 对象上的定义的属性可以。
使用 var 语句添加的 window 属性有一个名为[[Configurable]]
的特性,这个特性的值被设置为false
,因此这样定义的属性不可以通过delete
操作符删除。
尝试访问未声明的变量会抛出错误,但是通过查询 window 对象,可以知道某个可能未声明的变量是否存在。
2 窗口关系及框架
如果页面中包含框架,则每个框架都拥有自己的 window 对象,并且保存在 frames 集合中。
top 对象始终指向最高(最外)层的框架,也就是浏览器窗口。
因为对于在一个框架中编写的任何代码来说,其中的 window 对象指向的都是那个框架的特定实例,而非最高层的框架。
parent(父)对象始终指向当前框架的
直接上层框架。
3.窗口位置
使用下列代码可以跨浏览器取得窗口左边和上边的位置。
var leftPos = (typeof window.screenLeft == "number") ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ? window.screenTop : window.screenY;
moveTo()
接收的是新位置的 x 和 y 坐标值
moveBy()
接收的是在水平和垂直方向上移动的像素数
//将窗口移动到屏幕左上角
window.moveTo(0,0);
//将窗向下移动 100 像素
window.moveBy(0,100);
//将窗口移动到(200,300)
window.moveTo(200,300);
//将窗口向左移动 50 像素
window.moveBy(-50,0);
4.窗口大小
var pageWidth = window.innerWidth,
pageHeight = window.innerHeight;
if (typeof pageWidth != "number") {
if (document.compatMode == "CSS1Compat") {
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
} else {
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
resizeTo()接收浏览器窗口的新宽度和新高度
resizeBy()接收新窗口与原窗口的宽度和高度之差。
//调整到 100× 100
window.resizeTo(100, 100);
//调整到 200× 150
window.resizeBy(100, 50);
//调整到 300× 300
window.resizeTo(300, 300);
另外,这两个方法同样不适用于框架,而只能对最外层的window 对象使用。
5.导航和打开窗口
window.open()
方法:既可以导航到一个特定的 URL,也可以打开一个新的浏览器窗口。- 接收 4 个参数:
- 要加载的 URL
- 窗口目标
- 一个特性字符串
- 以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。
6 间歇调用和超时调用
- 超时调用: setTimeout()方法,
- 它接受两个参数:
- 要执行的代码
- 以毫秒表示的时间(即在执行代码前需要等待多少毫秒)。
//设置超时调用
var timeoutId = setTimeout(function() {
alert("Hello world!");
}, 1000);
//注意:把它取消
clearTimeout(timeoutId);
只要是在指定的时间尚未过去之前调用 clearTimeout(),就可以完全取消超时调用。前面的代码在设置超时调用之后马上又调用了 clearTimeout(),结果就跟什么也没有发生一样。
- 间歇调用的方法:
setInterval()
- 它接受的参数与 setTimeout()相同:
- 要执行的代码(字符串或函数)
- 每次执行之前需要等待的毫秒数。