javaScriptFunction(函数)闭包匿名函数this对象
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
javaScriptFunction(函数)闭包匿名函数this对象
1. Function
函数接受的参数类型、个数没有限定。
参数在内部是⽤数组arguments来存储的。
因此函数没有重载。
可以提供arguments【i】来表⽰传⼊的参数
4.1创建
使⽤函数声明和函数表达式创建,也可以使⽤Function()构造函数
Function sum(num1,num2){
函数声明
}
Var sum = function(num1,num2){
函数表达式
}
解析器会率先读取函数声明,并使其在执⾏任何代码之前可⽤;因为在代码执⾏之前,解析器就已经通过⼀个名为函数声明提升的过程,读取并将函数声明添加到执⾏环境,js引擎在第⼀遍会声明函数并将它们放到源代码树的顶部。
函数表达式须等到解析器执⾏到它所在代码⾏,才会真正被解析。
4.2函数内部属性
Arguments指代参数
Callee:arguments.callee指代拥有这个arguments对象的函数。
在递归调⽤时,⾮常有⽤。
Caller:保存着调⽤当前函数的函数的引⽤
Function outer(){
Inner();
}
Function inner(){
Alert(inner.caller);//警告框中显⽰outer()函数的源代码,等价于arguments.callee.caller
}
This:this引⽤的是函数据以执⾏的环境对象。
4.3 call()和apply()扩⼤函数赖以运⾏的作⽤域
每个函数都包含这两个⾮继承⽽来的⽅法。
这两个⽅法⽤途都是在特定的作⽤域⾥调⽤函数,实际上是设置函数体内的this值。
Apply()接受2个参数,⼀个是其中函数运⾏的作⽤域,另⼀个是参数数组
Call()接受多个参数,⼀个是其中函数运⾏的作⽤域,其他是传递给函数的参数必须逐个列举出来
Window.color = “red”;
Var o = {
Color:”blue”
};
Function sayColor(){
Alert(this.color);
}
sayColor(); //red
sayColor.call(window); //red
sayColor.call(this); //red
sayColor(o); //blue
4.4java与js创建函数
Java是:修饰符返回类型函数名(参数类型参数名){
函数体
}
Js是:函数声明和函数表达式
函数声明:function 函数名(参数名){
函数体
}
函数表达式:var 函数名 = function(参数名){
函数体
}
4.5匿名函数
在function后⾯没有跟函数名的函数称为匿名函数。
例如:
function(){
函数体
}
1.6 闭包
4.6.1闭包作⽤域链
闭包是有权访问另⼀个函数作⽤域中变量的函数。
因此任何函数都是闭包。
当某函数第⼀次被调⽤时,会创建⼀个执⾏环境及相应的作⽤域链,并把作⽤域链赋值给⼀个特殊的内部属性即[[scope]]。
然后使⽤this、arguments和其他命名参数的值来初始化函数的活动对象。
由此得出,js中所有函数都是闭包。
在全局环境中定义compare函数:
function compare(value1,value2){
if(value1 < value2){
return -1;
}else if(value1 > value2){
return 1;
}else{
return 0;
}
}
var result = compare(5,10);
在创建compare()函数时,会创建⼀个预先包含全局变量对象的作⽤域链,并保存在[[scope]]。
当调⽤compare()函数时,会创建⼀个包含this、arguments、value1、value2的活动对象。
此刻compare()执⾏环境的作⽤域链(scope)是[[scope]]+活动对象。
Scope可以看出数组,活动对象在最前⾯,[[scope]]在后⾯。
函数在创建时获得函数的[[scope]],通过该属性访问到所有⽗上⽂的变量。
同⼀个⽗上下⽂中创建的闭包是共⽤⼀个[[scope]],其中⼀个闭包对[[scope]]修改会影响到其他闭包
每个执⾏环境都有⼀个表⽰变量的对象,全局环境的变量对象⼀直存在,局部函数的执⾏环境也有变量对象,但只在函数执⾏的过程中存在(闭包除外)。
4.6.2闭包中的变量
当你弄清作⽤域链,你对闭包中变量的取值将会很清楚。
在这⾥,我将再举⼀个例⼦,说明下作⽤域链。
var x = 10;
function foo(){
var y = 20;
function bar(){
var z = 30;
alert(x+y+z);
}
bar();
}
foo();
在创建foo函数时,此时会创建⼀个包含x为10的全局作⽤域。
同⼀个⽗上下⽂中创建的闭包是共⽤⼀个[[scope]],其中⼀个闭包对[[scope]]修改会影响到其他闭包。
function fee(){
var data = [];
for(var k=0;k<3;k++){
data[k] = function(){
return k
}
}
return data;
}
console.log(fee());//返回值如下
/*[function (){
return k
}, function (){
return k
}, function (){
return k
}]*/
由此可见,返回的是k值,⽽这个k存在⽗上下⽂中,所以data⾥存相同的数值。
当将data[k] = function(){return k}改为
data[k] = function(num){
return function(){return num}
}(k);此时data存不同的值。
4.6.2关于this对象
在全局函数中,this等于window,⽽当函数被某个对象调⽤时,this指代那个对象。
但是匿名函数不⼀样,他的执⾏环境具有全局性,其this 指代window。
var name = "lily";
var object = {
name : "my name",
getName : function(){
alert(); //my name
return function(){
return ; //lily
}
}
};
alert(object.getName()()); //my name,lily
在每个函数被调⽤时其活动对象都会⾃动获取this和arguments。
内部函数在搜索这两个变量时,只会搜索到其活动对象为⽌,不可能去访问⽗上下⽂。
看下⾯的例⼦
var name = "lily";
var person = {
name : "my name",
getName : function(){
var that = this;
return function(){
return ; //my name }
}
};
alert(person.getName()()); //my name
此刻就可以让闭包访问person对象了。
4.6.2模仿块级作⽤域
Js没有块级作⽤域,这个跟其他⾯向对象语⾔不⼀样。
例如: for(var i = 0 ; i< 3; i++){
alert(i);
}
alert(i); //3
⽤块级作⽤域(通常称为私有作⽤域)的匿名函数的语法如下:
(function(){
//这⾥是块级作⽤域。
这⾥的变量⼀旦等到该函数执⾏完就被销毁。
})();
function(){}();会报错,这是因为js会将function关键字当做函数声明的开始,⽽函数声明后⾯不能加()。
⽽函数表达式后⾯可以跟(),例如:
var lulu = function(){alert(895);}();
只要是临时需要变量,可以使⽤私有作⽤域。
例如: function out(count){
(function(){for(var i = 0 ; i< count; i++){
alert(i);
})();
alert(i);//此时会报错,i是⼀个没有声明的变量。
}
out(3);
变量i只能在循环中使⽤,使⽤后被销毁。
⽽在私有作⽤域中能过访问⽗上下⽂的变量,因为匿名函数是⼀个闭包。
这种技术经常⽤在函数外部,从⽽限制全局作⽤域中添加过多的变量和函数。
减少闭包占⽤内存的问题。