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类型定义函数的效率远不如函数定义语句和字面量表达式的定义
定义函数的三种方式之间存在一定差别
- 函数定义语句:执行时函数名被提前声明 不存在效率问题
- 字面量表达式:函数体固定 无法动态执行 不存在效率问题
- 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();
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。