Function类型

Function类型是JS的引用类型之一 通过Function类型创建Function对象
在JS中 函数也以对象的形式存在
每个函数都是一个Function对象

console.log(Function instanceof Function)    //true
console.log(Function instanceof Object)     //true
console.log(Object instanceof Function)     //true

构造函数

函数除了用函数定义语句和字面量表达式两种方式定义之外 还可以通过Funcion类型进行定义
函数的参数和函数体都是以字符串形式传递给Function的

var fun = new Function ('num','console.log(num)');
fun(100);    //100  

通过Function类型定义函数的效率远不如函数定义语句和字面量表达式的定义
定义函数的三种方式之间存在一定差别

  1. 函数定义语句:执行时函数名被提前声明 不存在效率问题
  2. 字面量表达式:函数体固定 无法动态执行 不存在效率问题
  3. Function类型定义 函数体是字符串 可以动态执行 效率较低

Function的apply()方法

apply方法可以劫持另外一个对象的方法,继承另外一个对象的属性.
Function.apply(obj,arguments)方法能接收两个参数(可选):
obj:这个对象将代替Function类里this对象
arguments:这个参数是数组,它将作为参数传给Function
如果没有obj参数 那么Global对象被用作obj

 //定义一个人类
 function Person(name,age) {
     this.name=name;
     this.age=age;
 }
//定义一个男人
 function Man(name,age,hobby) {
     Person.apply(this,arguments);   //this代表的是man   arguments是一个数组 也就是['Sicong',30,'撕逼']
     this.hobby=hobby;
 }

 var man=new Man('Sicong',30,'撕逼');
 console.log("name:"+man.name +"\n"+ "age:"+man.age +"\n"+"hobby:"+man.hobby);   //name:SicongWang age:30 hobby:撕逼
//用Man去执行Person这个类里面的内容,在Person这个类里面存在this.name等语句,这样就将属性创建到了student对象里面

Function的call()方法

call方法与apply类似 只是第二个参数不是数组

 //定义一个人类
 function Person(name,age) {
     this.name=name;
     this.age=age;
 }
//定义一个woman
 function Woman(name,age,hobby) {
     Person.call(this,name,age);   //this代表的是woman  
     this.hobby=hobby;
 }

 var woman=new Woman('TimoFeng',18,'唱歌');
 console.log("name:"+woman.name +"\n"+ "age:"+woman.age +"\n"+"hobby:"+woman.hobby);  //name:TimoFeng age:18 hobby:唱歌

Function的bind()方法

bind方法与call和apply类似 第一个参数都是this要指向的对象 利用后续参数传参数
不同的是bind是返回对应的函数 可以稍后调用;call和apply是立即调用

var fn=function () {
    console.log(this.x)
};
var foo={
    x:3
};
fn();   //undefined
console.log(fn.bind(foo));    //ƒ () {
                              //        console.log(this.x) }
                              //                  此时this已经指向了foo,但是用bind()方法并不会立即执行,而是创建一个函 
                              //                  数    如果要直接调用的话 可以 bar.bind(foo)()
 var result=fn.bind(foo);
 result();   //3

递归

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数
递归函数的优点是定义简单,逻辑清晰 所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰
递归调用的次数过多,会导致栈溢出 使用过深会造成死循环

var num=function(x){
 if(x == 1){
   return 1;
} else{
   return x*num(x-1);
}
}
console.log(num(5))   //120
/*  计算过程为:
    ---> num(5)
    ---> 5 * num(4)
    ---> 5 * (4 * num(3))
    ---> 5 * (4 * (3 * num(2)))
    ---> 5 * (4 * (3 * (2 * num(1))))
    ---> 5 * (4 * (3 * (2 * 1)))              只有n=1时才特殊处理
    ---> 5 * (4 * (3 * 2))
    ---> 5 * (4 * 6)
    ---> 5 * 24
    ---> 120         
    */
    

回调函数

一个函数作为参数传给另一个函数 我们把另一个函数称为回调函数
通俗的说回调函数有3个特点: 1).你定义的 2).你没有调用 3).但最后执行了
回调函数的优点:

-  可以在未命名的情况下传递函数 节省全局变量
-  将另一个函数调用操作委托给另一个函数
-  有助于提升性能
$('btn').click(function(){            //click方法就是一个回调函数
 alert('我是一个按钮')
})

自调用函数

自调用函数 声明完了,马上进行调用,只能使用一次

(function(num1,num2){
  console.log(num1+num2)
})(10,20)    //30

作用域和作用域链

作用域: 一块代码区域, 在编写时就确定, 不会再变化
作用域链: 多个嵌套的作用域形成的由内向外的结构, 用于查找变量
分为全局作用域和函数(局部)作用域


作用:
作用域: 隔离变量, 可以在不同作用域定义同名的变量不冲突
作用域链: 查找变量

 var num1=10;       //全局变量
 function fn1(){
 var num2=20;     //fn1作用域的局部变量
   function fn2(){
 var num3=30;    //fn2作用域的局部变量
   function fn3(){
 var num4=40;     //fn3作用域的局部变量
 console.log(num1);    //10
 console.log(num2);    //20
 console.log(num3);    //30
 console.log(num4);    //40
}
fn3();
 console.log(num1);    //10
 console.log(num2);    //20
 console.log(num3);    //30
 console.log(num4);    //num4 is not defined
}
fn2();
 console.log(num1);    //10
 console.log(num2);    //20
 console.log(num3);    //num3 is not defined
 console.log(num4);    //num4 is not defined
}
fn1()

闭包函数

当嵌套的内部函数引用了外部函数的变量时就产生了闭包
闭包本质是内部函数中的一个对象, 这个对象中包含引用的变量属性


作用:
延长局部变量的生命周期
让函数外部能操作内部的局部变量
避免污染全局命名空间
缺点:
变量占用内存的时间可能会过长
可能导致内存泄露(占用的内存没有及时释放
内存泄露积累多了就容易导致内存溢出)

function fn1() {
  var a = 2;
  function fn2() {
    a++;
    console.log(a);    //3  4
  }
  return fn2;
}
var f = fn1();
f();
f();

RoOK1E
0 声望4 粉丝

下一篇 »
原型和继承