JavaScript网页编程之函数

function fbo(a) {

if(a == 1 || a == 2){

return 1;

}else {

return fbo(a - 1) + fbo(a - 2);

}

}

console.log(fbo(1));

console.log(fbo(2));

console.log(fbo(3));

console.log(fbo(4));

作用域


变量可以起作用的范围

  • 函数作用域:如果变量定义在一个函数内部,只能在函数内部被访问到,在函数外部不能使用这个变量,函数就是变量定义的作用域。

  • 块级作用域:任何一对花括号{}中的结构体都属于一个块,在这之中定义的所有变量在代码块外都是不可见的。

  • 在es5之前没有块级作用域的概念,只有函数作用域,现阶段可以认为JavaScript没有块级作用域。

变量根据作用域不同划分为两类

  • 全局变量:从广义上来说,也是一种局部变量,定义在全局的变量,作用域范围是全局,在整个 js 程序任意位置都能够被访问到。

  • 局部变量:在函数被调用,内存会开辟一部分空间去执行函数并声明其中的局部变量,当函数执行完,这块内存区域就会立即被释放。(函数的形式参数也属于局部变量)

  • 两者的区别:变量退出作用域之后会销毁,全局变量关闭网页或浏览器才会销毁。

参数和函数的作用域

  • 函数的形式参数也属于局部变量。,函数的参数也是属于函数自己内部的局部变量,只能在函数内部被使用,在函数外面没有定义。

  • 在函数中定义的函数,只能在定义函数的函数的范围内进行调用,到了全局会失效。

// 不正确的写法

function outer(a) {

a = 1;

console.log(a);

function inner() {

console.log(“我是inner”);

}

// 正确写法:在这里进行调用 inner();

}

// 调用函数

outer(1);

inner(); // 控制台会报错,undefined

作用域链和遮蔽效应

  • 只要是代码,就至少有一个作用域,即:全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。

  • 作用域链:将这样的所有的作用域列出来,可以有一个结构 -> 函数内指向函数外的链式结构

    • 案例:

// f1函数:0级链

function f1() {

// f1函数中的num变量:1级链

var num = 123;

// f1函数中的f2函数:1级链

function f2() {

// f2函数中的num变量:2级链

console.log(num);

}

f2();

}

// num变量:0级链

var num = 456;

f1();

案例配图:

  • 遮蔽效应

    • 程序在遇到一个变量时,使用时作用域查找顺序,不同层次的函数内都有可能定义相同名字的变量,一个变量在使用时,会优先从自己所在层作用域查找变量,如果当前层没有变量定义会按照顺序从本层往外依次查找,直到找到第一个变量定义(如果一直没有找到,那么就会在控制台报错 is no defined.)。整个过程中会发生内层变量遮蔽外层变量的效果,叫做“遮蔽效应”。
  • 案例:

/*

找不到的情况:

当执行f2()函数中的console.log(num);时,

会先查找f2()函数(2级链)中是否有num,有就输出;

假设不存在的话,就会往上一层f1()函数(1级链)中去找,有就输出num;

假设还是不存在的话,就还要往上一层找,有就输出num(当前已是最外层:0级链);

假设还是不存在的话,程序就会在控制台报错。

遮蔽效应:最近的会遮盖较远的

*/

// num变量:0级链

var num = 456;

// f1函数:0级链

function f1() {

// f1函数中的num变量:1级链

var num = 123;

// f1函数中的f2函数:1级链

function f2() {

var num = 78;

// f2函数中的num变量:2级链

console.log(num);

}

f2();

}

f1();

不写var关键字的影响

  • 在函数内部想要定义新的变量,如果不加关键字 var,相当于定义的全局变量。如果全局也有相同的标识符,会被函数内部的变量影响,局部变量污染全局变量。

// 全局变量

var a = 1;

function fun() {

a = 2;

console.log(a); // 2

}

// 局部变量污染全局变量。

console.log(a); // 2

预解析


  • javascript代码的执行是由浏览器中的javascript解析器来执行的。javascript解析器执行javascript代码的时候,分为两个过程:预解析过程和代码执行过程。

  • 预解析过程:

    • 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。
  • 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。

  • 先提升var,再提升function

  • javascript的执行过程:在预解析之后,根据新的代码顺序,从上往下按照既定规律执行js代码。

变量声明提升

  • 提升过程中,只提升声明过程,不提升变量赋值,相当于变量定义未赋值,变量内存储undefined 值。

  • 因此,在js中会出现一种现象,在前面调用后定义的变量,不会报错,只会使用undefined 值。

函数声明提升

  • 在预解析之后的代码执行过程中,函数定义过程已经在最开始就会执行,一旦函数定义成功,后续就可以直接调用函数。

  • 因此,在 js 中会出现一种现象,在前面调用后定义的函数,不会报错,而且能正常执行函数内部的代码。

提升顺序

预解析过程中,先提升 var 变量声明,再提升function 函数声明。

  • 假设出现变量名和函数名相同

// 模拟预解析过程

/*

提前变量声明,执行后fun = undefined

var fun;

提前函数声明,执行后fun中覆盖前面的undefined,变成fun函数的定义过程

function fun(a) {

a = 1;

return a;

}

*/

/* 执行下面这句输出语句,得到的结果:

ƒ fun(a) {

a = 1;

return a;

}

显然可以看出来undefined已经被覆盖

*/

console.log(fun);

// 在函数定义过程前面调用函数,也不会报错

var b = fun();

console.log(b); // 1

// 函数定义

function fun() {

return 1;

}

// 给fun赋值,fun变成Numner类型

var fun = 1;

console.log(fun); // 1

/* 再次调用fun函数的时候,就报错了

Uncaught TypeError: fun is not a function

类型错误:因为前面给fun赋值为一个数字类型了,其已经不是函数,无法执行调用。

*/

var c = fun();

console.log©; // Uncaught TypeError: fun is not a function

    • 如果调用标识符的过程在源代码函数和变量定义后面,相当于函数名覆盖了一次变量名,结果在执行到变量赋值时,又被新值覆盖了函数的值,那么在后面再次调用标识符,用的就是变量存的新值。
  • 那么后提升的函数名标识符会覆盖先提升的变量名。

  • 在后续的代码中出现调用标识符时,内部是函数的定义过程,而不是undefined.

  • 建议:不要书写相同的标识符给变量名或函数名,避免出现覆盖。

函数表达式的提升

  • 在预解析过程中,函数表达式进行的是变量声明提升,而不是函数声明提升。提升后变量内部存的是一个 undefined。在前面进行函数方法调用,数据类型会提示错误。

/* 模拟预解析

var foo;  此时内部存储:undefined

因此使用函数表达式方法,不能再函数定义过程之前调用函数,会报错

*/

foo();  // Uncaught ReferenceError: fun is not defined

var foo = function (){

console.log(5);

}

  • 建议:定义函数时,最好使用 function 关键字定义方式,这样函数声明提升可以永远生效。

函数声明提升的应用

  • 函数声明提升可以用于调整代码的顺序,将大段的定义过程放到代码最后,但是不影响代码执行效果。

IIFE自调用函数


  • IIFE:immediately-invoked function expression,叫做即时调用的函数表达式,也叫做自

调用函数,表示函数在定义时就立即调用。

  • 函数调用方式:函数名或函数表达式的变量名后面加 () 运算符。

  • 函数名定义的形式不能实现立即执行自调用,函数使用函数表达式形式可以实现立即执行,原因是因为函数表达式定义过程中,将一个函数矮化成了一个表达式,后面加()运算符就可以立即执行。

// 函数名+() 不能实现立即执行自调用

function fun (){

console.log(1);

}();

// 函数表达式形式可以实现立即执行

var foo = function (){

console.log(“halou”);

}();  // 没有调用语句,直接输出:halou

  • 启发:如果想实现 IIFE,可以想办法将函数矮化成表达式。

函数矮化成表达式

函数矮化成表达式,就可以实现自调用。

  • 函数矮化成表达式的方法,可以让函数参与一些运算,也就是说给函数前面加一些运算符。(四个)

+ function fun (){

console.log(1); // 1

}();

- function fun (){

console.log(1); // 1

}();

(function fun (){

console.log(1); // 1

})();

! function fun (){

console.log(1); // 1

}();

    • 数学运算符:+ - ()
  • 逻辑运算符:!非运算

  • IIFE 结构可以关住函数的作用域,在结构外面是不能调用函数的。

  • IIFE 最常用的是 () 运算符,而且函数可以不写函数名,使用匿名函数。

(function fun (a){  // 形参会接收到实参传递的值

console.log(a);  // Hello

})(“Hello!”);  //因为外部无法调用该函数,也无法传实参,因此实参写在这个小括号里面

相关文章


  1. Javascript 里的奇葩知识

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

最后:

总结来说,面试成功=基础知识+项目经验+表达技巧+运气。我们无法控制运气,但是我们可以在别的地方花更多时间,每个环节都提前做好准备。

面试一方面是为了找到工作,升职加薪,另一方面也是对于自我能力的考察。能够面试成功不仅仅是来自面试前的临时抱佛脚,更重要的是在平时学习和工作中不断积累和坚持,把每个知识点、每一次项目开发、每次遇到的难点知识,做好积累,实践和总结。

点击这里领取Web前端开发经典面试题

初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-6M3suqvN-1711676502283)]

[外链图片转存中…(img-BMaPczTe-1711676502283)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-tFamsia7-1711676502283)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

最后:

总结来说,面试成功=基础知识+项目经验+表达技巧+运气。我们无法控制运气,但是我们可以在别的地方花更多时间,每个环节都提前做好准备。

面试一方面是为了找到工作,升职加薪,另一方面也是对于自我能力的考察。能够面试成功不仅仅是来自面试前的临时抱佛脚,更重要的是在平时学习和工作中不断积累和坚持,把每个知识点、每一次项目开发、每次遇到的难点知识,做好积累,实践和总结。

点击这里领取Web前端开发经典面试题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值