js函数、作用域问题
概述
本文主要介绍函数的概念、作用。以及在js中如何封装一个函数,并且会讲解变量作用域的问题,js预解析问题。配合demo让我们快速上手js函数。
1. 函数
1.1 函数概念,函数作用,函数构成。
函数概念: 函数是一种可重复使用的代码块,用于执行特定的任务。
函数作用:
1.代码复用:将功能封装成函数,避免在程序中多次编写相同的代码。这有助于提高代码的可读性和维护性。
2.模块化:函数可以将复杂的操作分解为较小的部分,使程序更易于理解和维护。这有助于实现模块化编程,提高代码的可扩展性和可重用性。
3.抽象和封装:函数可以将数据和功能进行抽象,从而隐藏实现细节。这有助于降低模块间的耦合度,提高代码的灵活性和可维护性。
4.性能优化:通过将重复的计算逻辑封装成函数,可以减少程序中的重复计算,提高程序的性能。
函数构成: 函数一般由 函数名
、 参数
、函数体代码
、返回值
四个部分组成。
1.2 定义函数、调用函数
在 js 中定义函数的关键字为: function
函数定义有两种方式: 声明式定义 、 赋值式定义
重点掌握声明式定义函数、赋值式定义了解即可,稍后会讲到区别
定义的函数名规则和规范与变量名一致,应做到见名知意。下面使用定义一个简单的函数用于实现1-n的累加和。
// 声明一个getSum函数,用于实现1-n的累加和
function getSum(n){ // n为参数
var sum = 0 // 用于进行累加
for(var i = 1; i<=n; i++)
sum += i
return sum // 函数返回值
}
var res = getSum(10) // 调用函数
console.log(res) // 打印结果
// 赋值式定义、了解即可
var getSum_ = function (n){
var sum = 0
for(var i = 1; i<=n; i++)
sum += i
return sum
}
步骤 | 说明 |
---|---|
1 | 使用function定义名为getSum的函数 |
2 | 函数的参数[根据需求可不写,可写多个] |
3 | 函数体代码[根据需求编写功能] |
4 | 函数返回值[一般需要返回值] |
5 | 函数调用[不调用函数不会执行] |
声明式定义与赋值式定义在调用时写法相同。
1.3 函数参数
-
函数的参数
形参: 形参是定义在函数中的变量,它用来接收函数调用时传递的值。`在js中不需要声明类型,可接受各种类型数据` 实参: 实参是函数调用时传递给函数的实际值。 在1.2小节中,步骤二的n就是一个形式参数, 步骤5的‘10’就是一个实际参数。
-
实参和形参的个数关系
实参个数和形参个数相等 实参会从左往右一一给形参赋值 实参个数小于形参个数 多出形参的值是undefined 实参个数大于形参个数 多出实参没有任何作用
1.4 函数返回值
返回值关键字为: return , 且函数只可以有一个返回值
一个函数被调用后应该需要有一个返回值或者相应的文本提示!
作用: 函数调用之后得到的结果,可以用于下一步的运算或者判断
比如在js中提供的一些内置函数:
- var 变量1 = Number(数据)
- var 变量2 = parseInt(数据)
- var 变量3 = parseFloat(数据)
- 函数默认是没有返回值 他的返回值是undefined
- 如果函数需要有一个返回值 可以在函数定义的内部写一个return return后面的数据就会当成函数的返回值
1.5 js中的特殊函数
了解一下即可
1. 匿名函数 -- 没有名字、多用于事件处理函数
function(){
}
2.自执行函数、多用于封装插件库、用一个匿名将代码包裹、里面的变量均为局部变量
(funtion (num){
})(222)
(function name(){
})()
1.6 函数demo
1.使用函数封装一个简易计算器
/*
calc('+', 1, 2) // 3
*/
function counter(operator, num1, num2){
var res = 0
if(operator==='+'){
res = num1+num2
}else if(operator==='-'){
res = num1-num2
}else if(operator==='*'){
res = num1*num2
}else if(operator==='/'){
res = num1/num2
}else{
res = '你输入有误!'
}
return res
}
console.log(counter('+',5,2))
console.log(counter('-',5,2))
console.log(counter('*',5,2))
console.log(counter('/',5,2))
以上是使用js实现简易计算器, 函数名为counter、形式参数有三个operator、num1、num2,形式参数的作用也在告诉我们如何去使用这个函数,应该传入什么数据,该函数有一个返回值 res用来保存计算结果并且返回给调用处。console.log(counter(‘+’,5,2)) 直接将返回值打印到控制台。
2. 变量作用域
在学习函数时,应给变量划分为两大类:
1. 全局变量:
作用域为全局作用域,指的是在函数外部定义的变量,它们可以在整个程序中被访问和使用。
2. 局部变量:
作用域为局部作用域,指的是在函数内部定义的变量,它们只能在函数内部被访问和使用。在函数内部定义的变量称为函数参数和函数内部的变量。
// 全局变量
var num1 = 1, num2 = 2
function func1(){
num1++
// 局部变量
var num2 = 3, num3 = 3
num2++
console.log(num1)
console.log(num2)
}
func1()
console.log(num1)
console.log(num2)
console.log(num3)
根据打印的结果发现,函数内部输出的num1与外部输出的num1值相同,num1++使用的是外部的全局变量num1,而函数内部num2++以及内部输出的num2使用的是局部变量num2并没有改变全局变量num2,内部定义的num3在函数体外部也无法访问。这与全局作用域和局部作用域对应。
需要注意的是: 当函数内部有定义的变量会优先使用内部定义的,遵循就近原则。当函数内部无定义就会向包裹它的上个作用域寻找直到全局作用域,若还没有就是没定义该变量,此时会报错 xxx is not defined
若外部,内部均无var声明的num,此时浏览器会将num4解析为全局变量。
function func1(){
num4 = 6
console.log(num4)
}
console.log(num4)
3. js中的预解析
预解析:当JavaScript引擎解析脚本时,他会在预编译阶段对所有声明的变量和函数进行处理,并且是先预声明变量,再预定义函数!
- 内容:(预解析做了哪些事情)
- 会将声明式的函数提前定义
- 会将var声明的变量提前定义;只是定义提前没有将赋值提前
- 影响:(预解析有什么样的影响)
- 声明式函数可以提前调用
- var声明的变量可以提前使用但是使用的值是undefined
3.1 声明式定义与赋值式定义的区别
function print(){
console.log('我是声明式定义')
}
print()
var print_ = function (){
console.log('我是赋值式式定义')
}
print_()
这样似乎并没有区别, 我们将调用语句均提前看一下!
提前后发现声明式正常调用,赋值式报错无该方法,这是为什么呢?
这里就和js的预解析有关系了,预解析将声明式函数提前执行,所以提前调用也可以查的到,但赋值式将print_解析成了一个变量,我们说预解析只会提前声明var关键字定义的变量但不会提前赋值,所以此时只能找到值为undefined的print_变量而不是一个函数
函数还有一个特殊用法 递归
由于用法特殊所以在后续进行讲解。