javascript_引用类型_Function

  • Exercise1:

      <script>
          //每个函数都是function类型的实例。而且都与其他引用类型一样有属性和方法。
          //函数是对象,函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。
    
          //声明方法1:
          function sum(num1,num2){
              return num1 + num2;
          }
    
          //声明方法2:
          //在使用函数表达式定义函数时,没有必要使用函数名,通过变量即可引用函数。
          //函数末尾有一个分号。
          var sum1 = function(num1,num2){
              return num1 + num2;
          };
    
          //声明方法3:
          //不要使用这种方法定义函数,这种语法会导致解析两次代码。
          //但是这种方法对于理解“函数是对象,函数名是指针”的概念是直观的。
          var sum2 = new Function('num1','num2','return num1 + num2');
      </script>
    
  • Exercise2:

      <script>
          function sum(num1,num2){
              return num1 + num2;
          }
    
          //不带小括号的函数名是访问函数指针而不是调用函数
          var anotherSum = sum;
          console.log(anotherSum(10,10));
      </script>
    
  • Exercise3:

      <script>
          //将函数名想象为指针,可以更好理解ECMAScript中没有函数重载的概念。
          var addSomeNumber = function(num){
              return num + 100;
          }
    
          //在创建第二个函数时,实际上覆盖了引用第一个函数名字的变量addSomeNumber,第一种声明的方法也是同理。
          addSomeNumber = function(num){
              return num + 200;
          }
    
        var result = addSomeNumber(20);
        console.log(result);
    </script>
  • Exercise4:

      <script>
          //解释器会先读取函数声明,并使其在执行任何代码之前可用。
          //在函数声明之前可以调用。
          console.log(sum(10,10));
    
          function sum(num1,num2){
              return num1 + num2;
          }
    
          //函数表达式,必须等到解析器执行到它所在的代码行,才会真正被解释执行。
          //在声明之前调用将会报错
          console.log(sum1(10,10));
          var sum = function(num1,num2){
              return num1 + num2;
          };
      </script>
    
  • Exercise5:

      <script>
          //ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。
          //函数可以像传递参数一样把一个函数传递给另外一个函数。
          function test(testFunction,testArg){
    
              return testFunction(testArg);
    
          }
          //要调用的函数
          function dFun(arg){
              return arg+'!';
          }
    
          //调用时作为参数传递进去的函数名不用加引号。
          console.log(test(dFun,'haha'));
      </script>
    
  • Exercise6:

      <script>
          //可以从一个函数中返回另一个函数。
    
          function createComparisonFunction(propertyName){
    
              return function(object1,object2){
    
                  var value1 = object1[propertyName];
                  var value2 = object2[propertyName];
    
                  if(value1 < value2){
    
                      return -1;
    
                  }else if(value1 > value2){
    
                      return 1;
    
                  }else{
    
                      return 0;
                  }
    
              };
          }
    
          //创建了一个包含两个对象的数组data。每个对象都包含一个name属性和一个age属性。
          var data = [{name:'Zachary',age:28},{name:'Nicholas',age:29}];
    
          //默认情况下sort()方法会调用每个对象的toString()方法确定它们的次序。
          //传递进去一个自定义函数来进行比较数组对象中的某个属性。
          data.sort(createComparisonFunction('age'));
    
      </script>
    
  • Exercise7:

      <script>
          //arguments对象是函数内部的特殊对象。他是一个类数组对象,包含着传入函数中的所有参数。
    
          function test(){
              console.log(arguments[0]);
          }
    
          test('haha');
    
          //该对象有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
          function factorial(num){
              if(num <= 1){
                  return 1;
              }else{
                  return num * factorial(num - 1);
              }
          }
    
          //以上代码可以改为
          function factorial(num){
              if(num <= 1){
                  return 1;
              }else{
                  //arguments.callee保存着当前函数的函数名,这样不管函数名是什么,都可以更改。
                  return num * arguments.callee(num - 1);
              }
          }
      </script>
    
  • Exercise8:

      <script>
          //函数内部的另一个特殊对象是this。this引用的是函数执行的环境对象。
          //this引用的是函数执行的环境对象
          //在网页的全局作用域中调用函数时this对象引用的就是window
    
          window.color = "red";
          var o = {color:'blue'};
    
          function sayColor(){
              console.log(this.color);
          }
    
          //this指代的是windows
          sayColor();
    
          //给o中的sayColor属性赋值sayColor函数的指针。
          o.sayColor = sayColor;
          //这个时候this的作用域就是o对象。
          o.sayColor();
      </script>
    
  • Exercise9:

      <script>
          //ECMAScript5规范化了另一个函数对象的属性:caller。
          //这个属性中保存着调用当前函数的函数的引用。
    
          //在全局作用域中调用当前函数,它的值为null。
    
          function outer(){
              inner();
          }
          function inner(){
              console.log(inner.caller);
          }
    
          //因为是在outer()调用了inner(),所以inner.caller就指向outer()
          outer();
      </script>
    
  • Exercise10:

      <script>
          //ECMAScript中的函数是对象,因此函数也有属性和方法。
          //每个函数中包含length属性,指明的实参的个数。
          function sayName(name){
              console.log(sayName.length);
              console.log(name);
          }
    
          sayName('a');
      </script>
    
  • Exercise11:

      <script>
          window.firstName = 'diz';
          window.lastName = 'song';
    
          var myObject = {firstName:'my',lastName:'Object'};
    
          function hellName(){
              console.log("Hello"+this.firstName+this.lastName);
          }
    
          hellName();
          hellName.call(window);
          //改变了作用域,默认时hellName()使用的是window的作用域。
          hellName.call(myObject);
      </script>
    
  • Exercise12:

      <script>
          function fun1(){
              this.a = 123;
              //this.a的作用域默认为fun1
              this.add = function(){return this.a};
          }
    
          function fun2(){
              this.a = 456;
          }
    
          var f1 = new fun1();
          var f2 = new fun2();
          //改变作用域,作用域为fun2,模拟了继承。
          var a = f1.add.call(f2);
          console.log(a);
      </script>
    
  • Exercise13:

      <script>
          function test(){
              this.a = 'haha';
          }
    
          test();
          console.log(a);
      </script>