1、概述
1.1函数申明:
函数命令(函数的声明):function a(){}
函数表达式:const a=function(){}
1.2函数的重复声明:
后者覆盖前者(涉及到函数名的提升)
1.3 return和递归
1.4第一公民
函数可以作为变量和对象属性的赋值以及传参
1.5函数名的提升
(1)在js引擎中,函数命令本身会被整个提到头部去,如下
f()
function f(){}
js执行顺序:
function f(){}
f()
(2)被赋值的函数表达式如下
f()
var f=function (){}
js执行顺序:
var f
f() //这时候的f是指被定义了,但没有被赋值,更不知道他是不是函数
f=function(){}
最后结果:undefined is not a function
!!!最后值得注意的是:
function f(){}
var f=function (){}
f()
无论顺序是否是函数命令在上还是函数表达式在上,f()只会去调赋值的函数表达式
1.6不能在条件语句中声明函数
总结建议:如果要在try/if中使用函数,建议用函数表达式。
2、函数的属性和方法
2.1 属性:name(function后的名字)
函数定义的三种形式:
(1)
function f(){}
f.name //f
(2)
var f1=function(){}
f1.name // ' '
(3)
var f2=function myname(){}
f2.name // myname
第三种 :真正的函数名还是f2,myname只在函数体内部使用
2.2 属性:length
长度是函数定义时,参数的个数
2.3方法:toString()
返回函数的源码
3、函数的作用域
3.1全局作用域与函数作用域
3.2函数内部的变量提升
其实在函数内部也存在变量提升,在函数体内,var 命令申明的变量,都会提升到函数体的头部。
3.3函数本身的作用域
注意点:作用域和变量一样,是在其申明时所在的作用域。
原话:函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域。
var a=1//a是全局变量
var x=function(){
console.log(a)
}// x是全局函数,其可使用的变量范围在全局中,例如a
function f(){
var a=2
x()//相当于指向外面的那个函数,让外面那个函数去跑一下
}
f()// 1
4、参数
4.1 概述
函数运行的时候,有时需要提供外部数据,不同的外部数据会得到不同的结果,这种外部数据就叫参数。
4.2 参数的缺省
没有办法只省略靠前的参数,而保留靠后的参数。如果一定要省略靠前的参数,只有显式传入undefined
4.3默认值
注意点:避免在传值的时候,传空字符 ' '和0
遇到此类问题:建议写:
function f(a) {
(a !== undefined && a !== null) ? a = a : a = 1
return a
}
f() // 1
f(' ') // ' '
f(0) // 0
4.4 传递方式
在函数中,如果传递的是数值、字符串、布尔值,那么拷贝原始值,函数内部的修改不起作用。
但如果传递的值是复合型:例如数组、对象、其他函数,如果在函数内部修改,会影响原始值。
如果是替换掉整个复合型数据,就不会影响原始值!
4.5 同名参数
如果有同名参数,取后面出现的值
function f(a,a){
console.log(a)
}
f(1,2) // 2
即使后面的值缺省,也是取后面的值
function(a,a){
console.log(a)
}
f(1) // 1
4.6 argument对象
(1)它可以读取传过来参数的个数
console.log(arguments[0])
其参考对象是f(1,2,3)=》//arguments.length=3
(2)可以将数组转为真正可用的数组:
var args=Array.prototype.slice.call(arguments)
(3)callee属性可以读取到 它所对应的原函数
var f=function(one){
console.log(arguments.callee === f)
}
f() // true
5 OTHER
5.1 闭包
*如何在局部作用域中取出数据:*/
functionf1() {
var n=999
functionf2() {
console.log(n)}
f2()
}
f1()
/*上面的f2就是闭包,定义在一个函数内部的函数
*闭包的用处:
* 1、获取到函数内部的数据
* 2、让这些变量始终保持在内存中,既闭包使内部变量记住上一次调用的运算结果
* 3、封装对象的私有属性和方法*/
5.2 IIFE 立即调用(自己执行)
格式:
(function(){ code }());
new function(){ code }
new function(){ code }()//后面的括号用于传参
(function(){
code
}());
目的:
一、是不必为函数命名,避免了污染全局变量;
二、是IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。
参考链接:http://javascript.ruanyifeng.com/grammar/function.html#toc8