function 类型

一、函数的声明方式

1、普通的函数声明

function box(num1,num2){
    return num1+num2;
}
alert(box(1,2));

2、使用变量初始化函数

var box=function(num1,num2){
    return num1+num2;
}
alert(box(1,2));

3、使用Function构造函数

var box=new Function("num1","num2","return num1+num2");
alert(box(1,2));

第三种不推荐,因为这种语法导致解析两次代码(第一次解析常规ECMAScript代码,第二次解析传入构造函数中的字符串)
,从而影响性能,但我们可以通过这种语法来理解,函数是对象,函数名是指针的概念

二、作为值的函数,函数可以传递函数

1、函数的返回值可以来传递

function box(sum,num){
    return sum+num;
}
function sum(num){
    return num+10;
}
var result=box(sum(10),10);   //这里传递的是函数的返回值,和普通变量没区别
alert(result);

2、把函数本身作为参数来传递,而不是作为结果

function box(sum,num){
   return sum(num);
}
function sum(num){
    return num+10;
}
var result=box(sum,10)   //这里sum是函数,当做参数传递到另外一个函数里,而不是返回值
alert(result)

三、函数内部属性

 1、arguments类数组对象,包含了传入函数中所有参数,这个对象还有一个callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数

function box(num){
    if(num<=1){
        return 1;
    }else{
        return num*box(num-1);    //3*2*1
    }
}
alert(box(3));

以上是一个阶乘或者是递归,box调用了自己,如果很多自我调用修改也许会麻烦,所以用到arguments.callee来调用自己

function box(num){
    if(num<=1){
        return 1;
    }else{
        return num*arguments.callee(num-1);    //arguments.callee 调用自身,实现递归
    }
}
alert(box(3));

 2、this

四、函数的属性和方法

1、length   函数希望接收参数个数

function box(a,b){
    return a+b;
}
alert(box.length)    //2

2、prototype  原型,下面有两个方法 apply()和call(),每个函数都包含这两个非继承而来的方法,这两个方法的用途都在特定的作用域中调用函数,实际上等于设置函数体内this对象的值

function box(a,b){
    return a+b;
}
function sum(a,b){
    return box.apply(this,[a,b]);   //this表示window作用域,[]表示传递的参数
}
function sum1(a,b){
    return box.apply(this,arguments);   //这个可以当数组传递
}
alert(box(10,10));alert(sum(10,10));
alert(sum1(10,10));

call()和apply()方法相同,他们的区别在于接收参数方式不同。对于call()方法,第一个参数也是作用域,没有变化,变化只是其余的参数都是直接传递给函数的

function box(a,b){
    return a+b;
}
function sum(a,b){
    return box.call(this,a,b);   //this表示window作用域,[]表示传递的参数
}
alert(box(10,10));
alert(sum(10,10));

以上是对象冒充,其实call()和apply()最大的作用是修改作用域

var color="hongse";
var box={
    color:"lanse"
}
function sayColor(){
    alert(this.color);
}
sayColor.call(window);    
sayColor.call(this);    //this就是window
sayColor.call(box);

----------------------------------------------进阶----------------------------------------------

1、当函数作为对象的方法时,this指向该对象

2、作为普通函数调用时(当函数不作为对象属性调用时,也就是普通函数方式,此时的this总是指向全局对象,在JavaScript中,这个全局对象是Window对象

例子1:

var myObject={
  name:"sven",
  getName:function(){
    return this.name;
  }
}
console.log(myObject.getName())     //sven
var myObject1=myObject.getName;

window.name="lee";

console.log(myObject1())     //lee

例子2:

var div=document.getElementById('div1');
div1.onclick=function(){
  console.log(this);     //这里的this是dom节点
  function callback(){
    console.log(this);    //这里的this是window,因为是作为普通函数调用的
  }
  callback();
}
-------修改方法,callback.call(this)

3、使用new调用构造器时,如果构造器显示返回一个object类型的对象,那么这次结果最终会返回这个对象,而不是之前期待的this

例1

var myObject=function(){
  this.name="sven";
  return {
    name : "anne"                  //返回object类型
  }
}
var obj=new myObject();
console.log(obj.name)           //输出 anne

4、Function.prototype.call 或 Function.prototype.apply 调用

跟普通函数相比,用Function.prototype.call 或 Function.prototype.apply可以动态的改变传入函数的this

例1

var obj1={
  name:"sven",
  getName:function(){
    return this.name;
  }
}
var obj2={
  name:"annr"
}
console.log(obj1.getName());          //输出 sven
console.log(obj1.getName.call(obj2));   //输出 anne
-------------call是function方法-----------

5、call和apply

apply接收两个参数,第一个参数指定了函数体内this对象的指向,第二个是个集合(可以是数组,也可以是类数组)

var func=function(a,b,c){
  console.log([a,b,c]);
}
func.apply(null,[1,2,3])    //[1,2,3]

其实和之前学的是一样的,调用函数的时候,都省略了call或apply,比如调用 a(),其实是a.apply()的缩写,只不过,第一个参数是null,函数体内的this会指向默认的宿主对象,在浏览器中则是window

var func=function(a,b,c){
  console.log(this===window);
}
func.apply(null,[1,2,3])

***借用其他对象的方法

有时候我们使用call或者apply的目的不在于指定this指向,而是另有用途,比如借用其他对象的方法,传入null代替某个具体的对象

Math.max.apply(null,[1,2,5])     //5

借用Array.prototype对象上的方法,往arguments中添加一个新的元素,通常会借用Array.prototye.push方法

(function(){
  Array.prototype.push.call(arguments,3)
  console.log(arguments)
})(1,2)     //[1,2,3]


把任意对象传入Array.prototype.push
var a={};
Array.prototype.push.call(a,"frist");
a[0];       //frish   
a.length;   //1

想把arguments转成真正的数组的时候,可以借用Array.prototype.slice方法,想截去arguments列表的头一个元素的时候,可以借用Array.prototype.shift方法

(function(){
  Array.prototype.slice.call(arguments)
  console.log(arguments)
})(1,2)         //[1,2]


(function(){
  Array.prototype.shift.call(arguments)
  console.log(arguments)
})(1,2)     //[2]
原文地址:https://www.cnblogs.com/change-oneself/p/5027149.html