前言
函数是javaScrit中的一个基本概念,学习好函数及其重要, 在本文中,我们介绍函数的基本语法、如何定义和调用、范围和参数等,让你没有任何基础也能看懂。
目录
什么是函数
假如我们项目程序有10万行代码,我们在第1万行中写了个功能,假如我们在第2万行中,又用到了这个功能,我们可以复制粘贴的方法实现,后来我们又在第3万行中用到这个功能,我们又采用复制粘贴的方式。
这个方法是可行的,但是某一天,我们想将这个功能修改,这样子我们要就需要改很多行代码,所以,我们希望有个地方给我们的代码存起来,我们每次使用就用我们已经存储好的代码块,改只需要在这个存储的地方上改,而实现这个功能的东西就是函数。
创建一个函数
基本语法
function fn(){
语句...
}
我们通过function 定义函数,函数的使用分为了两个步骤,一个是函数的 定义,定义函数名与函数体内部需要操作的语句,第二部是调用函数,也就是使用函数,我们看以下例子。
function fn(){
//定义函数名为 fn,函数体内容为打印
console.log('你好,你今天学习了吗');
}
fn();//调用函数
函数的创建方式
在上述函数创建方式之外,函数还有其他两种创建方式
1)函数表达式
const fn = function(){
语句...
}
const fn = function(){
console.log('你好,你今天学习了吗');
}
fn();
通过将函数赋值给一个变量来创建函数
2)箭头函数
箭头函数可以让我们编写语句更加简短的函数,我们可以将function关键词省略,()以及{}的含义不变。
const fn = ()=>{
语句...
};
函数参数
普通函数参数
在定义函数时,可以在函数中指定数量不等的形式参数(形参),在函数中定义参数,相当于在函数内部声明了对应的变量,但是没有赋值,我们通过在 ( ) 内写参数名,即可定义函数的参数
function Name(parameter1, parameter2, parameter3) {
要执行的代码
}
- JS函数定义不会为参数(parameter)规定数据类型,也就是我们不需要考虑参数数据类型
- JS函数不会对所传递的参数(argument)实行类型检查,也就是我们不需要考虑参数类型
- JS函数不会检查所接收参数(argument)的数量,也就是我们在()内写多少个参数都行
我们先定义一个最简单的求和函数
function sum(a,b){
console.log(a+b);
}
sum(3,5);
我们在调用函数的时候,就把3赋值给了a,把5赋值给了b,最后在代码块中完成了操作
而在调用函数时,在函数的()传变量数量与在函数定义中()的变量数量不等时,将会出现以下几种情况。
1.如果实参(调用函数时传入的参数)形参(定义函数时声明的参数)数量相同,则使用时一 一对应。
function test(a,b){
console.log(a);
console.log(b)
}
test(5,3);
2.如果实参多余形参,多余的实参不会使用
function test(a,b){
console.log(a);
console.log(b)
}
test(5,3,5);
3. 如果实参少于形参,多余的形参,赋值为undefined
function test(a,b){
console.log(a);
console.log(b)
}
test(5);
箭头函数的参数
const fn1 = (a,b)=>{
console.log("a = ",a);
console.log("b = ",b);
}
箭头函数只有一个参数时,可以省略括号
const fn2 = a=>{
console.log("a = ",a);
}
定义参数时,可以为参数指定默认值
const fn3=(a=10,b=20,c=30)=>{
console.log("a = ",a);
console.log("b = ",b);
console.log("c = ",c);
}
fn3(1,2);
如果没有传c就会使用默认值,在没有对应实参时使用,避免出错
argument对象
JavaScript 函数有一个名为 arguments 对象的内置对象。也就是我们无需定义,在函数内部都可以直接调用的对象。
arguments 对象包含函数调用时使用的参数数组
function findMax() {
let i;
let max = -Infinity;
for (i = 0; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
x = findMax(1, 123, 500, 115, 44, 88);
以上例子 argument就是一个参数数组。可以得出argument[0]==1,argument[1]==123,以此类推
函数的返回值
普通函数的返回值
我们可以用return关键词来返回函数的值,如果return不返回任何值,就是返回undefined
function sum(a,b){
return a+b;
}
console.log(sum(2,4))
我们可以看到,sum(2,4)所代表的值就是 6 ,我们也可以将这个值赋值给一个新的变量,方便后续使用。
注意:return 之后函数立刻执行结束 ,不会再执行retrun后面的函数
箭头函数的返回值
/*
箭头函数的返回值可以直接写在箭头后面
*/
const sum = (a,b)=>{
return a+b;
}
let result = sum(a,b)
console.log(result);
//如果箭头函数的执行语句只有一句,则可以省略{},并将该语句的值当作返回值。
const sum1 = (a,b)=>a+b;
// 如果直接在箭头函数后面设置对象为返回值,对象字面量必须使用()来包围
const fn = (a,b)=>({name:'qibai'});
作用域
全局与局部作用域
作用域指一个变量的可见区域,作用域可以分为全局作用域与局部作用域
- 全局作用域
- 生命周期:全局作用域在网页生成时创建,在网页关闭时销毁
- 所有直接编写到script中的变量位于全局作用域中
- 全局作用域中的变量叫做全局变量,可以在任意位置访问(使用)
- 局部作用域(在{ }内)
- 块作用域(在{ }内的代码)
- 块作用域在代码块执行时创建,在代码执行完销毁
- 在块中的变量为局部变量,只能在块内部访问,其余都不能访问
- 函数作用域(实际上也是在{ })
- 调用时创建,代码生成玩之后销毁
- 函数每次调用都会产生一次新的函数作用域
- 变量为局部变量,只能在函数内部访问
let a = 'a';
console.log(a);
{
let b = 'b';
console.log(b);
}
这是一个块
console.log(b);
这个console.log(b)就访问不到b了
作用域链
当我们使用一个变量时,JS解释器会优先在当前作用域中寻找,如果找到则直接使用,如果没有找到,则向上一层作用域中找变量,如果一直没找到,则报错 xxx is not defined,我们看以下例子
let a = 10;
{
let a = 20;
{
console.log(a);
}
}
函数的作用域链同理
windows对象
在浏览器中,浏览器为我们提供了一个window对象,可以直接访问。
window对象代表的是浏览器窗口,通过该对象可以对浏览器窗口进行各种操作,除此之外,window对象还负责存储JS中的内置对象和浏览器的宿主对象
alert(window)
String();
Number();
这些对象是ES都定义好的,叫做内置对象,这些对象就是存在window中,alert叫做宿主对象,也是存在window中。document.write console.log document console 都属于宿主对象
window可以通过window对象访问,可以直接访问比如: window.alert()与alert()的效果是一样的
以下为补充:
window.a = 10; //向window对象中添加的属性会自动变成全局变量
console.log(a);
/*
var 用来声明变量,作用与let相同,但是var不具有块作用域
在全局中使用var声明的变量,都会变成window对象的属性保存
使用function声明的函数,都会作为window的方法保存
*/
var b = 20;
console.log(window.b)
函数中的this
普通函数中的this
函数在执行时,JS解释器每次都会传递一个隐含的参数,这个参数名字叫做 this,与前文argument一样,我们能够直接使用。我们先来看看这个this是什么。
function fn(){
console.log('打印',this)
}
fn();
我们看到目前 this是指向一个window对象。这种形式叫做以函数的形式去调用,this指向的是window对象。我们再来尝试下面这个例子。
function fn(){
console.log('打印',this)
}
const obj = {name:'qi_bai'};
obj.test = fn;
const obj2 = {name:'name',test:fn};
obj.test();
obj2.test();
以方法的形式调用,this指向调用方法的对象,通过this可以调用方法中的对象
我们看到目前的this指向其外层的对象,所以this所指向的对象会根据函数调用方式的不同而不同。实际上我们可以理解为,this指向离自己作用域链最接近的外层对象,如果this所在的作用域外层没有其他对象,就会指向window对象。(注意一定是指向对象,函数不是啥对象当然不能指向一个函数)
箭头函数中的this
function fn(){
console.log('hello',this)
}
fn()
const fn2 = ()=>{
console.log('nihao',this)
}
fn2();
const obj = {name:'qi_bai',fn:fn,fn2:fn2}
obj.fn();
obj.fn2()
//箭头函数没有自己的this,需要靠this的外层作用域来决定
以上内容如有错误,麻烦大家在评论区指正,让我们共同进步。 加油!!!
如果对您有帮助就给一个关注支持一下吧。