zoukankan      html  css  js  c++  java
  • Javascript 函数初探


          在 Javascript 中, 函数是“一等公民”, 它是 Javascript 的中心对象。

           1.  函数是值,可以用在值被用到的任何地方。 可以存储在变量中, 用于表达式中,放在数组里, 放在对象的值对里, 作为参数传入函数, 作为函数返回值;
           2.  函数是对象, 可以拥有数据属性, 拥有方法, 指向原型对象;
           3.  函数拥有可调用的代码块,有多种调用模式; 可以制造闭包和回调, 这两种编程模式是非常强大的。

           代码运行:  打开 chrome 浏览器, 工具 --- Javascript 控制台。 

           参考文献:  
              
               《Javascript: The Good Parts》 Douglas Crockford
           

           一.   函数是值 

           让我们从最常规的函数调用形式开始吧! 

           1.  函数存储在变量中。

           先看一段普通的代码: 

    function numAdd(a,b) {
                 return a+b;
           } 
           numAdd(5, 7);

          实际上,它的含义是:
          

    var numAdd = function(a,b) {
                 return a+b;
           }
           numAdd(5, 7);

           函数对象被存储在变量 numAdd 中, 可以通过该变量进行引用;

           2.  函数用于表达式中

    var  choice =  function(boolvar) {
                  return  boolvar ?  function(num) { return num*num }  :  function(num) {  return num / 2; }
           }   
           var  square = choice(true);
           square(2);   // print 4
           var  half = choice(false);
           half(4);       //  print 2      

           这段代码根据传入的布尔值, 分别返回不同的函数对象; 如果为真, 则返回平方值函数, 如果为假,则返回取半函数。 它也演示了函数如何作为返回值。

          3.  函数作为参数传入函数

    var worker = function(callback) {
              var arrparams = [1, 2, 3, 4, 5];  
              callback(arrparams);
          };
          worker(function(arrparams) {
                document.write('You get me print it !');
                document.write(arrparams.join(' '));
          });
          worker(function(arrparams) {
                document.write('You get me print it reversed !');
                var reversed = arrparams.reverse();
                document.write(reversed.join(' '));
          });

          函数作为参数传入函数, 可以演变成回调。 回调是一种非常强大的编程模式。回调请参考文章 《编程模式:回调》


          4.  函数作为对象的值对

    var person = { 
                  name : 'Shuqin',
                  say :  function() {
                        document.write("I am " + this.name);
                  }  
           }
           person.say();

          上述代码演示了 Javascript 中的对象封装基本方法。

          
           二、 函数是对象
           对象拥有数据属性, 拥有方法, 拥有原型对象。 函数的原型对象是 Function.prototype .  继续前面的例子:

    worker.salary = '6K';
           document.write("My salary is " + worker.salary);     
    
           document.write("My type is " + worker.typename);  
           Function.prototype.typename =  'func';   // 将所有函数的 typename 属性设置为 func 
           document.write("My type is " + worker.typename);  
           document.write("My type is " + choice.typename);  
             
           Function.prototype.fsay = function() {   // 为所有函数添加 fsay 方法
                  document.write('Hey, i am a function, the first class object in javascript');
           }
           worker.fsay();
           choice.fsay();
    
           worker.mycareer = function(career) {   // 仅为 worker 函数添加方法
                  document.write('I am worker ' + career);
           }
           worker.mycareer(' a programmer');
           choice.mycareer(' a choice');   // Error: Has no method 'mycareer'

          基于原型的继承机制的最大优点就是动态灵活, 可以在运行时动态地添加任何属性和方法。 当然, 过度滥用会导致混乱。     


          三、 闭包

          函数可以嵌套在另一函数中, 内层函数可以访问外层函数的私有变量,从而延伸了其作用域。
          

    var secretMan = function() {
                var count = 1;
                var secret = 'very very important secret.  Poison case happened in tsinghua 19 years ago';
                return function() {
                      count +=1;
                      return secret + " ********* " + count;    
                }
          }
          document.write("The secret: " + secret);  //Error: ReferenceError: secret is not defined
          var revealTruth = secretMan();
          document.write('Now is the time to reveal it out: ' + revealTruth());
          // 页面打印: Now is the time to reveal it out: very very important secret. Poison case happened in tsinghua 19 years ago ********* 2
          document.write('Now is the time to reveal it out: ' + revealTruth());
          // 页面打印: Now is the time to reveal it out: very very important secret. Poison case happened in tsinghua 19 years ago ********* 3

          注意到, 当执行完 var revealTruth = secretMan() 之后, 作为局部变量的 count,  secret 均应该退出其作用域(退出参数栈而不存), 但由于内层函数的存在,它们依然存在着并可以继续使用, 例如 在 第二遍 revealTruth() 调用时依然可以访问 count 的值。

          四、 调用模式与 this

          函数有四种调用模式: 通过变量引用, 通过对象方法, 通过构造器, 通过 apply 函数.

             1.  变量引用: 将函数对象存储在变量中, 从而通过变量引用来调用。 this 绑定在全局对象中;
             2.  对象方法: 函数作为对象方法而调用, this 动态绑定给当前调用函数的对象; 绑定发生在调用时;
             3.  构造器: 函数用于创建和初始化新对象,  this 绑定给新创建的对象;
             4.  apply :   函数作为参数传入 apply 函数, this 绑定给指定的对象。 

             第一种情况:
             

    var outer = function() {
                   document.write('Outer this: ' + this);     // [object Window]
                   var inner = function() {
                        document.write('Inner this: ' + this);  // [object Window]
                    };
                    inner();
             }
             outer();

             第二种情况:      

    var person = { 
                  name : 'Shuqin',
                  sayme :  function() {
                        document.write("Object this: " + this.name);   // Shuqin
                        ( function() {
                               document.write('Inner this: ' + this);  // [object Window] , this 被切换了!
                         })();
                  }  
           }
           person.sayme();  

          第三种情况:
         

    var Man =  function(name, power) {
                  this.name =  name;   // this 绑定到将要被创建的新对象
                  this.sex = 'Man';
                  this.power = power;
                  this.ability = function() {
                        document.write('Name: ' + this.name + 'Sex: ' + this.sex + 'Power: ' + this.power);
                        if (this.power < 80) {
                             document.write('Oh, no , you power is little, you must strengthen it!');
                        }
                  }
           }  
           var me = new Man('Shuqin', 60);
           me.ability();

           第四种情况:      
           

    var  generalsum = function(callback, args) {
                  document.write("generalsum this: " + this);
                  var result = 0;
                  var caller ;
                  if (typeof this == 'function') {  
                        caller = this;  
                  }
                  else {
                        caller = callback;
                   }
                   document.write((typeof caller) + ' ' + args.join(' '))
                   for (i=0; i < args.length; i++) {
                        result += caller(args[i]);
                         document.write(result);
                   }
                   return result; 
            };      
            var plainsumdef = function(num) { return num; } 
            generalsum(plainsumdef, [1, 2, 3, 4, 5]);   // this: [object Window]
            var plainsum = generalsum.apply(plainsumdef, [null, [1,2,3,4,5]]);  // this: function (num) { return num; }

           在这种情况下, this 被绑定到指定对象。

             

            小结

            本文初步探讨了 Javascript 的函数,所给例子倾向于阐明它的基本特征。在实际中, 还需要深入去使用它, 衍化出各种高级技巧。 理解它, 将成为理解 javascript 的一把钥匙。
     

  • 相关阅读:
    苹果所有常用证书,appID,Provisioning Profiles配置说明及制作图文教程(精)
    使用tcpdump抓取HTTP包
    android保持在休眠时,后台程序继续运行(让程序获取设备电源锁)
    insert数据时,获取插入数据的id
    Android学习笔记(五五):通知Notification(下)
    apk反编译与android项目代码混淆
    android 解决横竖屏切换时重新载入的问题
    android中往字符串数组动态添加元素
    error 25015安装程序集“C:WindowsMicrosoft .NETFrameworkv2.0.50727xxx.dll”失败,原因是出现了系统错误:另一个程序正在使用此文件,进程无法访问
    win7 安装vs2013后无法连接远程数据库,出现如下提示的解决方法
  • 原文地址:https://www.cnblogs.com/lovesqcc/p/4037762.html
Copyright © 2011-2022 走看看