js函数
概述
函数是抽取的公共代码块,主要是为了复用。函数相当于一个工具需要的时候就可以调用,当我们没有这个工具就需要自己封装。
函数的分类
- 系统函数 (console.log、 toString 等 )
- 内置函数 (Math.pow等)
- 自定义函数 (自己定义的函数)
函数的定义
使用function关键词声明定义 (推荐)
匿名函数的定义 (没有函数名的函数)
function(){
代码块
}
示例
//自执行函数 不需要调用 自动执行(早期的源码设计)
(function () {
console.log('hello world!!')
})()
//使用变量接收匿名函数的函数对象 相当于接收的变量名为函数名(具名函数的第二种写法)
var fn = function () {
console.log('我是匿名函数')
}
//调用 函数名()
fn()
具名函数的定义 (有函数名的函数 复用)
function 函数名(){
代码块
}
示例
function logFn(){
console.log('我是具名函数')
}
//函数调用
logFn()
使用new 关键构建函数对象(不推荐)
var 函数名 = new Function('执行的代码')
示例
//new关键词构建函数对象
var fn = new Function('console.log("hello!!!")')
//函数调用
fn()
预编译机制
概述
预编译指的是js引擎预先编译,它主要针对的是俩个一个使用var关键修饰的变量会进行预编译,使用function修饰的函数会进行预编译。
注意事项
- var关键词不包含赋值过程
- 函数的预编译会比var关键词慢 如果var关键词修饰的变量和函数名同名,那么在预编译的时候函数会覆盖var。
//预编译 就是预先编译 就是指你没执行倒对应的步骤 可以使用预编译的东西
console.log(1)
console.log(2)
console.log(a) //undefined
fn() //可以调用
//var关键词会进行预编译的操作 预编译不包含赋值
var a = 10
//函数也会进行预编译
function fn() {
console.log('123')
}
//函数的预编译慢于var 函数的内容会覆盖var的内容
var fn = 20
console.log(fn) //20
//关键问题
// 具名函数的变量赋值写法
console.log(fn1) //undefined
var fn1 = function () {
console.log('我是匿名函数')
}
console.log(logFn)//函数
// 具名函数的标准声明写法
function logFn() {
console.log('我是具名函数')
}
函数支持传入参数
关键词
- 形参 (形容的参数)
- 实参 (实际的参数 (实际的值))
函数的参数定义
function 函数名(形参1,形参2,形参3....){
代码块
}
示例
求和函数
//a b 为形参
function sum(a, b) {
console.log(a + b)
}
//调用需要传入实参 按照顺序一一对应
sum(1, 2)
练习
封装一个判断是否为回文数的方法
function isPalindrome(number) {
//如果类型不是数值
if(typeof number != 'number'){
//抛出一个错误 直接终止程序 后面的内容也不再执行
throw new Error('参数类型错误')
}
if (number % 10 == 0 && number != 0 || number < 0) {
console.log('当前数不是回文数')
} else if (number >= 0 && number < 10) {
console.log('当前数是回文数')
} else {
var x = number
var y = 0
//反转操作
while (x > y) {
y = y * 10 + x % 10
x = parseInt(x / 10)
}
if (x == y) {
console.log('当前数为回文数')
} else if (y > x) {
//判断当前的y/10是否等于x
if (parseInt(y / 10) == x) {
console.log('当前数为回文数')
} else {
console.log('当前数不是回文数')
}
}
}
}
封装一个函数判断当前传入的数值是否为水仙花数
function isPPDI(n) {
if (typeof n != 'number') {
throw new Error('参数类型错误')
}
if(!(n>=100 && n<1000)){
throw new Error('参数范围错误')
}
//水仙花的特点 个位的三次方+十位的三次方+百位的三次方为本身
if (Math.pow(n % 10, 3) + Math.pow(parseInt(n / 10) % 10, 3) + Math.pow(parseInt(n / 100),3) == n) {
console.log('当前是水仙花数')
} else {
console.log('当前不是水仙花数')
}
}
在定义函数的时候,需要考虑特殊情况
函数传入的实参可变
// 函数的实参个数可变 (多传 少传)
function fn(a, b, c) {
console.log(a, b, c)
}
//多传实参 (避免的)
fn(1,2,3,4)
//少传实参 默认没传的参数的值为undefined
fn(1)
return 关键词
return关键词是用于返回值的,默认没有return的情况下返回的值为undefined
function fn() {
console.log(1)
}
//调用返回的值为undefined
console.log(fn()) //undefined
//返回对应的内容 使用return关键词
function fn1(){
return 10
}
console.log(fn1()) //10
//return关键词 它会直接退出当前的function
function fn2(){
return 20 //一般放在函数的结束位置
console.log('hello') //不会打印
}
console.log(fn2()) //20
注意事项
-
return关键词用于返回对应的function的值,默认没有return返回undefined
-
return会退出当前的function执行,function内的后续代码不再执行
-
return 结束当前function ,throw new error是结束当前的执行程序
//return 和 throw new Error的区别 function fn3(){ return 'world' console.log('你好 我是function后面的代码')//不执行 } fn3() console.log('我是整体后面的代码') //会执行 function fn4(){ //抛出错误 throw new Error() console.log('你好 我是function后面的代码')//不执行 } fn4() console.log('我是整体后面的代码') //不会执行 -
break (用于跳出循环代码块或switch代码块) 和 continue (跳过本次循环)
练习
封装一个俩个数求和的函数
function sum(first,last){
if(typeof first !='number' || typeof last !='number'){
throw new Error('当前传入的参数错误')
}
return first + last
}
//调用
console.log(sum(2,3)) //5
arguments
arguments是一个伪数组(存储多个值的一个列表),主要是接收对应的传入的实参。它是一个内置对象。它存在于function中。
示例
function fn() {
console.log(arguments) //接收的a b c的值
//通过下标来访问arguments里面的值 具备下标 (下标从0开始 到arguments.length-1结束)
console.log(arguments[0]) //获取arguments的第一个值 a
console.log(arguments.length) //获取arguments里面的参数的个数 3
//可以使用循环来进行遍历
for(var i=0;i<arguments.length;i++){
console.log(arguments[i]) //通过下标来访问值
}
}
fn('a', 'b', 'c')
arguments的特点
- arguments存在于function中 (只能在function里面使用)
- arguments的长度通过length属性来获取 (arguments.length 获取长度)
- arguments具备下标,通过下标可以访问对应的arguments里面的元素(下标从0开始 到arguments.length-1结束)
- 如果使用arguments来获取实参,那么对应的形参就不需要定义
练习
传入不定的值来计算他们的和
function sum(){
//通过arguments接收传入的实参 进行遍历计算
var sum = 0
//for循环遍历arguments
for(var i=0;i<arguments.length;i++){
sum += arguments[i]
}
return sum
}
//调用
console.log(sum(1,2,3,4))
console.log(sum(7,8,9,10,11))
console.log(sum(45,67))
传入不定个数的值 得出他们的最大值
//获取最大值
function getMax() {
var max = arguments[0]
//遍历arguments数组
for (var i = 1; i < arguments.length; i++) {
//如果比最大值还大那么重新赋值
if (max < arguments[i]) {
max = arguments[i]
}
}
return max
}
//调用
console.log(getMax(1, 3, 4, 8, 6, 9))
console.log(getMax(37, 1, 2))
作用域及作用域链
作用域
一个变量的作用范围称为作用域
作用域的划分
- 全局作用域 (全局都可以访问 全局声明)
- 局部作用域 (在局部才可以访问 函数内声明的 (函数作用域))
示例
console.log(a) //undefined
var a = 10 //全局作用域
function fn() {
console.log(a) //访问的局部作用域 undefined
var a = 11 //局部作用域
var b = 20
console.log(a) //访问的局部作用域 11
}
fn()
console.log(a) //访问的全局作用域 10
console.log(b) //b is not define
全局作用域可以在全局访问 局部作用域只能在局部访问 外部不能访问
作用域链
根据作用域查找对应的变量的过程称为作用域链
function允许嵌套
console.log(a) //undefined
var a = 10
function fn(){
fn1()
console.log(a) //全局作用域 10
function fn1(){
fn2()
console.log(a) //局部变量 30
var a = 20 //局部作用域
function fn2(){
console.log(a) //局部变量 fn1里面的a undefined
a = 30 //局部变量 fn1里面的a赋值
console.log(a) // 30
}
}
}
fn()
console.log(a) //全局变量 10
作用域链一层一层的向外找(没有var关键词声明)找最近的var关键词声明的变量。
事件驱动
利用dom操作中的事件来执行对应的方法
获取dom元素
document.getElementById(id选择器名字) //根据id获取元素
获取input框的值 value属性
<!-- 使用事件驱动 onclick 点击事件
当你点击按钮的时候 自动执行handler函数 事件驱动
-->
<button onclick="handler()">获取input框的值</button>
<input type="text" id="input">
<script>
function handler(){
//获取input框
var input = document.getElementById('input')
//打印input框的值
console.log(input.value)
}
</script>
显示内容到标签中 使用innerHTML属性
<!-- 计算俩个数的和 -->
<input type="text" id="number1"> +
<input type="text" id="number2"> =
<span id="result"></span>
<input type="text" id="sum">
<button onclick="sum()">计算</button>
<script>
function sum(){
//获取俩个input框的值
var number1 = document.getElementById('number1').value
var number2 = document.getElementById('number2').value
//显示到span中
document.getElementById('result').innerHTML = Number(number1) + Number(number2)
//显示在input中
document.getElementById('sum').value = Number(number1) + Number(number2)
}
</script>
递归 (Ologn)
递归是一个基础算法,它可以完成任何循环可以完成的操作。
递归三要素
- 找初始值(没有规律的值)
- 找规律
- 自己调自己 (在函数内部调用自己这个函数)
简单递归
function fn(参数){
if(没有规律的条件){
//返回没有规律的值
}else{
//返回有规律的值 自己调用自己
}
}
示例
打印1-100的值
function fn(n){
console.log(n)
if(n==1){
return 1
}else{
return fn(n-1) + 1
}
}
fn(100)
1 3 5 7 9 打印第一百位的值
//1 3 5 7 9打印100位的值
function fn1(n) {
if (n == 1) {
return 1
} else {
//上一位的值 + 2
return fn1(n - 1) + 2
}
}
console.log(fn1(100))
1 1 2 3 5 取第十位的值
//1 1 2 3 5 取第十位的值
function fn2(n) {
if (n == 1 || n == 2) {
return 1
} else {
//当前的值 = 上一位的值 + 上上的位的值
return fn2(n - 1) + fn2(n - 2)
}
}
console.log(fn2(10))
2 5 9 14 20求第十位的值
//2 5 9 14 20求第十位的值
function fn3(n) {
if (n == 1) {
return 2
} else {
//上一个值 + n + 1
return fn3(n - 1) + n + 1
}
}
console.log(fn3(10))
10的阶乘
//1*2*3*4*5...
function fn4(n){
if(n==1){
return 1
}else{
return fn4(n-1) * n
}
}
console.log(fn4(10))