java js中 function函数报错_javaScript Function(函数) 闭包 匿名函数 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]]在后面。

2e2d6bc9c07a8f2a8ba9d28e0d7e4196.png

函数在创建时获得函数的[[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的全局作用域。

cbc0a4bb9ad3c9258833f48b76bf6fc0.png

同一个父上下文中创建的闭包是共用一个[[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(this.name); //my name

return function(){

return this.name; //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 this.name; //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只能在循环中使用,使用后被销毁。而在私有作用域中能过访问父上下文的变量,因为匿名函数是一个闭包。

这种技术经常用在函数外部,从而限制全局作用域中添加过多的变量和函数。减少闭包占用内存的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值