闭包中的this对象
我们知道this对象是运行时基于函数的执行环境绑定的,在全局环境中,this就等于window,而当函数作为某个对象的方法调用时,this等于这个对象。不过,当我们在闭包中使用this就会导致一些问题,因为匿名函数的执行环境具有全局性,因此this对象通常指向window。但是有时候由于编写闭包的方式不同,这一点也就不明显
//匿名函数的全局性
var name="The window";
(function(){
var name="jack";
alert(this.name)
})()
//对象中的匿名函数
var name="The window";
var obj={
name:"My Object",
getNameFunc:function(){
return function(){
return this.name;
}()
}
}
alert((obj.getNameFunc()))//The window
每个函数被调用时都会自动获取到两个特殊变量:this和arguments,内部函数在搜索这两个变量的时候,只会搜索到其活动对象为止,因此永远不可能直接访问到外部函数中这两个变量,只会访问到其活动对象为止,因此永远不可能直接访问到外部函数中的这两个变量。不过把外部作用域的this放在闭包中就能够访问到变量
var name="the window";
var object={
name:"my object",
getName:function(){
var that=this;
return function(){
return (that.name)
}
}
}
alert(object.getName()())
内存泄漏问题
闭包并非只有好处没有坏处,如果闭包的作用域链中保存着一个HTML元素,那么就意味着该元素无法被销毁。用完之后请将闭包修改为Null
(function assign(){
var element=document.getElementById("some");
element.innerHTML="textPage"
element.onclick=function(){
alert(element.id)
}
element=null;
})()
私有变量
严格来讲,Javascript中没有私有成员的概念,所有对象属性都是公有的。不过倒是有一个私有变量的概念。任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问到这些变量。私有变量包括函数的参数、局部变量、其他函数
function(a,b){
var sum=a+b;
return sum;
}
在上面的例子中,a,b,sum就是私有变量。在函数内部可以访问这几个变量,但是在外部却不能访问到这些变量。如果我们在内部创建一个闭包,那么闭包通过自己的域链也可以访问到这些变量。而利用这一点,我们就能创建用于访问私有变量的公有方法。
function MyObject(){
var privateA=10;
function privateReturn(){
return false;
}
this.publicMethod=function(){
console.log(privateA)//10
return privateReturn();
}
}
var a=new MyObject()
console.log(a.publicMethod())//false
我们能够通过这种方法隐藏哪些不应该被直接修改的数据
function Person(name){
this.getName=function(){
return name;
}
this.setName=function(value){
name=value
}
}
var person=new Person("ROTK");
console.log(person.getName());//ROTK
person.setName("burning");
console.log(person.getName());//burning
静态私有变量
(function(){
var name="";
Person=function(value){
name=value;
}
Person.prototype.getName=function(){
return name;
}
Person.prototype.setName=function(value){
name=value;
}
})()
var person1=new Person("burning");
person1.setName("ZSMJ");
var person2=new Person("Rotk");
console.log(person2.getName())//ROTK
console.log(person1.getName())//ROTK