匿名函数
匿名函数就是没有名字的函数
(function () {
alert("匿名函数()");
})
//匿名函数的调用
(function () { alert("匿名函数()");})();
(function (name) { alert(name);})("lisi");
var s = (function (name) {
return name;})("zhangsan");
alert(s); //zhangsan
alert( (function (name) { return name;})("zhangsan"));
//把匿名函数赋值给一个变量
var m = function(){
alert("ha");
};
m(); //ha
var b = function(name){ alert(name);};b("xiaoli");
var a = function(name){ return name;};alert(a("xiaoli"));
闭包
1定义:在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
function show(){
var name = "lisi";
return function(){
return name;
}; //闭包 这个函数是个引用类型的对象,所以可以用一个变量接收一下 如①
}
var fun = show(); ①
fun(); //就是在调用紫色部分那个函数
或者:show()(); 这也是在调用紫色部分函数
2好处:
例:实现一个变量的累加
function add(){
var age = 10;
age++;
return age;
}
alert(add());//11
alert(add());//11解释:每次调用add函数时会给age开辟内存,结束时释放内存,函数每次调用时,局部变量开辟内存,函数调用结束时,局部变量释放内存。
局部变量不能实现每次调用age++,解决这个问题可用全局变量,但是全局变量是公共的,任何函数都可以使用,容易出现问题,所以尽量少用全局变量,为了解决这个问题,让age的值逐渐递增使用闭包。
function add1(){ var age = 10; return function(){ age++; return age; };}var func = add1();
alert(func());//11
alert(func());//12而
alert(func());//13
解释:反复调用的是func(),而add1()只调用了一次;闭包使用的局部变量,不会立刻释放内存,会在内存驻留一段时间。
注意:尽量少使用闭包,在必要时再使用闭包
3在循环中使用闭包:
function fun(){
var arr =[];
for(var i = 0;i<3 ; i++){
arr[i] =function (){
return i;
};
}
return arr;
}
var a = fun();
for(var j = 0; j<a.length; j++){
alert(a[j]()); //a[j] 代表的是一个函数 调用这个函数a[j]() 运行后显示是 3 3 3
}
function fun(){ var arr =[]; for(var i = 0;i<3 ; i++){ arr[i] =(function (num){ return num; })(i); //改成了函数调用,当i= 0 时,num = 0,返回0放在arr[0]中 } return arr;}var a = fun();for(var j = 0; j<a.length; j++){ alert(a[j]); //012}
//用闭包实现如下:
function fun(){ var arr =[]; for(var i = 0;i<3 ; i++){ arr[i] =(function (num){ return frunction(){ return num; }; })(i); } return arr;}var a = fun();for(var j = 0; j<a.length; j++){ alert(a[j]()); //012 闭包中的局部变量会长时间驻留,所以 012都不会立刻消失}
4闭包中this的特点
闭包中的this在运行时指向windw,因为闭包并不属于这个对象的属性或方法。
var obj ={
name:"lisi",
fun:function(){
return function(){
return this;
};
}
};
var a = obj.fun();
a(); //返回的this指向的是window
var name = "window";
var obj2 ={ name:"object", fun:function(){ return function(){ return this.name; }; }};alert(obj2.fun()()); //window
alert(obj2.fun().call(obj2) ); //对象 冒充 显示 object
var name = "window";
var obj2 ={ name:"object", fun:function(){ var t = this; //obj2 return function(){ return t.name; //引用之间的赋值 }; }};alert(obj2.fun()()); //object
5块级作用域
js中不存在块级作用域 if(){} for(){}
实现for循环结束时,变量i的作用域结束,i在内存中消失
//模拟块级作用域(私有作用域)
(function () {
//作用域
})();
//在之后做项目中会经常用到,在项目中,尽量少使用全局的变量和函数,多用块级作用域
function fun(){
(function(){
for(var i = 1; i<=3;i++){ alert(i); }
})(); //匿名函数执行完时(i相当于其中的局部变量,)i的作用域结束,从内存中释放了
alert(i); //访问不到了
}
fun();
6私有变量、静态私有变量
(1)私有变量
function show(){
var num = 5; //私有变量(局部变量)
function test(){ //私有函数(局部函数)
return "我是局部函数";
}
this.test = function(){
return num + test();
}
}
var s = new show();
s.test(); //可以通过公共的访问私有的
function Test(){
this.name ="lisi"; //公共属性
this.fun = function(){ //公共函数
alert(this.name);
}
} (这是一个构造函数)
var t1 = new Test();
alert(t1.name);
t1.fun();
//使用构造函数的传参访问私有变量
function Person(value){
var user = value; //私有变量
this.getUser = function(){ //公共的
return user;
}
this.setUser = function(v){
user = v;
}
}
var person = new Person("hello");
alert(person.getUset());
person.setUser("hai");
alert(person.getUset());
(2)静态私有变量:所有对象共享的局部变量(在内存中只有一块)
//让一个私有变量,被所有对象共享
//块级作用域
(function(){
var country = ''; //静态私有变量
//这是一个全局的Person
Person = function(value){
country = value;
}
Person.prototype.setCountry = function(c){ //提到共享应想到原型 country = c; }
Person.prototype.getCountry = function(){ return country; }
})();
var ren = new Person("usa");
var ren2 = new Person("china");alert(ren2.getCountry()); //china
alert(ren.getCountry()); //china 因为只有一个country
7访问私有变量和私有函数的其他方式
(1)块级作用域+字面量 方式访问私有变量,私有函数
var objs = (function(){
var name = "zhang"; //私有变量
function show(){ //私有函数
return “我爱编程”;
}
return {
go:function(){
return name+show();
}
} //字面量对象
})();
alert(objs.go()) ; //zhang我爱编程
细节:如果块级作用域赋给一个变量,绿色小括号可以省略()
var objs = function(){ var name = "zhang"; //私有变量 function show(){ //私有函数 return “我爱编程”; } var o = { go:function(){ return name+show(); } }; return o; //这个o是个引用,指向的是这个字面量对象,最后返回的这个字面量对象}();
(2)块级作用域+构造函数 方式访问私有变量,私有函数
function Test(){}
var oo = function(){ var name = "zhang"; //私有变量 function show(){ //私有函数 return “我爱编程”; } var t = new Test(); t.go=function(){ return name+show(); } return t; }();alert(oo.go());