一、函数声明与函数表达式区别
可以通过变量访问的时间不同
1、函数声明
函数声明提升——函数声明会先被解析,提升到源代码树的顶部,因此在声明位置前调用也可以正常执行
alert(sum(10,20))//30
function sum (a, b) {
return a + b
}
2、函数表达式
函数表达式是从上到下顺序解析的,因此执行alert语句时sum函数还未声明,会报错
alert(sum(10,20))//sum is not a function
var sum = function (a, b) {
return a + b
}
alert行执行时,sum已声明但未定义,值为undefined
二、函数作为值/参数传递
function callSomeFunction (someFunction, someArgument) {
return someFunction(someArgument)
}
function sum (num) {
return num + 10
}
var result = callSomeFunction (sum, 10);//函数作为参数时无需加括号
alert(result)//20
示例:根据数组对象的某个属性进行排序
var arr = [{a: 2, b: ''}, {a: 999, b: 'ddd'}, {a: 3, b: '34'}, {a: 70, b: ''}]
function compare (attr) {
return function (obj1, obj2) {
var val1 = obj1[attr]//1、
var val2 = obj2[attr]
return val1-val2
}
}
arr.sort(compare('a'))//2、
alert(arr[1].a)//3
console.log(arr)
对于上述示例我的失误点:
1、代码中第4、5行,必须使用方括号来取得给定属性的值,使用点表示法无法取得——通过访问变量来访问对象属性时要使用方括号语法,见高程P85
2、代码中第9行,数组传入的两个参数即为上方函数内的obj1、obj2
为什么可以传递给内层函数??
原因:sort()方法传给调用的函数2个参数,函数接收到这两个参数作为此函数的局部变量,由于函数内部的函数在同一作用域,因此也可以调用,并不是把参数传递给了内层函数
三、arguments.callee属性
使用函数名的递归函数:
function factorial (num) {
if(num <= 1) {
return 1
}else {
return num * factorial (num-1)
}
}
console.log(factorial(5))//120
使用callee——不受函数名影响:
function factorial (num) {
if(num <= 1) {
return 1
}else {
return num * arguments.callee(num-1)
}
}
var another = factorial
factorial = function () {
return 0
}
console.log(another(5))//120
console.log(factorial(5))//0
我的失误点分析:factorial把指向第一个函数的指针复制给了another,之后factorial指向了另一个函数,因此调用factorial会执行第二个函数,调用another执行原来的函数
四、this——指向所在函数执行的环境
五、caller
1、
function outer () {
inner ()
}
function inner () {
alert(inner.caller)
}
outer()//输出整个outer函数的源代码
2、使用argument.callee.caller松散耦合
function outer () {
inner ()
}
function inner () {
alert(arguments.callee.caller)
}
outer()//输出整个outer函数的源代码
3、调用的父函数全局作用域的函数
function c () {
alert(c.caller)
}
c()//null
4、callee和caller
- callee指向当前函数
- caller指向当前函数的直接父函数
六、apply()方法
传入两个参数:在其中运行函数的作用域、参数数组(可使用arguments或形参组成的数组)
function sum (n1, n2) {
return n1 + n2
}
function sum1 (n1, n2) {
return sum.apply(this, arguments)//this指向的是sum函数的作用域,即把arguments数组的值传给sum函数的参数
}
function sum2 (n1, n2) {
return sum.apply(this, [n1, n2])
}
console.log(sum1(10,20))//30
console.log(sum2(10,20))//30
也可以理解为:使用apply使sum函数的this指向改变为sum1/sum2
七、call()方法
与apply方法作用相同,唯一区别:接收参数的方式不是数组,而是逐一直接传递给函数
function sum (n1, n2) {
return n1 + n2
}
function sum1 (n1, n2) {
return sum.call(this, n1, n2)
}
console.log(sum1(10,20))//30
通过下方例子体现通过apply/call方法扩充函数作用域的功能——原本只能访问函数内部及全局环境变量,调用方法后可以访问其他作用域
window.color = 'red'
var a = {color: 'blue'}
var b = {color: 'green'}
function sayColor () {
console.log(this.color)
}
sayColor()//red
sayColor.call(this)//red
sayColor.call(window)//red
sayColor.call(a)//blue
sayColor.call(b)//green
八、bind()方法
函数调用bind()方法,作用域将变为bind()中传入的值(对象)
window.color = 'red'
var o = {color: 'blue'}
function sayColor () {
alert(this.color)
}
var another = sayColor.bind(o)
another()//blue