1.函数声明
JavaScript函数有匿名函数、具名函数和箭头函数三种。
匿名函数
let fn = function () {
return 1
} //引用匿名函数的地址
let fn2 = fn //引用匿名函数地址
console.log(fn.name) //fn
console.log(fn2.name) //fn
函数就是对象,对象存在堆内存里面。匿名函数的函数名就是引用它的变量的名字。
具名函数
function fn3() {
return 3
}
console.log(fn3.name) //fn3
let fn5 = function fn4() {
return 4
}
console.log(fn4.name) //Uncaught ReferenceError: fn4 is not defined
console.log(fn5.name) //fn4
fn3的作用域的全局,fn5引用了fn4,所以fn4的作用域是函数本身。
箭头函数
let fn6 = i => i + 1 //一个参数写法
let fn7 = (i, j) => { //多个参数写法
console.log(i, j)
return i + j;
}
箭头函数没有name,但是箭头函数没有this
2.词法作用域(静态作用域)
静态作用域又叫做词法作用域,采用词法作用域的变量叫词法变量。词法变量有一个在编译时静态确定的作用域。词法变量的作用域可以是一个函数或一段代码,该变量在这段代码区域内可见(visibility);在这段区域以外该变量不可见(或无法访问)。词法作用域里,取变量的值时,会检查函数定义时的文本环境,捕捉函数定义时对该变量的绑定。【维基百科】
var global1 = 1 //全局变量
function fn1(param1){
var local1 = 'local1' //局部变量
var local2 = 'local2' //局部变量
function fn2(param2){
var local2 = 'inner local2' //局部变量
console.log(local1)
console.log(local2)
}
function fn3(){
var local2 = 'fn3 local2' //局部变量
fn2(local2)
}
fn2()
//local1
//inner local2
fn3()
//local1
//inner local2
}
fn1()
词法树只能确定变量的关系,不能确定变量的值。
3.this和arguments
this 就是 call 的第一个参数!call 的其他参数统称为 arguments
call才是正常的函数调用,其他调用函数的方式都是语法糖。
function f(){
console.log(this)
console.log(arguments)
}
f.call() // window,相当于f.call(undefined)
f.call({name:'frank'}) // {name: 'frank'}, []
f.call({name:'frank'},1) // {name: 'frank'}, [1]
f.call({name:'frank'},1,2) // {name: 'frank'}, [1,2]
this 是隐藏的第一个参数,且一般是对象,用于占位。arguments是伪数组,第二到最后一个参数都放里面,如果只有一个参数就为[]。
4.call、apply和bind
fn.call(asThis, p1,p2) 是函数的正常调用方式
当你不确定参数的个数时,就使用 apply
fn.apply(asThis, params)
call 和 apply 是直接调用函数,而 bind 则是返回一个新函数(并没有调用原来的函数),这个新函数会 call 原来的函数,call 的参数由你指定。
5.函数柯里化
函数柯里化就是只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。(返回函数的函数)
//柯里化之前
function sum(x,y){
return x+y
}
//柯里化之后
function addOne(y){
return sum(1, y)
}
//柯里化之前
function Handlebar(template, data){
return template.replace('{{name}}', data.name)
}
//柯里化之后
function Handlebar(template){
return function(data){
return template.replace('{{name}}', data.name)
}
}
6.高阶函数
在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:
a.接受一个或多个函数作为输入:forEach sort map filter reduce,
b.输出一个函数:lodash.curry,
c.不过它也可以同时满足两个条件:Function.prototype.bind
7.回调函数
被当做参数的函数就是回调函数(调用这个回调),回调跟异步没有任何关系。
//同步回调
array.sort.call(array, fn)
array.forEach.call(array, fn)
array.map.call(array, fn)
array.filter.call(array, fn)
array.reduce.call(array, fn)
//异步回调
setTimeout(fn, 1000)
8.构造函数
返回对象的函数就是构造函数,一般首字母大写。
new Number(1)
new String('s')
function Empty(){
this.name = 'null'
return this
}
var empty = new Empty //Empty.call({})