标签:应用 meta 返回 ber 浏览器 斐波那契数列 次数 遍历 不能
讲一段代码一起封装起来,内部封装的一段代码为一个结构体,执行就全都一起执行(遇到return除外),不执行就都不执行
可以重复使用
函数声明又叫函数定义,必须先定义才能使用
跟变量的命名要求相似
不然会报引用错误
语法
function 函数命 (参数) {
封装的结构体
}
特点:生命的时候函数并不会执行,只有调用的时候才会被执行
(1)函数的参数1
一个函数可以设置0个或者多个参数,用逗号分隔
可以接受任意数据类型
function sum (a, b) {
console.log(a + b)
}
sum(1, 2)
(2)函数的参数2
形式参数(形参):定义的()内的参数,本质是变量,接受实参
function aaa(a, b) {...}
a, b就是形参
实际参数(实参):调用的()内的参数,本质是传递各种类型的数据,再传递给实参
aaa(c, d)
c, d是实参
传参过程:实参 -> 形参 -> 函数内部调用
(3)函数参数的优点
只要关心传递什么参数就可以知道函数怎么使用了
调用方法:函数名()
函数内部的语句执行的位置,与函数定义的位置无关(因为会命名提升),与调用位置有关
可以一次定义,多次(重复)执行
函数能够接受数据,也可以接受一个返回值
return作为一个关键字,可以设置函数的返回值
甚至可以将函数作为返回值
① 函数执行到return,会立即停止后面代码的执行
② return后面空格再定义一个字面量/表达式可以,即可以把整个函数变成一个表达式
如果没有指定表达式或者没有return,函数运行会返回一个undefined
如果有返回值,执行结果可以当成普通数据参与程序
甚至可以当成一个实参赋值给一个函数的变量
是函数定义的另外一种方式,即定义一个匿名函数然后赋给一个变量
也可以是一个具名函数
但是如果这个具名函数声明的时候(如果在声明之前就定义了后面的就不成立)赋值给了一个新变量,则函数原名称不可以调用,而console.log新函数名称中的表达式函数名还是旧函数名,但是可以调用
匿名函数:没有函数命
语法
var foo1 = function () { console.log(‘foo1‘) }
var foo2 = foo1
// foo1 和 foo2 都可以调用
// console.log(foo2)中的函数名是foo1
var foo4 = function foo3 () { console.log(‘foo3‘) }
// foo4可以调用,foo3不可以调用
// foo4被console.log输出的话函数名是foo3
var foo5 = function () { console.log(‘foo5‘) }
// foor5被console.log输出的话没有函数名
函数是属于object中的一种复杂数据类型
用typeof检测的话会返回‘function’
js中,arguments是函数内置的一个属性,其储存了传递的所有实参(并不形参),arguments是一个伪数组,也可以进行遍历
可以通过argumeng.length返回传递了多少实参
相似的,函数的.length
可以返回定义了多少形参
函数的实参个数可以跟形参个数不一致,但是实参都可以在arguments中找到
案例
定义一个求和函数,如果传入1个参数,返回它自己,如果传入两个参数,返回他们的和,如果传入三个参数,先比较前两个的大小,大得与第三个参数求和返回,如果传入4个及以上,输出错误提示
function sum (a, b, c) {
switch (arguments.length) {
case 1:
return a
break
case 2:
return a + b
break
case 3:
return a > b ? a + c : b + c
break
default:
throw new Error(‘请输入3个以下参数!‘)
}
}
函数里面调用自己,就是函数递归
但是递归次数太多容易出现错误:超出计算机计算最大能力
推荐尾部递归优化
案例
斐波那契数列:1,1,2,3,5,8...
function fibo (num) {
if (num === 1 || num === 2) {
return 1
} else {
return fibo(num - 1) + fibo(num - 2)
}
}
作用域:变量可以起作用的范围
如果变量定义在一个函数内部,只能在函数内部被访问到,在函数外部不能使用这个变量,函数就是变量定义的作用域
块级作用域:任何一对 {} 中的结构体都属于一个块,其里面就称为一个块级作用域
在es5之前没有块级作用域的概念,只有函数作用域
局部变量:定义在函数内部的变量,只能在函数作用域被范围到
全局变量:从广义上讲也是一种局部变量,定义在全局的变量,作用域范围是全局,所以js在任意位置都可以被访问到
变量退出作用域(函数调用完毕)之后都会被销毁,全局变量等到关闭网站或者浏览器才会销毁
函数的参数也是是属于函数内的一个局部变量
函数的作用域
只能在这个函数内部被访问
定义在另一个函数内部,如果外部函数没有执行,相当于内部代码没写
function foo1 () {
var a = 1
function foo2 () {
(1)作用域链
每定义一个函数,都会生成一个作用域。函数内部的函数,也会有一个新的作用域。
把这些所有作用域列出来,就会有一个函数内指向函数外的链式结构,叫作作用域链
(2)遮蔽效应
每个作用域都可以访问到外层作用域,若每作用域都有一个值,则会就近作用域依次往外层选取,直到找到第一个变量定义,并遮蔽更上层作用域的值
案例
var a = 1
function foo1 () {
var a = 2
function foo2 () {
var a = 3
console.log(a)
}
foo2()
console.log(a)
}
foo1() // 3 2
比如在函数内部定义新变量不加var,则视为在全局作用域定义该变量。
应该每次定义都书写var,否则会定义在全局,会污染全局变量
执行js代码的时候分为两个过程:预解析和代码执行
预解析
① 把变量的声明提升到当前作用域的最前面
② 把函数的生民给提升到当前作用域的最前面,只会提升声明,不会提升调用
③ 先提升var,再提升function
JavaScript的代码执行过程:在预解析之后,根据新的代码顺序,从上往下按照既定规律执行js代码
在预解析过成功,所有定义变量,都会将声明的过程提升到所在的作用域最上面
只提升声明,不提升变量赋值,相当于变量定义未赋值,变量存储undefined值
所以在定义之前使用该变量,不会报错,只会提示undefined
console.log(a) // undefined
var a = 1
console.log(a) // 1
相当于变成下面的过程
var a console.log(a) a = 1 console.log(a)
在预解析过程中,所有定义的函数会将声明的过程提升到所在作用域最上面
所以可以在声明语句之前就调用该函数
foo() // 不会报错 function foo () {}
先提升var,后提升function
如果变量名和函数名相同,则函数名会覆盖变量名,之后到了变量赋值,一直都是函数
所以不建议变量名和函数名相同
console.log(foo) // 输出函数 foo() // 不会报错 var foo = 1 console.log(foo) // 1 foo() // 会报错 function foo () {}
函数表达式进行的是变量提升,而不是函数声明提升,在赋值之前,会存储undefined先
建议:最好用function来定义函数
console.log(foo) // undefined var foo = function () {} console.log(foo) // 输出函数
开头先声明变量
把赋值放在声明之后
函数声明放在最后
及时调用表达式,也叫自调用函数,表示函数在定义的时候就立刻调用
自调用方式:在函数声明之后立刻加()
注意如果开头是()的话要加上分号!
这种方法会把整段代码矮化成一个表达式
function foo () {}() // 会报错 var foo = function () {}() // 不会报错 ;(function foo () {})() // 不会报错
矮化成表达式
算数运算符 + - () (* / %不能使用,因为前面必须有其它值)
逻辑运算符: ! (|| &&不能使用,前面要有其它值)
+function () { console.log(1) }() // 1 -function () { console.log(1) }() // 1 !function () { console.log(1) }() // 1 ;(function () { console.log(1) })() // 1
自调用的函数执行完就会销毁,外界无法访问函数名和里面定义的东西
IIFE使用的最多的是
标签:应用 meta 返回 ber 浏览器 斐波那契数列 次数 遍历 不能
原文地址:https://www.cnblogs.com/lezaizhu/p/14093698.html