Javascript中Function类型(不能错过!)

没有重载

由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其它变量没有什么不同。 将函数名想象为指针,也有助于理解为什么ECMAScript中没有函数重载的概念。

函数声明与函数表达式

解析器会率先读取函数声明,并使其在执行任何代码之前可用(可用访问);至于函数表达式,
	  则必须等到解析器执行到它所在的代码行,才会真正被解释执行
          如下;函数可以正常执行:
         
1      console.log(sum(10,10));
2         function sum(num1,num2){
3             return num1 + num2;
4         }


         但是,如果像下面把函数声明该为等价的函数表达式,就会在执行期间导致错误;
1 //        console.log(sum1(10,10));
2 //        var sum1 = function(num1,num2){
3 //            return num1 + num2;
4 //        }


        

作为值的函数

因为ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,
	不仅可以像传递参数一样把一个函数传递给另一个函数,
	而且可以将一个函数作为另一个函数的结果返回。
         
         
 1      function callSomeFunction(someFunction,someArgument){
 2             return someFunction(someArgument)
 3         }
 4 
 5         function add10(num){
 6             return num + 10;
 7         }
 8         var result = callSomeFunction(add10,10);
 9         console.log(result);  // 20
10         function getGreeting(name){
11             return "Hello,"+name;
12         }
13         var result1 = callSomeFunction(getGreeting,'Andy');
14         console.log(result1);//  Hello,Andy



       

函数内部属性

在函数内部,有两个特殊的对象:arguments 和 this。
	  虽然arguments的主要用途是保存函数参数,但这个对象还有一个名叫callee的属性,
	  该属性是一个指针,指向拥有arguments对象的函数
          如下面的阶乘函数
          
1      function factorial(num){
2             if(num <=1){
3                 return 1;
4             }else{
5                 return num*factorial(num-1);
6             }
7         }


         上面的函数,这样定义没有问题,但问题是这个函数的执行与函数名factorail紧紧耦合在了一起。
	 为了消除这种紧密耦合的现象,可以使用arguments.calllee
1     function f1(num){
2             if(num <=1){
3                 return 1;
4             }else{
5                 return num * arguments.callee(num - 1);
6             }
7         }


        
        函数内部的另一个特殊对象是this。this引用的是函数据以执行的环境对象---
	或者也可以说是this值(当网页的全局作用域中调用函数时,this对象引用的就是window)。
         

        
        ECMAScript 5规范化了两一个函数对象的属性:caller。
	除了Opera的早期版本不支持,其他浏览器都支持这个ECMAScript 3 并没有定义的属性。
        这个属性中保存着调用当前函数的引用,如果在全局作用域中调用当前函数,它的值为null;
         

 1 function outer(){
 2             inner();
 3         }
 4         function inner(){
 5             console.log(inner.caller);  // 会显示outer()函数的源代码。因为outer()调用了inner(),所以inner.caller就指向outer()。
 6         }
 7         outer();
 8         // 为了实现更松散的耦合,也可通过arguments.callee.caller来访问相同的信息。
 9         function outer1(){
10             inner1();
11         }
12         function inner1(){
13             console.log(arguments.callee.caller);
14         }
15         outer1();



        总结:
        当函数在严格模式下运行时,访问arguments.callee会导致错误。
	ECMAScript 5 还定义了arguments.caller属性,但在严格模式下访问它也会导致错误,
	而在非严格模式下这个属性始终是undefined。
          定义这个属性是为了分清arguments.caller和函数的caller属性。
          严格模式下还有一个限制:不能为函数的caller属性赋值,否则会导致错误。
          

        

函数属性和方法:

ECMAScript 中的函数是对象,因此函数也有属性和方法。
	  每个函数都包含两个属性:length 和 prototype。
         
         
 1       function sayName(name){
 2             console.log(name);
 3         }
 4         function sum1(num1,num2){
 5             return num1 + num2;
 6         }
 7         function sayHi(){
 8             console.log('hi,andy!')
 9         }
10         console.log(sayName.length);  // 1
11         console.log(sum1.length);  //2
12         console.log(sayHi.length); //0


        
        在ECMAScript 核心所定义的全部属性中,最耐人寻味的就是输prototype属性了。
	如toString()和valueOf()等方法实际上都保存prototype名下,
	只不过是通过各自对象的实例拜访罢了。
          在ECMAScript 5中,prototype属性是不可枚举的,因此使用for-in无法实现。
          每个函数都包含两个非继承而来的方法:apply()和call()。
	  这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
          apply()方法接收两个参数:一是在其中运行函数的作用域,另一个是参数数组。
	  其中,第二个参数可以是Array的实例,也可以是arguments对象。
          call()方法和apply()方法作用相同,它们的区别仅在于接收参数的方式不同。
          

 1        function sum2(num1,num2){
 2             return num1 + num2;
 3         }
 4         function callSum2(num1,num2){
 5             return sum2.apply(this,arguments);
 6         }
 7         function callSum3(num1,num2){
 8             return sum2.apply(this,[num1,num2]);
 9         }
10         console.log(callSum2(10,10));  // 20
11         console.log(callSum3(10,10));   //20
12         // 在严格模式下,未指定环境对象而调用函数,则this值不会转型为window。除非明确把函数添加到某个对象或者调用apply()或call()。
		否则this值是undefined;
13 
14         function callSum4(num1,num2){
15             return sum2.call(this,num1,num2);
16         }
17         console.log(callSum4(10,10));  // 20



         总结:事实上,传递参数并非apply()和call()真正的用武之地;
	它们正真强大的地方是能够扩充函数赖以运行的作用域。
1       window.color = 'red';
2         var o = {color:'blue'};
3         function sayColor(){
4             console.log(this.color);  // red
5         }
6         sayColor();
7         sayColor.call(this); // red
8         sayColor.call(window);// red
9         sayColor.call(0);// blue


        
          ECMAScript 5还定义了一个方法:bind();
	这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的 值
         支持bind()方法的浏览器有IE9+......
         
1         window.color1 = 'red';
2         var o1 ={color1:'blue'};
3         function sayColor1(){
4             console.log(this.color1);
5         }
6         var objectSayColor1= sayColor1.bind(o1);
7         objectSayColor1();// blue

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值