专栏首页魏晓蕾的专栏JavaScript中的匿名函数、闭包和BOM

JavaScript中的匿名函数、闭包和BOM

1、匿名函数

匿名函数就是没有名字的函数。

// 普通函数
function box() { 			// 函数名是 box
	return 'Lee';
}

// 匿名函数
function () { 				// 匿名函数,会报错
	return 'Lee';
}

// 通过表达式自我执行
(function box() { 			// 封装成表达式
	alert('Lee');
})(); 
							// ()表示执行函数,并且传参
// 把匿名函数赋值给变量
var box = function () { 	// 将匿名函数赋给变量
	return 'Lee';
};
alert(box()); 				// 调用方式和函数调用相似

// 函数里的匿名函数
function box () {
	return function () { 	// 函数里的匿名函数,产生闭包
	return 'Lee';
} }
alert(box()()); 			// 调用匿名函数

2、闭包

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。

// 通过闭包可以返回局部变量
function box() {
	var user = 'Lee';
	return function () { 		// 通过匿名函数返回 box()局部变量
		return user;
	};
}
alert(box()()); 				// 通过 box()()来直接调用匿名函数返回值
var b = box();
alert(b()); 					// 另一种调用匿名函数返回值

使用闭包有一个优点,也是它的缺点:就是可以把局部变量驻留在内存中,可以避免使用全局变量。(全局变量污染导致应用程序不可预测性,每个模块都可调用必将引来灾难,所以推荐使用私有的,封装的局部变量)。

// 通过全局变量来累加
var age = 100; 						// 全局变量
function box() {
	age ++; 						// 模块级可以调用全局变量,进行累加
}
box(); 								// 执行函数,累加了
alert(age); 						// 输出全局变量

// 通过局部变量无法实现累加
function box() {
	var age = 100;
	age ++; 						// 累加
	return age;
}
alert(box()); 						// 101
alert(box()); 						// 101,无法实现,因为又被初始化了

// 通过闭包可以实现局部变量的累加
function box() {
	var age = 100;
	return function () {
		age ++;
		return age;
} }
var b = box(); 						// 获得函数
alert(b()); 						// 调用匿名函数
alert(b()); 						// 第二次调用匿名函数,实现累加

由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降,建议在非常有必要的时候才使用闭包。作用域链的机制导致一个问题,在循环中里的匿名函数取得的任何变量都是最后一个值。

// 循环里包含匿名函数
function box() {
	var arr = [];
	for (var i = 0; i < 5; i++) {
		arr[i] = function () {
		return i;
		}; 
	}
	return arr;
}
var b = box(); 								// 得到函数数组
alert(b.length); 							// 得到函数集合长度
for (var i = 0; i < b.length; i++) {
	alert(b[i]()); 							// 输出每个函数的值,都是最后一个值
}

上面的例子输出的结果都是 5,也就是循环后得到的最大的 i 值。因为 b[i]调用的是匿名函数,匿名函数并没有自我执行,等到调用的时候,box()已执行完毕,i 早已变成 5,所以最终的结果就是 5 个 5。

// 循环里包含匿名函数-改 1,自我执行匿名函数
function box() {
	var arr = [];
	for (var i = 0; i < 5; i++) {
		arr[i] = (function (num) { 					// 自我执行
		return num;
		})(i); 										// 并且传参
	}
	return arr;
}
var b = box();
for (var i = 0; i < b.length; i++) {
	alert(b[i]); 									// 这里返回的是数组,直接打印即可
}

改 1 中,我们让匿名函数进行自我执行,导致最终返回给 a[i]的是数组而不是函数了。最终导致 b[0]-b[4]中保留了 0,1,2,3,4 的值。

// 循环里包含匿名函数-改 2,匿名函数下再做个匿名函数
function box() {
	var arr = [];
	for (var i = 0; i < 5; i++) {
		arr[i] = (function (num) {
			return function () { 			// 直接返回值,改 2 变成返回函数
				return num; 				// 原理和改 1 一样
			}
		})(i);
	}
	return arr;
}
var b = box();
for (var i = 0; i < b.length; i++) {
	alert(b[i]()); 							// 这里通过 b[i]()函数调用即可
}

改 1 和改 2 中,我们通过匿名函数自我执行,立即把结果赋值给 a[i]。每一个 i,是调用方通过按值传递的,所以最终返回的都是指定的递增的 i。而不是 box()函数里的 i。

关于 this 对象

在闭包中使用 this 对象也可能会导致一些问题,this 对象是在运行时基于函数的执行环境绑定的,如果 this 在全局范围就是 window,如果在对象内部就指向这个对象。而闭包却在运行时指向 window 的,因为闭包并不属于这个对象的属性或方法。

var user = 'The Window';
var obj = {
	user : 'The Object',
	getUserFunction : function () {
		return function () { 					// 闭包不属于obj,里面的this指向window
			return this.user;
		};
	}
};
alert(obj.getUserFunction()()); 				// The window

// 可以强制指向某个对象
alert(obj.getUserFunction().call(obj)); 		// The Object

// 也可以从上一个作用域中得到对象
getUserFunction : function () {
	var that = this; 							// 从对象的方法里得对象
	return function () {
		return that.user;
	};
}

内存泄漏

由于 IE 的 JScript 对象和 DOM 对象使用不同的垃圾收集方式,因此闭包在 IE 中会导致一些问题。就是内存泄漏的问题,也就是无法销毁驻留在内存中的元素。

function box() {
	var oDiv = document.getElementById('oDiv'); 		// oDiv 用完之后一直驻留在内存
	oDiv.onclick = function () {
		alert(oDiv.innerHTML); 							// 这里用 oDiv 导致内存泄漏
	};
}
box();

那么在最后应该将 oDiv 解除引用来避免内存泄漏。

function box() {
	var oDiv = document.getElementById('oDiv');
	var text = oDiv.innerHTML;
	oDiv.onclick = function () {
		alert(text);
	};
	oDiv = null; 										// 解除引用
}

如果并没有使用解除引用,那么需要等到浏览器关闭才得以释放。

模仿块级作用域

JavaScript 没有块级作用域的概念。

function box(count) {
	for (var i=0; i<count; i++) {}
	alert(i); 											// i 不会因为离开了 for 块就失效
}
box(2);
function box(count) {
	for (var i=0; i<count; i++) {}
	var i; 												// 就算重新声明,也不会前面的值
	alert(i);
}
box(2);

以上两个例子,说明 JavaScript 没有块级语句的作用域,if () {} for () {}等没有作用域,如果有,出了这个范围 i 就应该被销毁了。就算重新声明同一个变量也不会改变它的值。JavaScript 不会提醒你是否多次声明了同一个变量;遇到这种情况,它只会对后续的声明视而不见(如果初始化了,当然还会执行的)。使用模仿块级作用域可避免这个问题。

// 模仿块级作用域(私有作用域)
(function () {
	// 这里是块级作用域
})();

// 使用块级作用域(私有作用域)改写
function box(count) {
	(function () {
		for (var i = 0; i<count; i++) {}
	})();
	alert(i); 									// 报错,无法访问
}
box(2);

使用了块级作用域(私有作用域)后,匿名函数中定义的任何变量,都会在执行结束时被销毁。这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。一般来说,我们都应该尽可能少向全局作用域中添加变量和函数。在大型项目中,多人开发的时候,过多的全局变量和函数很容易导致命名冲突,引起灾难性的后果。如果采用块级作用域(私有作用域),每个开发者既可以使用自己的变量,又不必担心搞乱全局作用域。

(function () {
	var box = [1,2,3,4];
	alert(box); 								// box 出来就不认识了
})();

在全局作用域中使用块级作用域可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函数执行完毕,就可以立即销毁其作用域链了。

私有变量

JavaScript 没有私有属性的概念;所有的对象属性都是公有的。不过,却有一个私有变量的概念。任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数的外部访问这些变量。

function box() {
var age = 100; 									// 私有变量,外部无法访问
}

而通过函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些变量。而利用这一点,可以创建用于访问私有变量的公有方法。

function Box() {
	var age = 100; 								// 私有变量
	function run() { 							// 私有函数
		return '运行中...'; 
	}
	this.get = function () { 					// 对外公共的特权方法
		return age + run();
	};
}
var box = new Box();
alert(box.get());

可以通过构造方法传参来访问私有变量。

function Person(value) {
	var user = value; 							// 这句其实可以省略
	this.getUser = function () {
		return user;
	};
	this.setUser = function (value) {
		user = value;
	};
}

但是对象的方法,在多次调用的时候,会多次创建。可以使用静态私有变量来避免这个问题。

静态私有变量

通过块级作用域(私有作用域)中定义私有变量或函数,同样可以创建对外公共的特权方法。

(function () {
	var age = 100;
	function run() {
		return '运行中...';
	}
	Box = function () {}; 						// 构造方法
	Box.prototype.go = function () { 			// 原型方法
		return age + run();
	};
})();
var box = new Box();
alert(box.go());

上面的对象声明,采用的是 Box = function () {} 而不是 function Box() {} 因为如果用后面这种,就变成私有函数了,无法在全局访问到了,所以使用了前面这种。

(function () {
	var user = '';
	Person = function (value) {
		user = value;
	};
	Person.prototype.getUser = function () {
		return user;
	};
	Person.prototype.setUser = function (value) {
		user = value;
	}
})();

使用了 prototype 导致方法共享了,而 user 也就变成静态属性了。(所谓静态属性,即共享于不同对象中的属性)。

模块模式

之前采用的都是构造函数的方式来创建私有变量和特权方法。那么对象字面量方式就采用模块模式来创建。

var box = { 						// 字面量对象,也是单例对象
	age : 100, 						// 这是公有属性,将要改成私有
	run : function () { 			// 这时公有函数,将要改成私有
		return '运行中...';
	};
};
私有化变量和函数:
var box = function () {
	var age = 100;
	function run() {
		return '运行中...';
	}
	return { 						// 直接返回对象
		go : function () {
			return age + run();
		}
	};
}();

上面的直接返回对象的例子,也可以这么写:

var box = function () {
	var age = 100;
	function run() {
		return '运行中...';
	}
	var obj = { 					// 创建字面量对象
		go : function () {
			return age + run();
		}
	};
	return obj; 					// 返回这个对象
}();

字面量的对象声明,其实在设计模式中可以看作是一种单例模式,所谓单例模式,就是永远保持对象的一个实例。增强的模块模式,这种模式适合返回自定义对象,也就是构造函数。

function Desk() {};
var box = function () {
	var age = 100;
	function run() {
		return '运行中...';
	}
	var desk = new Desk(); 			// 可以实例化特定的对象
	desk.go = function () {
		return age + run();
	};
	return desk;
}();
alert(box.go());

3、BOM

BOM 也叫浏览器对象模型,它提供了很多对象,用于访问浏览器的功能。BOM 缺少规范,每个浏览器提供商又按照自己想法去扩展它,那么浏览器共有对象就成了事实的标准。所以,BOM 本身是没有标准的或者还没有哪个组织去标准它。

window 对象

BOM 的核心对象是 window,它表示浏览器的一个实例。window 对象处于 JavaScript 结构的最顶层,对于每个打开的窗口,系统都会自动为其定义 window 对象。

1. 对象的属性和方法

window 对象有一系列的属性,这些属性本身也是对象。 window 对象的属性:

属性

含义

closed

当窗口关闭时为真

defaultStatus

窗口底部状态栏显示的默认状态消息

document

窗口中当前显示的文档对象

frames

窗口中的框架对象数组

history

保存有窗口最近加载的 URL

length

窗口中的框架数

location

当前窗口的 URL

name

窗口名

offscreenBuffering

用于绘制新窗口内容并在完成后复制已存在的内容,控制屏幕更新

opener

打开当前窗口的窗口

parent

指向包含另一个窗口的窗口(由框架使用)

screen

显示屏幕相关信息,如高度、宽度(以像素为单位)

self

指示当前窗口

status

描述由用户交互导致的状态栏的临时消息

top

包含特定窗口的最顶层窗口(由框架使用)

window

指示当前窗口,与 self 等效

window 对象的方法:

方法

功能

alert(text)

创建一个警告对话框,显示一条信息

blur()

将焦点从窗口移除

clearInterval(interval)

清除之前设置的定时器间隔

clearTimeout(timer)

清除之前设置的超时

close()

关闭窗口

confirm()

创建一个需要用户确认的对话框

focus()

将焦点移至窗口

open(url,name,[options])

打开一个新窗口并返回新 window 对象

prompt(text,defaultInput)

创建一个对话框要求用户输入信息

scroll(x,y)

在窗口中滚动到一个像素点的位置

setInterval(expression,milliseconds)

经过指定时间间隔计算一个表达式

setInterval(function,milliseconds,[arguments])

经过指定时间间隔后调用一个函数

setTimeout(expression,milliseconds)

在定时器超过后计算一个表达式

setTimeout(expression,milliseconds,[arguments])

在定时器超过时后计算一个函数

print()

调出打印对话框

find()

调出查找对话框

window 下的属性和方法,可以使用 window.属性、window.方法()或者直接属性、方法()的方式调用。例如:window.alert()和 alert()是一个意思。

2. 系统对话框

浏览器通过 alert()、confirm()和 prompt()方法可以调用系统对话框向用户显示信息。系统对话框与浏览器中显示的网页没有关系,也不包含 HTML。

// 弹出警告
alert('Lee'); 							// 直接弹出警告

// 确定和取消
confirm('请确定或者取消'); 				// 这里按哪个都无效
if (confirm('请确定或者取消')) { 		// confirm 本身有返回值
	alert('您按了确定!'); 				// 按确定返回 true
} else {
	alert('您按了取消!'); 				// 按取消返回 false
}

// 输入提示框
var num = prompt('请输入一个数字', 0); 	// 两个参数,一个提示,一个值
alert(num); 							// 返回值可以得到

// 调出打印及查找对话框
print(); 								// 打印
find(); 								// 查找
defaultStatus = '状态栏默认文本'; 		// 浏览器底部状态栏初始默认值
status='状态栏文本'; 					// 浏览器底部状态栏设置值

3. 新建窗口

使用 window.open()方法可以导航到一个特定的 URL,也可以打开一个新的浏览器窗口。它可以接受四个参数:(1)要加载的 URL;(2)窗口的名称或窗口目标;(3)一个特性字符串;(4)一个表示新页面是否取代浏览器记录中当前加载页面的布尔值。

open('http://www.baidu.com'); 				// 新建页面并打开百度
open('http://www.baidu.com','baidu'); 		// 新建页面并命名窗口并打开百度
open('http://www.baidu.com','_parent'); 	// 在本页窗口打开百度,_blank 是新建

不命名会每次打开新窗口,命名的第一次打开新窗口,之后在这个窗口中加载。窗口目标是提供页面的打开的方式,比如本页面,还是新建。 第三字符串参数:

设置

说明

width

数值

新窗口的宽度。不能小于 100

height

数值

新窗口的高度。不能小于 100

top

数值

新窗口的 Y 坐标。不能是负值

left

数值

新窗口的 X 坐标。不能是负值

location

yes 或 no

是否在浏览器窗口中显示地址栏。不同浏览器默认值不同

menubar

yes 或 no

是否在浏览器窗口显示菜单栏。默认为 no

resizable

yes 或 no

是否可以通过拖动浏览器窗口的边框改变大小。默认为 no

scrollbars

yes 或 no

如果内容在页面中显示不下,是否允许滚动。默认为 no

status

yes 或 no

是否在浏览器窗口中显示状态栏。默认为 no

toolbar

yes 或 no

是否在浏览器窗口中显示工具栏。默认为 no

fullscreen

yes 或 no

浏览器窗口是否最大化,仅限 IE

// 第三参数字符串
open('http://www.baidu.com','baidu','width=400,height=400,top=200,left=200,toolbar=yes');

// open 本身返回 window 对象
var box = open();
box.alert(''); 										// 可以指定弹出的窗口执行 alert();

// 子窗口操作父窗口
document.onclick = function () {
	opener.document.write('子窗口让我输出的!');
}

4. 窗口的位置和大小

用来确定和修改 window 对象位置的属性和方法有很多。IE、Safari、Opera 和 Chrome都提供了 screenLeft 和 screenTop 属性,分别用于表示窗口相对于屏幕左边和上边的位置。Firefox 则在 screenX 和 screenY 属性中提供相同的窗口位置信息,Safari 和 Chrome 也同时支持这两个属性。

// 确定窗口的位置,IE 支持
alert(screenLeft); 					// IE 支持
alert(typeof screenLeft); 			// IE显示 number,不支持的显示 undefined

// 确定窗口的位置,Firefox 支持
alert(screenX); 					// Firefox 支持
alert(typeof screenX); 				// Firefox 显示 number,不支持的同上

screenX 属性 IE 浏览器不认识,直接 alert(screenX),screenX 会当作一个为声明的变量,导致不执行。那么必须将它将至为 window 属性才能显示为初始化变量应有的值,所以应该写成:alert(window.screenX)。

// 跨浏览器的方法
var leftX = (typeof screenLeft == 'number') ? screenLeft : screenX;
var topY = (typeof screenTop == 'number') ? screenTop : screenY;

窗口页面大小,Firefox、Safari、Opera 和 Chrome 均为此提供了 4 个属性:innerWidth 和innerHeight,返回浏览器窗口本身的尺寸;outerWidth 和 outerHeight,返回浏览器窗口本身及边框的尺寸。

alert(innerWidth); 					// 页面长度
alert(innerHeight); 				// 页面高度
alert(outerWidth); 					// 页面长度+边框
alert(outerHeight); 				// 页面高度+边框

在 Chrome 中,innerWidth=outerWidth、innerHeight=outerHeight;IE 没有提供当前浏览器窗口尺寸的属性;不过,在后面的 DOM 课程中有提供相关的方法。 在 IE 以及 Firefox、Safari、Opera 和 Chrome 中,document.documentElement.clientWidth 和document.documentElement.clientHeight 中保存了页面窗口的信息。 在 IE6 中,这些属性必须在标准模式下才有效;如果是怪异模式,就必须通过document.body.clientWidth 和 document.body.clientHeight 取得相同的信息。

// 如果是 Firefox 浏览器,直接使用 innerWidth 和 innerHeight
var width = window.innerWidth; 								// 这里要加 window,因为 IE 会无效
var height = window.innerHeight;
if (typeof width != 'number') { 							// 如果是 IE,就使用 document
	if (document.compatMode == 'CSS1Compat') {
		width = document.documentElement.clientWidth;
		height = document.documentElement.clientHeight;
	} else {
		width = document.body.clientWidth; 					// 非标准模式使用 body
		height = document.body.clientHeight;
	} 
}

以上方法可以通过不同浏览器取得各自的浏览器窗口页面可视部分的大小。document.compatMode 可以确定页面是否处于标准模式,如果返回 CSS1Compat 即标准模式。

// 调整浏览器位置
moveTo(0,0); 			// IE 有效,移动到 0,0 坐标
moveBy(10,10); 			// IE 有效,向下和右分别移动 10 像素

// 调整浏览器大小
resizeTo(200,200); 		// IE 有效,调正大小
resizeBy(200,200); 		// IE 有效,扩展收缩大小

由于此类方法被浏览器禁用较多,用处不大。

5. 间歇调用和超时调用

JavaScript 是单线程语言,但它允许通过设置超时值和间歇时间值来调度代码在特定的时刻执行。前者在指定的时间过后执行代码,而后者则是每隔指定的时间就执行一次代码。超时调用需要使用 window 对象的 setTimeout()方法,它接受两个参数:要执行的代码和毫秒数的超时时间。

setTimeout("alert('Lee')", 1000); 		// 不建议直接使用字符串
function box() {
	alert('Lee');
}
setTimeout(box, 1000); 					// 直接传入函数名即可
setTimeout(function () { 				// 推荐做法
	alert('Lee');
}, 1000);

直接使用函数传入的方法,扩展性好,性能更佳。调用 setTimeout()之后,该方法会返回一个数值 ID,表示超时调用。这个超时调用的 ID 是计划执行代码的唯一标识符,可以通过它来取消超时调用。要取消尚未执行的超时调用计划,可以调用 clearTimeout()方法并将相应的超时调用 ID 作为参数传递给它。

var box = setTimeout(function () { 		// 把超时调用的 ID 复制给 box
	alert('Lee');
}, 1000);
clearTimeout(box); 						// 把 ID 传入,取消超时调用

间歇调用与超时调用类似,只不过它会按照指定的时间间隔重复执行代码,直至间歇调用被取消或者页面被卸载。设置间歇调用的方法是 setInterval(),它接受的参数与 setTimeout() 相同:要执行的代码和每次执行之前需要等待的毫秒数。

setInterval(function () { 					// 重复不停执行
	alert('Lee');
}, 1000);

取消间歇调用方法和取消超时调用类似,使用 clearInterval()方法。但取消间歇调用的重要性要远远高于取消超时调用,因为在不加干涉的情况下,间歇调用将会一直执行到页面关闭。

var box = setInterval(function () { 		// 获取间歇调用的 ID
	alert('Lee');
}, 1000);
clearInterval(box); 						// 取消间歇调用

但上面的代码是没有意义的,我们需要一个能设置 5 秒的定时器,需要如下代码:

var num = 0; 								// 设置起始秒
var max = 5; 								// 设置最终秒
setInterval(function () { 					// 间歇调用
	num++; 									// 递增 num
	if (num == max) { 						// 如果得到 5 秒
		clearInterval(this); 				// 取消间歇调用,this 表示方法本身
		alert('5 秒后弹窗!');
	}
}, 1000); 									// 1 秒

一般认为,使用超时调用来模拟间歇调用是一种最佳模式。在开发环境下,很少使用真正的间歇调用,因为需要根据情况来取消 ID,并且可能造成同步的一些问题,我们建议不使用间歇调用,而去使用超时调用。

var num = 0;
var max = 5;
function box() {
	num++;
	if (num == max) {
		alert('5 秒后结束!');
	} else {
		setTimeout(box, 1000);
	}
}
setTimeout(box, 1000); 						// 执行定时器

在使用超时调用时,没必要跟踪超时调用 ID,因为每次执行代码之后,如果不再设置另一次超时调用,调用就会自行停止。

location 对象

location 是 BOM 对象之一,它提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。事实上,location 对象是 window 对象的属性,也是 document 对象的属性;所以 window.location 和 document.location 等效。

alert(location); 							// 获取当前的 URL

location 对象的属性:

属性

描述的 URL 内容

hash

如果该部分存在,表示锚点部分

host

主机名:端口号

hostname

主机名

href

整个 URL

pathname

路径名

port

端口号

protocol

协议部分

search

查询字符串

location 对象的方法:

方法

功能

assign()

跳转到指定页面,与 href 等效

reload()

重载当前 URL

repalce()

用新的 URL 替换当前页面

location.hash = '#1'; 							// 设置#后的字符串,并跳转
alert(location.hash); 							// 获取#后的字符串
location.port = 8888; 							// 设置端口号,并跳转
alert(location.port); 							// 获取当前端口号,
location.hostname = 'Lee'; 						// 设置主机名,并跳转
alert(location.hostname); 						// 获取当前主机名,
location.pathname = 'Lee'; 						// 设置当前路径,并跳转
alert(location.pathname); 						// 获取当前路径
location.protocal = 'ftp:'; 					// 设置协议,没有跳转
alert(location.protocol); 						// 获取当前协议
location.search = '?id=5'; 						// 设置?后的字符串,并跳转
alert(location.search); 						// 获取?后的字符串
location.href = 'http://www.baidu.com'; 		// 设置跳转的 URL,并跳转
alert(location.href); 							// 获取当前的 URL

在 Web 开发中,我们经常需要获取诸如?id=5&search=ok 这种类型的 URL 的键值对,那么通过 location,我们可以写一个函数,来一一获取。

function getArgs() {
	// 创建一个存放键值对的数组
	var args = [];
	// 去除?号
	var qs = location.search.length > 0 ? location.search.substring(1) : '';
	// 按&字符串拆分数组
	var items = qs.split('&');
	var item = null, name = null, value = null;
	// 遍历
	for (var i = 0; i < items.length; i++) {
		item = items[i].split('=');
		name = item[0];
		value = item[1];
		// 把键值对存放到数组中去
		args[name] = value;
	}
	return args;
}
var args = getArgs();
alert(args['id']);
alert(args['search']);
location.assign('http://www.baidu.com'); 		// 跳转到指定的 URL
location.reload(); 								// 最有效的重新加载,有可能从缓存加载
location.reload(true); 							// 强制加载,从服务器源头重新加载
location.replace('http://www.baidu.com'); 		// 可以避免产生跳转前的历史记录

history 对象

history 对象是 window 对象的属性,它保存着用户上网的记录,从窗口被打开的那一刻 算起。 history 对象的属性:

属性

描述 URL 中的哪部分

length

history 对象中的记录数

history 对象的方法:

方法

功能

back()

前往浏览器历史条目前一个 URL,类似后退

forward()

前往浏览器历史条目下一个 URL,类似前进

go(num)

浏览器在 history 对象中向前或向后

function back() { 								// 跳转到前一个 URL
	history.back();
}
function forward() { 							// 跳转到下一个 URL
	history.forward();
}
function go(num) { 								// 跳转指定历史记录的 URL
	history.go(num);
}

可以通过判断 history.length == 0,得到是否有历史记录。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • CSS中的传统布局、多列布局、弹性伸缩布局及Emmet工具

    在早期没有平板和智能手机等移动设备大行其道的时期,Web 页面的设计主要是面向 PC 端电脑分辨率展开的。这种分辨率比例比较单一,基本上只要满足最低分辨率设计即...

    魏晓蕾
  • JavaScript简介及JavaScript中的关键保留字、变量和数据类型

    JavaScript 诞生于 1995 年。它当时的目的是为了进行表单输入的验证。因为在 JavaScript 问世之前,表单的验证都是通过服务器端验证的。而当...

    魏晓蕾
  • 网格计算

    版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/gon...

    魏晓蕾
  • JavaScript基础

    一 JavaScript的基础 1.1 JS的引入方式 1 直接编写 <script> alert('hello yuan') ...

    用户1214487
  • 函数基础知识回顾

      String    Number   Boolean   Null    undefined    //占有固定的内存大小,如数值型占八个字节,布尔类型...

    用户3159471
  • 浅谈js的内存与闭包0.前言1.先说类型2.再说顺序3.然后到了函数4.接着是临时空间5.垃圾回收6.IIFE和闭包

    主要结合了内存的概念讲了js的一些的很简单、但是又不小心就犯错的地方。 结论:js执行顺序,先定义,后执行,从上到下,就近原则。闭包可以让外部访问某函数内部变量...

    lhyt
  • 前端学习之JavaScript

    尽管 ECMAScript 是一个重要的标准,但它并不是 JavaScript 唯一的部分,当然,也不是唯一被标准化的部分。实际上,一个完整的 JavaScri...

    超蛋lhy
  • 腾讯数据中心第三代供电架构探秘(一)概述篇

    【背景】:随着腾讯海量服务器的发展,高昂的运营费用将成为沉重的负担。虽然传统UPS供电架构相对成熟,但依然存在设备成本高,配电结构复杂,自损耗高等问题。为提供年...

    腾讯数据中心
  • 链表问题

    A stringSof lowercase letters is given. We want to partition this string into as...

    大学里的混子
  • Python爬虫进阶必备 | XX文书网加密分析-20190902版

    目前该网站已经更换了加密算法,主要原因是原算法太简单,9月2日更新的算法9月3日访问网站已经感觉到明显卡顿,防护并不是很到位。

    咸鱼学Python

扫码关注云+社区

领取腾讯云代金券