函数声明: function funcName(args1, args2) { … … return… } 函数调用传参时可以传递不限数量的参数,在函数内部使用arguments对象接受 函数表达式: funcName = function (args1, args2) { … … return… } 使用函数声明与使用函数表达式定义的区别: 函数声明会在调用之前已经加载好 函数表达式只有执行到该行代码时才会定义函数
// 函数声明式定义方式 function myFun(){ console.log("hello world") } //函数调用 myFun() // 函数参数 function mySub(a, b){ console.log("a=>",a ," b=>", b) return a-b } // // 传参调用 // // 顺序传参 // mySub(10,2) // //不支持关键字传参 mySub(b=2, a=10)运行结果:(注意js是不支持关键字传参的,不要被mySub(10,m=2)迷惑)
使用函数声明与使用函数表达式定义的区别 函数声明会在调用之前已经加载好 函数表达式只有在执行到该行代码时才会定义函数
my_func = function(){ console.log(arguments) } my_func() myHello1() // 这句正常执行,因为函数声明会在调用之前已经加载好 myHello2() // 这句会报错,因为匿名表达式只有执行到该行代码时才会定义函数 function myHello1(){ console.log("hello") } myHello2 = function(){ console.log("hello") } // 下面两句都可以正常执行 myHello1() myHello2()在web浏览器中,全局环境表示为窗口window对象下 所有的全局变量与函数都是window的属性或者方法 关闭浏览器窗口,就销毁了所有的全局对象 每个函数都拥有自己的执行环境 每一个代码执行时都有自己的作用域链,作用链前端就是当前执行环境的变量对象,作用域链下一个变量对象就是下一个包含的环境,直到全局环境
在另一个窗口的运行:
在函数内部使用var定义的变量为函数内部变量, 如果没有使用var关键字,变量就会声明为全局变量。 es5规范中并没有块级作用域,即诸如if, while的{}部分,es6拥有块级作用域
my_sex= "男" function myFun(){ var my_name = "luxp" // 此处my_name是局部作用域的变量,外部不能访问;如果没有用var,则是全局作用域的变量,外部可以访问 my_age = 18 console.log(my_name, my_sex) } myFun() console.log(my_name)变量作用域查找顺序由内而外寻找,当在函数内部定义局部变量时,首先会声明该变量
var name = "luxp" function seekName1(){ var name = "luxp_2" console.log(name) // 输出 luxp_2 var name = "luxp_1" function subFun(){ var name = "luxp_3" // name = "luxp_4" console.log(name) // 输出 luxp_3 } subFun() } seekName1() //局部变量会被预先声明 function seekName2(){ console.log(name) // 输出全局变量中的name,为 luxp // 如果用var声明name,则上面的语句打印结果为undefined,是相当于在打印name之前声明了局部变量name // var name = "luxp_2" // var name = "luxp_1" function subFun(){ var name = "luxp_2" // name = "luxp_4" console.log(name) // 输出局部变量中的name,为luxp_2 } subFun() } seekName2()将函数作为值返回 示例代码:
function create_fun(I){ return function (){ return "func_"+I } } func_array = [] for (i=0;i<5;i++){ func_array[i]=create_fun(i) }如何让每个函数输出不同的值
/* 闭包的原因,所有的函数都会输出five */ function create_fun(){ var array=['one','two','three','four','five'] var func_array=[] for(i in array){ console.log(i) func_array[i]=function(){ return array[i] } } return func_array } //执行这一句的时候,内部函数其实是引用i,而不是i的值,执行 //到最后的时候i的值是4,所以全部的函数的i都是5 func_array=create_fun() func_array[0]()function create_fun(){ var array = ["one", "two", "three", "four", "five"] var func_array = [] for (i in array){ func_array[i] = function create_fun(I){ //增加了一个内嵌函数 return function (){ return array[I] } //执行,通过执行把i的值固定下来 }(i) } return func_array } func_array = create_fun() func_array[0]()
函数可以作为一个参数给另一个函数调用,另一个函数就被称为该函数的高阶函数
示例代码:
function sum(a,b){ return a+b } function sub(a,b){ return a-b } function compute(func, a,b){ return func(a,b) } value = compute(sum, 10,3) value = compute(sub, 10, 3) function selectEvenNumber(number){ if (number % 2 == 0) { return number } else { return 0 } } function selectOddNumber(number){ if (number % 2 == 1) { return number } else { return 0 } } function map(array, func=selectEvenNumber){ for ( i in array){ array[i] = func(array[i]) } } array = [1,2,3,4,5,6,7,8,9] map(array) console.log(array) array = [1,2,3,4,5,6,7,8,9] map(array, selectOddNumber) console.log(array) /* js中常见的一种高阶用法 */ function myfun(args, func){} myfunc(args, function(){})运行结果:
2.5.1 callee与this
arguments.callee可以在内部对函数名实现解耦 callee代表这对函数自身的引用,可以降低函数名与内部调用的耦合性
示例代码一:
function myFun(){ console.log(arguments) console.log(arguments.callee) }运行结果: 示例代码二:
/*利用递归计算阶乘 */ // 这种方法,当函数名改变时,函数内部的递归方法名也得修改 function jiecheng(num) { if (num === 1) { return 1 } else { return num * jiecheng(num-1) } } // 这种方法不一样,无论函数名如何改变,函数内部的递归方法名不用修改 function jiecheng(num) { if (num === 1) { return 1 } else { return num * arguments.callee(num-1) } }在函数内部,this引用了函数的执行环境
/* this 指向对象由所在的执行环境决定 */ console.log(this) function myFun(){ console.log(this) // return this this.nickname = "luxp" } function myFun(){ function mySubFun(){ console.debug(this) return this } return mySubFun() } function myFun(){ var o = new Object() o.func = function(){ console.log(this) } return o }