js中的每一个函数都是 Function类型的实例(new Function()),也就是说函数是一个对象(引用类型),函数名其实包含着的是指向当前函数的指针(你懂的)。
定义函数的方法:声明式和表达式的方法
// 定义函数的方法:声明式
function getSum(num1){
return num1+10
}
// 表达式的方式
var getSum1 = function(num1){
return num1+10
}
// 虽然定义的方式不同,但是效果确实一样的,由于函数是一个引用类型的对象,所以函数名getSum1包含着的是指向当前函数的指针而已,所以:
var getSumCopy = getSum1;
console.log(getSumCopy(19))//29,因为getSumCopy指向了getSum1所指向的函数
函数声明和函数表达式的区别:
前者有一个叫函数声明提升的过程(会被提升到最顶部),导致即使函数声明写函数执行的后面也能够正常执行;后者则必须等到浏览器解析到函数所在的位置后才能执行。
// 前者有一个叫函数声明提升的过程(会被提升到最顶部),导致即使函数声明写函数执行的后面也能够正常执行;
alert(addOne(3))//4
function addOne(num2){//在解析的时候会被提升到顶部
return num2+1
}
//后者则必须等到浏览器解析到函数所在的位置后才能执行:
alert(addOne1(3))//Uncaught TypeError: addOne1 is not a function,因为变量addOne1真正包含函数的指针是在下一行代码
var addOne1 = function (num3){
return num3+1
}
函数也可以作为参数
//母函数,函数名作为参数
function consRe(func,elem1){
return func(elem1)
}
//参数子函数
function getCheng(num){
return num*4
}
var result = consRe(getCheng,12);//其实consRe(getCheng,12)=getCheng(12)=48;
//但是如果改成这样呢
function consRe(func,elem1){
func(elem1)
}
//参数子函数
function getCheng(num){
return num*4
}
var result = consRe(getCheng,12);// undefined,其实consRe(getCheng,12)执行完之后什么也没留下来(函数直接销毁了)以至于result什么也没接收到,所以是undefined;
arguments
1.一个包含着函数所有参数的类似数组的对象(只是类似),函数中的所有参数都可以通过arguments获取,arguments[0]第一个参数,arguments[1]第二个参数....,函数接收的永远是一个数组。这也就意味着无论你定义函数的时候参数有几个,调用的时候不一定就要非得传几个。
function getChanged(){
return arguments[0]+arguments[1];
}
console.log(getChanged(12,15));//27,虽然定义函数的时候没有传参,但是调用函数的时候可以传参
argument.callee:arguments有一个属性callee,其是一个指针,指向拥有该arguments对象的函数,说白了就是当前函数(可用作阶乘)
function getChanged(){
console.log(arguments.callee)//function getChanged(){...}指向函数本身
return arguments[0]+arguments[1];
}
this,在函数中,this引用的是当前函数执行时候所在的环境对象(或者说是值)跟函数定义在哪里无关(以后还会祥细解析)
function getChanged(){
console.log(this)//window
return arguments[0]+arguments[1];
}
getChanged(12,15);//window,因为当执行的时候是在全局环境中
var obj = {}
obj.hert = getChanged;
obj.hert()//this返回的是obj对象
3.函数的属性caller,
“保存的是调用当前函数的函数的引用”,说白了就是哪个函数调用了该函数func,func.caller就指向哪个函数(是一个指针),全局环境下func.caller指向的是null,因为此时调用着是一个window对象,并不是函数
function getChanged(){
console.log(arguments.callee.caller)//null
}
getChanged(12,15);//window,因为当执行的时候是在全局环境中
函数的方法:
4.call()和apply()
作用:为函数的调用设置特定的执行环境,说白了就是改变函数体内this的指向,让一个函数在不同的作用域中有不同的结果;
区别:
func.apply()接受两个参数,第一个参数指定函数运行所在的作用域(环境),第二个参数是一个参数数组或者arguments
func.call()和前者的作用一样,只不过在传递参数的方式有所不同,call()的参数第一个依然是作用域,第二个起的所有参 数都必须一一列举出来。例如:
var phone = "魅族";
var phoneObj = {
phone:"小米"
};
function phoneSay (){
console.log(this.phone)
}
phoneSay()//魅族,全局环境中执行,this就是window
phoneSay.apply(window)//魅族,执行环境指定为window,所以函数体内的this就是window,
phoneSay.call(phoneObj);//小米,执行环境是phoneObj,所以函数体内的this就是phoneObj
5.bind()
func.bind():将会创建一个新的函数实例,bind()方法接收一个参数,来指定新函数的this的指向,和call与apply的区别就是bind是生成了一个新的函数实例,但并没有执行(当该新函数执行的时候,无论执行环境在哪里,函数体内this永远都执行bind()方法传递过来的参数 ),而call和apply在改变执行环境后直接运行了
function phoneSay (){
console.log(this.phone)
}
var phoneSayBind = phoneSay.bind(phoneObj)//新函数phoneSayBind,该函数的this指向对象phoneObj,无论将来该函数在什么环境中执行。
phoneSayBind()//小米,虽然是在全局环境中执行的该函数