闭包的理解及常见实例解析

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<button onclick="move()">点我跳转</button>
<script>
//闭包
function f1() {
var n = 999;

function f2() {
alert(n);
}

return f2;//其实此时的函数f2就是一个闭包,其实闭包就是能够读取其他函数内部变量的函数
//在javascript中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成‘定义在一个函数内部的函数’,即闭包的本质就是
//将函数内部和函数外部链接起来的一座桥梁
}
f1()();

//用途 1.可以读取函数内部的变量;2.让这些变量的值始终保持在内存中
function f3() {
var n = 999;
nAdd = function () {
n += 1;
};
function f4() {
alert(n);
}

return f4;
}
var result = f3();
result();//在这里result其实就是闭包f2函数,此时result是一个全局的变量,函数nAdd也是全局的变量,
// 说白了其实就是通过全局变量来操作局部变量,而且f2是f1大的子函数,f2被赋给了一个全局的变量,导致f2一直在内存中
//而f2的存在依赖于f1,所以,f1也一直存在在内存中,调用结束后,不会被垃圾回收机制所回收。,nAdd其实也是一个闭包
nAdd();
result();

//使用闭包的注意点
//1.闭包会使得变量一直存在内存中,内存消耗大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中会导致内存的泄露,
//解决办法是 在退出函数之前,将不使用的局部变量全部删除。
//2.闭包会在父函数的外部,改变夫函数的值。所以,如果你把父函数当作对象使用,把闭包当作它的公用的方法,把内部变量当作它的
//私有属性,这时要小心,不要随便的改变父函数内部变量的值;
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());//The Window

var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());//My Object


// //常见的经典实例
var points = [
{x: 0, y: 0}, {x: 1, y: 1}
];
//这里的this指代的是points数组中对象
points.dist = function () {
var p1 = this[0];
var p2 = this[1];
var a = p2.x - p1.x;
var b = p2.y - p1.y;
return Math.sqrt(a * a + b * b);
};
console.log(points.dist());

//阶乘的表示函数1
function fn(n) {
var i, product = 1;
for (i = 2; i <= n; i++) {
product *= i;
}
return product;
}
console.log(fn(5));//120
//阶乘的表示函数2
function fn1(n1) {
var product1 = 1;
while (n1 > 1) {
product1 *= n1;
n1--;
}
return product1;
}
console.log(fn1(5));//120

//实例化对象 并赋方法,计算该点到原点的距离、
function Point(x1, y1) {
this.x1 = x1;//this指代初始化的实例
this.y1 = y1;
}
var p = new Point(1, 1);
Point.prototype.r = function () {
return Math.sqrt(
this.x1 * this.x1 + this.y1 * this.y1
);
};
p.r();
document.write(p.r());

function move() {
var answer = confirm(" Are you sure exit");
if (answer) {
window.location = "http://www.baidu.com";
}
setTimeout(move, 3000);
}
var a1 = [3, 1, 5, 2, 7, 4];
console.log(a1.sort());

var a = {};
b = {"key": "1"};
c = {"key": "c"};
a[b] = 123;
console.log(a);//{{object object}:123}
a[c] = 678;
console.log(a[b]);//678;
console.log(a);//{{object object}:678}
class Dog {
constructor() {
this.type = 'dog';
}

says(say) {
setTimeout(function () {
console.log(this.type + 'says' + say);
}, 1000)
}
}
var dog = new Dog();
// anmial.says("hi");//anmial is not defined
dog.says("hi");//undefinedsayshi;

var newObject = {
foo: "bar",
func: function () {
var self = this;
console.log("outer func:this.foo=" + this.foo);////outer func:this.foo=bar
console.log("outer func:self.foo=" + self.foo);//outer func:self.foo=bar
(function () {
console.log("inner func:this.foo=" + this.foo);//inner func:this.foo=undefined
console.log("inner func:self.foo=" + self.foo);//inner func:self.foo=bar
}());
}
};
newObject.func();//undefinedsayshi
</script>
<!--定时器实现多长时间后跳转的问题-->
<p style="text-indent: 2em; margin-top: 30px;">
系统将在 <span id="time">10</span> 秒钟后自动跳转至新网址,如果未能跳转,<a href="http://www.baidu.com" title="点击访问">请点击</a>。</p>
<script type="text/javascript">
delayURL();
function delayURL() {
var delay = document.getElementById("time").innerHTML;
var t = setTimeout("delayURL()", 1000);
if (delay > 0) {
delay--;
document.getElementById("time").innerHTML = delay;
} else {
clearTimeout(t);
window.location.href = "http://www.baidu.com";
}
}
;
var a = document.createElement('div');
a.id = "add";
a.innerHTML = "<h1>大家好</h1>";
document.body.appendChild(a);
</script>

</body>
</html>
posted @ 2017-10-09 10:58  johnny-cli  阅读(207)  评论(0编辑  收藏  举报