day04函数
概述:
函数相当于一个代码空间,这个空间可以存储一些代码片段,一般我们会将一些功能性代码放到函数内,这样的操作是封装,核心是利用函数来减少多余代码,形成复用
函数分类
系统函数(系统本身写好的,只需要调用console.log() 属于全局窗口的window)
内置函数
自定义函数
函数定义
使用function关键来定义
定义的方式
匿名函数(没有名字的函数 无法复用) 自己执行
//自执行函数,自己执行 准备工作的执行(框架的封装)
//前面的()表示他是一个整体,后面()表示执行函数
(function(){
console.log('我是匿名函数')
})()
具名函数
/*
function 函数名(形参...){
函数体
}
*/
/*
function sayHello(){
console.log('hello')
}
sayHello()
*/
调用 函数名()
结合匿名函数来声明具名函数
var sayHi = function(){
console.log('he')
}
sayHi()
使用对象构建的形式(new关键练构建)
// new Function('函数体')
var fn = new Function('console.log('你好')')
fn()
函数的执行过程
预编译过程
预编译过程 var关键词修饰的变量会预编译
function 关键词修饰的变量也会预编译
console.log(a)//undefined
var a = 10
console.log(a) //10
fn() //也能执行 function会被预编译
function fn(){
console.log('声明')
}
//fn()
//var关键词预编译不会进行读取操作 报错is not a function
//fn1() //var关键词预编译不会进行读取操作 报错is not a function
var fn1 = function(){
console.log('tack')
}
fn1()
执行过程
函数声明会发生预编译 调用的时候会发生声明操作?
-
他回去寻找对应堆空间的函数引用
-
再将它推入执行栈中
-
进行执行
-
在执行栈中会打开对应函数内的代码进行执行
-
执行完毕后 gc会将它回收(可达性)
回收过程
gc是一个垃圾回收机制(用于回收当前没有被使用的变量)(浏览器回收)
回收器
主回收器 Major gc (常用的,回收大的对象 明显)
副回收器 Minor gc (回收碎片haunt内容 使用频繁)
回收机制
标记清除(通过设置 true false)
引用清除(引用操作进行++)
函数的参数
没有实际值的参数是形参 用于定义(随便写)
有实际值的参数是形参 用于传递
//a b为形参
function sum(a,b){
console.log(a+b)
}
sum(1,2) //1 2为实参
注意事项:js运行可以少传参数 但是这个参数没有被使用到 (没有函数的调用) 否则会出错
示例
传入一个数判断是否回文
function isPalindrome(n) {
//判断当前是否为数值
if(isNaN(Number(n))){
//错误提示
// console.error('当前输入的内容出错')
//抛出一个新的错误 底下的内容不会被执行
throw new Error('当前输入的内容出错')
}
//个数为0不可能是回文数
if(n%10==0 && n!=0){
console.log('这个数不是回文数')
}else if (n < 10 && n >= 0) { //小于10 大于0的数为回文
console.log('当前数为回文数')
} else {
//需要将当前这个数进行反转
var x = n
var y = 0
//反转操作
while (x > y) {
y = y * 10 + x % 10
x = parseInt(x / 10)
}
//偶数情况下
if (x == y) {
console.log('当前数为回文数')
} else if (x == parseInt(y / 10)) {
console.log('当前数为回文数')
} else {
console.log('这个数不是回文数')
}
}
}
isPalindrome(prompt('输入数值进行判断'))
传入一个数是否为水仙花数
function isNarcissusNumber(number){
//判断当前是否为数值
if(isNaN(Number(n))){
//错误提示
// console.error('当前输入的内容出错')
//抛出一个新的错误 底下的内容不会被执行
throw new Error('当前输入的内容出错')
}
//验证
if(Math.pow(number%10,3)+Math.pow(parseInt(number/10%10),3)+Math.pow(parseInt(number/100),3)==number){
console.log('当前数为水仙花数')
}else{
console.log('当前数不是水仙花数')
}
}
isNarcissusNumber(prompt('输入数值进行判断'))
函数考虑其复用性的同时,必须考虑多种情况
return关键词
return是用于函数中返回对应的结果,默认情况下函数return undefined,当return完那么对应的函数也就执行结束了.
function fn(){
}
console.log(fn())//undefined
示例
输入两个数返回他们的和
function sum(number1,number2){
return number1 + number2
consoloe.log('我是后面的代码')
}
var i = sum(5,8)
console.log(i)
练习
输入两个数,返回他们的最小公倍数和最大公约数
function fn(x,y){
//得到最小公倍数和最大公约数
var max = Math.max(x,y)
var min = Math,min(x,y)
while(true){
if(max % x == 0 && min % y == 0){
break
//得到最小公倍数
}
max++
}
while(true){
if(x%max==0 && y%min==0){
break
}
min--
}
return max+min
}
总结
-
break跳出循环和switch 不会结束function
-
continue 只能用于循环中 跳出本次循环 进入下次
-
return 结束整个函数,返回对应的数据(放在最后)
-
throw new Error 结束整个循环
arguments
arguments是一个参数列表,参数列表是一个伪数组(伪装的数组 有数组的一些特性,但是不是数组(不具备数组的方法)) 他可以用于获取所有的参数(传递的参数)
function fn(a, b, c) {
console.log(arguments) //[1,2]
//arguments 长度属性 length (实际传入的参数个数) callee 指向的是当前的方法
console.log(arguments.length)
//访问 arguments里面的参数 使用对应的下标来访问 下标从0开始 到length-1结束
console.log(arguments[0])//获取第一个参数 1
console.log(arguments[1])//获取第二个参数 2
}
fn(1, 2)
arguments的属性,方法
-
length属性 用于获取对应的传入的参数个数
-
callee方法 指向当前函数
arguments访问对应参数使用下标
-
下标从0开始 到 arguments.length-1结束
-
0表示是第一个参数 那么5表示第六个参数 x表示x+1个参数
-
省略对应的形参 直接传入实参 在函数中使用arguments来接收的对应的实参
传入不定参数,计算他们之间的和
function sum(){
var result = 0
//arguments 会接受所有的实参 那么我们就可以通过循环遍历对应的参数进行操作
for(var i=0;i<=arguments.length-1;i++){
result+=arguments[i]
}
return result
}
console.log(sum(3,5,8,4,7,))
console.log(sum(3,5,8,4,7,3,5,8,4,7))
作用域及作用域链
作用域该数
一个变量的作用范围称为作用域,作用域主要划分为全局作用域(全局可用),局部作用域(局部可用 又为函数作用域)
示例
var a = 10 //全局变量
function fn(){
var a = 20 //局部变量
var b = 30
}
fn()
console.log(a)//10
console.log(b) //b is not undefined
全局变量不能访问局部变量
console.log(a)//undefinde
var a = 10
function fn(){
// a = undefined
a = 20 //局部变量赋值
console.log(a) //局部变量打印
var a = 30 //局部作用域 var修饰关键进行预编译
}
function fn1(){
a = 40 //全局作用域
var b = 30
console.log(a+b)
}
function fn2(){
//预编译
console.log(a) //undefined
var a = 50
}
fn1()//70
console.log(a)//40
fn()//20
console.log(a)//40
fn2()//undefinde
console.log(a)//40
-
var 关键词会进行变量提升
-
只要是在function中使用var关键词声明那么这个变量就是局部变量 那么在这个里面使用到所有这个变量都是指向这个局部变量
-
如果在function中没有使用var关键词声明那么这个变量就是全局变量
作用域链
作用域链就是逐层向上查找对应的作用域(变量声明)形成的链子,如果没有找到那么就会报错。
var a = 10
function fn(){
console.log(a)//undefinde
var a = 20 //局部变量赋值
function fn1(){
console.log(a) //20
function fn2(){
console.log(a)//20
}
fn2()
}
fn1()
}
fn()var x = 1;
function f(x, y = function () { x = 3; console.log(x); }) {
console.log(x)//undefinde
var x = 2
y()//3
console.log(x)//2
}
f()
console.log(x)//1
//undefinde 3 2 1
事件驱动
事件驱动就是说通过触发一个行为执行对应的函数,这个被称为事件驱动
获取输入框的值
html准备
<input type="text" id="input"><button id="btn">点击按钮</button>
2.点击按钮 触发对应的事件 来执行对应的函数 (不需要手动调用的)
btn.onclick = fn
3.在函数内打印input框中的内容
-
获取输入框
-
拿到输入框的值
function fn(){
//获取输入框
var input = document.getElementById('input')
//获取输入框的值
var value = input.value
console.log(value)
}
简单的dom操作
-
通过id获取对应的dom元素(标签)
-
document.getElementById('id名字')
递归 (Ologn)
递归是一个算法,算术其实就是固定的套路,递归算法是为了降低时间复杂度提高效率所设计的算法,他可以完成所有循环可以做的事情。
递归的用途 (可以在不知道层级的情况下走到底)
-
文件目录遍历
-
DFS查找
-
多级对象分析合并
-
深拷贝
-
...
递归的流程
-
初始值 (不变的值)
-
规律
-
自己调自己
示例
function 函数名(参数){
if(条件){
初始值 进行返回
}else{
规则值 返回值 自己调用自己
}
}
求1-100的和
//n表示次数 1次 值为1 2次 值为3
function fn(n){
if(n==1){
return 1
}else{
return n+fn(n-1)
}
}
console.log(fn(100))
求1-100之间的偶数和
//n表示次数 50
function fn1(n){
if(n==1){
return 2
}else{
return fn1(n-1)+2*n
}
}
fn1(50)
1 1 2 3 5 8 13 21 第20位是什么
function fn(n){标签:function,console,log,day04,var,fn,函数 From: https://www.cnblogs.com/buyAVnub/p/17132205.html
if(n==1 || n==2){
return 1
}else{
return fn(n-1)+fn(n-2)
}
}
console.log(fn(20))