第五章 引用类型>Function类型

Function类型

每个函数都是Function类型的实例,与其他引用类型一样具有属性和方法。

函数声明语法定义:

function sum(num1, num2) {
    return num1+num2;
 }

函数表达式定义:

var sum = function(num1, num2) {
                return num1 + num2;
           };

由于函数是对象,因此函数名是一个指向函数对象的指针。不会与某个函数绑定。

function sum(num1, num2) {
    return num1 + num2;
  }
console.log(sum(10, 10));
//20

var anotherSum = sum;                 //将函数的值赋给anotherSum,不带圆括号的函数名访问的是函数指针而非调用函数。
console.log(anotherSum(10, 10));   //sum和anotherSum指向同一个函数
//20 

sum = null;                                   //就算把sum清空; anotherSum还是可以调用, 清空的只是函数名的指针而已,ahotherSum的指针没有被清空
console.log(anotherSum(10, 10));
//20

函数没有重载

同名函数只能存在一个,后面覆盖前面的;

funcition addSomeNumber(num) {
            return num+100;
     }

function addSomeNumber(num) {
           return num + 200;
      }

var result = addSomeNumber(100);
console.log(result);
//300

//上面的代码和下面的基本没有区别
var  addSomeNumber = function(num) {
               return num +100;
         };


var  addSomeNumber = function(num) {
               return num +200;
         };

函数声明与函数表达式

函数声明:     解析器率先读书函数声明。函数声明被提升到代码的顶部,使在执行任何代码之前可用。

console.log(sum (10, 10));
function sum (num1, num2) {
         return num1 + num2;
   }
 
// 20  对代码求值时JS引擎再第一遍声明函数并将他们放到源代码的顶部。

函数表达式:  只有变量名被提前了, 而变量名知识一个指向函数对象的一个指针。函数体和函数声明依然在变量所在行执行。

console.log(sum1(10, 10));
var sum1 = function(num1, num2) {
         return num1 + num2;
        };
// Uncaught TypeError: sum1 is not a function(…)

//在执行到函数所在的语句之前,变量sum并没有保存对函数的引用.变量被提升到了顶部,赋值语句还在原来的地方进行。第一行代码就会导致 Uncaught TypeError;根本不会执行到下一行

作为值的函数

function callSomeFunction(someFunction, someArguments) {
         return someFunction(someArguments); 
        }

function getGreeting(name) {
   return "hello!" + name;
 }

var result2 = callSomeFunction(getGreeting, "zhangsan");
// 没有使用圆括号的getGreeting,只是获得了getGreeting指向的那个函数对象的指针,并不是立即调用函数,返回结果。


console.log(result2); // hello!zhangsan

从一个函数中返回另外一个函数。

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;
                   }
               };
          }

var data = [{name: "Zachary", age: 28},{name: "Nicholas", age: 29}];
//创建一个包含2个对象的数组data。每个对象都有一个name属性,和age属性

data.sort(createComparisonFunction("name"));
//调用写好的排序函数,把name属性当做排序函数的参数传递进去 console.log(data[
0].name); data.sort(createComparisonFunction("age")); console.log(data[0].name); // Nicholas // Zachary

函数内部属性

函数内部俩个特殊的对象:

arguments: 类数组对象,包含着传入函数中的所有参数。

aruguments还有一个callee的属性;

callee: 该属性是个指针,指向拥有这个arguments对象的函数。

function factorial(num) {
         if(num<=1) {
               return 1;
            } else {
                 return num*arguments.callee(num-1);
            }
       }
var trueFactorial = factorial;

factorial = function() { return 0;};
//factorial的指针被修改
console.log(factorial(5));     
// 0
console.log(trueFactorial(
5));
//120 trueFactorial的指针依然指向的是之前的阶乘函数对象。

this: 引用的是函数 据以执行的环境对象,或者也可以说是this值(在网页的全局作用域调用this对象引用的是WINDOW);

window.color = "red";
var o = { color: "blue" };

function sayColor() {
    console.log(this.color);
   // 由于函数是全局作用域定义的函数,this.color = window.color
  }
sayColor();
o.sayColor = sayColor;  //相当于用匿名函数的形式把函数赋给变量,sayColor 里面的this引用对象的是o 
o.sayColor();
// red
// blue

caller:保存这调用当前函数的函数的引用;如果是全局作用域调用调用当前函数,值为null;

function outer() {
    inner();
   }
function inner(){
    console.log(inner.caller);
  //可以用arguments.callee.caller。是一样的效果
  }
outer();
// outer() {  inner();  }

函数的属性和方法

length:        函数希望接受的命名参数的个数;

prototype:  保存所有实例和方法的真正所在。

函数包含2个非继承来的方法:apply()和call(),作用是在特定作用域中调用函数,设置函数体内的this对象的值。

apply(): 接受俩个参数, 第一个参数是再其运行函数的作用域,第二个参数,可以是数组,也可以是Array的实例,也可要是arugments的对象。

function sum2(num1, num2) {
         return num1 + num2;
     }

function callSum1(num1, num2) {
         return sum2.apply(this, arguments);
          //截获sum2函数并当做返回值返回
//这里 的this指的window。因为sum2是全局作用域的函数 this = window.sum2
} function callSum2(num1, num2) { return sum2.apply(this,[num1, num2]); } console.log(callSum1(10, 10)); console.log(callSum2(10, 10)); // 20 // 20

call():和apply的作用一样。第二个接受的参数方式不同, 递给call()的参数必须逐个列举出来。

function sum(num1, num2) {
          return num1 + num2;
     }
function callSum(num1, num2) {
          return sum.call(this, num1, num2);
   }

console.log(callSum(10, 10));

call()和apply()最大的作用扩充函数赖以运行的作用域

window.color = "red";
var o = { color: "blue" };

function sayColor() {
     console.log(this.color);
   }

sayColor();
sayColor.call(this);
sayColor.call(window);
sayColor.call(o);
// red
// red
// red
// blue

bind():  这个方法会创建一个函数实例,this值 会被绑定到传给bind()函数的值。

window.color = "red";
var o = { color: "blue" };

function sayColor() {
     console.log(this.color);
   }
var objectSayColor = sayColor.bind(o);
//把this的值设置为o
objectSayColor();
// blue
原文地址:https://www.cnblogs.com/zhangbaihua/p/5564513.html