JavaScript-函数

函数的定义语法

function 函数名(){
    代码段
}

function是一个关键字,函数的名字自定义,但取名的规则和变量定义的规则相同。定义好的函数并不会自己执行,而是需要我们进行调用。

函数的调用

语法:
函数名()

举例:

// 定义函数:求两个数的和
function fn(){
    var a = 1;
    var b = 2;
    var c = a + b;
    console.log(c);
}
// 函数定义好以后,不会自动执行,需要手动调用
fn();

赋值式函数

将一个函数代码段赋值给一个变量,这个变量的类型是function类型,变量的值为函数的代码,可以正常的调用,但如果给他赋值的函数是有名称的,那么这个函数名称失效(调用后报错 函数名 is not defined)一般可以在赋值时省略这个名称。
例子:

    var a = function zhubi() {
        console.log('zhubiluohuihuang');
    }
    a();
    console.log(a);
    console.log(typeof a);
    zhubi()

控制台查看结果如下:


赋值式函数

匿名函数

没有名字的函数叫做匿名函数。匿名函数在空间中不能单独的存在,必须用小括号将它包裹。

(function(){
    console.log(13)
})

匿名函数用一种特殊的方式调用,引出了新的概念,自调用函数。

自调用函数

调用匿名函数的语法:

(function(){
    console.log(13)
})()

这样的函数在定义好后被立即调用,同时自调用函数还有两种不同调用的写法,不给函数加小括号而是改用~

!function(){
    console.log(14);
}()

~function(){
    console.log(14);
}()

PS:自调用的函数也可以传递参数。

(function(a,b){
    var c = a + b;
    document.write(c);
})(1,2);

带参数的函数

在函数中的变量需要根据需要发生变化时,就可以定义带参数的函数。形参声明的方法将变量写在定义函数的()中,多个变量用,隔开
例如:

function zizeng(a){  // 叫做形参 - 形式上的参数
    var b = a + 1;
    console.log(b);
}

调用时,需要给形参赋值,在调用的()中从左到右一一对应的写入需要付给形参的值,这些值被称为实参。

zizeng(1); // 实参 - 实际上的参数,实参其实就是给形参赋值

如果没有实参给形参赋值,形参默认是undefined,如果实参数量超出了形参,超出的实参是无效的

带参数的函数

函数的本质

当我们去调用函数的时候,通过函数的名称就可以调用到,那说明我们在定义函数的时候,函数就已经保存起来了,所以下面才能调用出来。
调用函数,就相当于将这段代码拿出来执行。

函数的优点

  1. 实现了代码的可重用性
  2. 实现了模块化编程

带返回值的函数

如果我们需要一个函数调用之后得到的结果,就需要带返回值的函数。返回函数的结果,在函数中使用return关键字,后面跟上要返回的结果,可以使一个变量也可以是其他。
例如:

    function zhubi(a, b) {
        var c;
        c = a + b;
        return c;//返回c为函数计算的结果
    }
    var d = zhubi(3,5) * 4;//执行这里的计算需要return的到函数计算的结果
    console.log(d);//返回结果为32

return关键字除了可以给函数调用返回结果,还可以结束函数运行

结束运行

虽然在函数中有一个字符串输出的代码,但因为return结束了函数的进程,所以代码并没有被输出。

return只能返回一个结果,不能返回多个

若函数中没有加return,那么函数的返回值是undefined,而如果加了return而return后面没有数值,函数返回的也是undefined。

输出undefined

预解析(重要)

js解析器执行代码过程:

1.预解析js代码

预解析的过程就是在代码中查找var与function两个关键字,找到关键字后将,变量定义与函数赋值的过程提升到整一个代码的最前端。所以此时变量的值为undefined因为预解析只是将变量定义放到了代码的最前端,而没有赋值的变量值为undefined。函数为初始值的代码段。

2.执行代码

开始按顺序一行一行解读代码

预解析题目:
题目:

console.log(a)
var a = 10;
test()
function test(){
    console.log("this is test function")
}

题目解析:

var a
function test(){
    console.log("this is test function")
}
console.log(a) // 前面有定义过变量a,没有赋值,所以变量的值为undefined
a = 10; // 将a的值改变为10
test() // 前面有定义过函数,内存中能找到,所以调用成功

一些题目:

// 第1题
console.log(num)
var num = 100
//输出undefined

// 第2题
fn();
function fn() {
    console.log(123);
}
//输出123 因为预解析

// 第3题
console.log(fn)
fn()
var fn = function () {
    console.log(123);
}
//第一个输出undefined
//第二个报错 fn is not a function
//相当于 预解析先定义了一个变量fn 但fn为undefined但不是一个函数 不可以用来调用

// 第4题
fun()
var fn = function () {
    console.log('我是 fn 函数')
}
function fun() {
    console.log('我是 fun 函数')
}
fn()
fn = 100
fn()
//


// 第5题
fn()
function fn() {
    console.log('我是一个 fn 函数')
}
fn()
var fn = 100
fn()
//我是一个fn函数
//我是一个fn函数
//报错
//

/*function fn() {
    console.log('我是一个 fn 函数')
}
var fn
函数和变量的定义词同名 保留函数 忽视变量声明声明
fn()
执行函数
*/

// 第6题
var fun = 200
fun()
var fun = function () {
console.log('我是一个 fun 函数')
}
fun()
// 第7题
var a = b
a = 0
b = 0
console.log(a)
console.log(b)
//没有定义变量b所以报错 报错后 后面的代码不执行


// 第8题
console.log(num)
if (false) {
    var num = 100
}
//输出undefined

预解析的总结:

1.如果变量名和函数名重名了,则保留函数预解析,而忽视变量预解析。
2.不执行的代码中如果有变量或者函数的定义,这些函数与变量也会被预解析。因为预解析在执行之前。
3.如果js的代码报错,则之后的代码不再执行。
4.赋值式函数在预解析时算作定义变量,而不算定义函数。
5.函数会在函数内部进行预解析

函数的调试

示意图

作用域

作用域的定义:能起到作用的区域,因为定义在不同区域的变量,其作用域是不同的。

作用域的分类

全局作用域:

不在任何一个函数中定义的变量叫做全局变量,全局变量的作用域是整一个script区域

<script>
    var a = 6; //全局变量a,作用域范围也包括了下一个script
    console.log(a);
    function fn(){
        console.log(a);
    }
    fn()
</script>
局部作用域:

在函数内部定义的变量,他的作用域的范围就是这个函数,在函数外不能使用这个变量。

<script>
    function fn(){
        var a = 6;
        console.log(a);
    }
    fn() //输出6
    console.log(a);//报错a is not defined
</script>

如果全局和局部有相同的变量名,局部输出时先考虑当前的作用域

<script>
    var a = 12;
    function fn(){
        var a = 6;
        console.log(a);
    }
    fn() //输出6
    console.log(a);//输出12
</script>

作用域链

函数是写在全局当中的,所以局部作用域是嵌套在全局作用域之中的,如果再在函数中嵌套另一个函数,则在局部作用域中又会再嵌套一个局部作用域。这样就形成了作用域的嵌套,由作用域的嵌套引发的链式结构就叫做---作用域链

   var a = 10;

    function fn() {
        var b = 20;
        fun()
        function fun() {
            var c = 30;
            console.log(b);//输出20
        }
        console.log(a);//输出10
    }
    fn()
作用域链

作用域链的规则

  1. 当使用一个变量时,包括:用变量作为值进行赋值、用变量进行计算、输出变量,会先在当前作用域中寻找变量是否有定义过变量,若定义过,正常使用;若没有在这个定义域中定义,则按照作用域链,返回这个定义域的上一级寻找,同理若找到正常使用,若没有找到则重复这个操作直到全局作用域中。若在全局定义域中有,则还是可以正常使用,若没有则在使用中报错:变量名 is not defined.
  2. 当给一个变量进行赋值时,现在当前作用域中查找是否定义过这一个变量,如果定义过则给这个变量赋值。若没有,则和使用变量的原理一样,直到全局作用域。不同的是若是全局作用域也没有定义过这个变量,则规则是在全局定义这个变量,并对他赋值,值为你书写的值。
    一些练习:
// function fn() {
//     console.log(num) // undefined,原因为在函数中也会进行预解析
//     return
//     var num = 100
// }
// fn()
// console.log(num); // 报错

// var num = 10;
// fn1();
// function fn1() {
//     console.log(num);
//     var num = 20;
// }
/*
预解析:
var num
function fn1() {
  var num
  console.log(num); // undefined
  num = 20;
}
num = 10;
fn1();

函数中也会预解析

*/

// var a = 18;
// fn2();
// function fn2() {
//     var b = 9;
//     console.log(a); // 18
//     console.log(b); // 9
// }

// fn3();
// console.log(c);
// console.log(b);
// console.log(a);
// function fn3() {
//     var a = b = c = 9; // b=9
//     console.log(a); // 9
//     console.log(b); // 9
//     console.log(c); // 9
// }

// var a = b = c = 9
/*
相当于:
var a = 9
b = 9
c = 9
*/
// console.log(a,b,c);



// function fn(a) {
//   // var a = 10
//   // -------------------
//   function a() {
//       console.log('我是函数 a')
//   }
//   console.log('我是 fn 函数')
//   a()
// }
// fn(10)
习题总结:
  1. 全局中有预解析,局部中也有预解析,局部的预解析只在局部中进行对全局没有影响。
  2. 在使用 var a = b = c =9这种方式给变量赋值时,只有第一个变量是有定义的过程也就说只有第一个变量定义等同于 var a=9其余都是直接给变量赋值。
  3. 函数定义好以后,函数名就跟变量名一样,可以使用函数名修改这个空间中的值。
  4. 局部的预解析会在形参赋值之后,预解析中的函数会覆盖掉形参赋的值。

递归函数

递归函数就是在函数内部调用自己,形成循环。
使用递归函数时,应该注意要有一个停止函数的条件,否则会形成死循环。

写递归函数的步骤:

  1. 先书写一个空函数,并调用
  2. 调用时传入实参,定义形参
  3. 书写大致的代码
  4. 根据想要实现的效果给递归函数一个停止的条件

用递归函数实现效果:

// 求10的阶和,即:10+9+8+...+1
function facSum(num){
    if(num == 1){
        return 1;
    }
    return num + facSum(num-1);
}
var res = facSum(10);
console.log(res); // 55
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容

  • 每天一句:想说会有多少人问自己一下几个问题“你这辈子到底要什么,要做怎么样的人?你现在能够做什么?你正在做什么?你...
    EndEvent阅读 279评论 0 0
  • 概念 函数(function),也叫作功能、方法,函数可以将一段代码一起封装起来,被封装起来的函数具备某一项特殊的...
    白棠阅读 174评论 0 0
  • 每天一句:想说会有多少人问自己一下几个问题“你这辈子到底要什么,要做怎么样的人?你现在能够做什么?你正在做什么?你...
    王梓懿_1fbc阅读 155评论 0 0
  • 一、函数的概念 函数是一段可以反复调用的代码块。 作用:在程序设计中,常将一些常用的功能模块编写成函数,以减少重复...
    MJ的小世界阅读 146评论 0 1
  • 1. JS函数的概念 2. 函数的作用 3. 使用函数的好处 4.函数的分类 函数可以分为: 系统函数 内置...
    阿里P9王者阅读 349评论 0 0