前言
俗话说:好记性不如烂笔头。再好的记性也总有忘记的时候,而笔记的好处之一便在于信息记录的长久性,你可以通过不断的复习、熟悉来加强理解,深化记忆,从而达到持久记忆的效果。
本篇文章主要记录了 JavaScript 的部分基础内容,包括函数、作用域、以及预解析的概念、相关代码、应用以及注意事项等,目的主要是为了帮助自己记录学习,同时也把文章分享出来,供大家参考学习。
本篇文章基于该视频:
JavaScript基础语法-dom-bom-js-es6新语法-jQuery-数据可视化echarts黑马pink老师前端入门基础视频教程(500多集)持续_哔哩哔哩_bilibili
1、函数
1.1 函数的使用
1.1.1 声明函数
//声明函数
function 函数名(){
//函数体代码
}
- function 是声明函数的关键字,必须小写
- 由于函数一般是为了实现某个功能才定义的, 所以通常我们将函数名命名为动词,比如 getSum
1.1.1 调用函数
//调用函数
函数名(); //通过调用函数名来执行函数体代码
- 调用的时候千万不要忘记添加小括号
- 口诀:函数不调用,自己不执行
注意:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码
// function sayHi() {
// console.log('Hi');
// }
// sayHi();
// 示例:利用函数计算1-100之间的累加和
function getSum() {
var sum = 0;
for (var i = 0; i <= 100; i++) {
sum += i;
}
console.log(sum);
}
getSum();
1.2 函数的封装
函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口
1.3 函数的参数
1.3.1 形参和实参
在声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参,而在调用该函数时,同样也需要传递相应的参数,这些参数被称为实参。
参数 | 说明 |
---|---|
形参 | 形式上的参数 函数定义的时候 传递的参数 当前并不知道是什么 |
实参 | 实际上的参数 函数调用的时候 传递的参数 实参是传递给形参的 |
参数的作用 : 在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去
1.3.2 形参和实参个数不匹配
参数个数 | 说明 |
---|---|
实参个数等于形参个数 | 输出正确结果 |
实参个数多于形参个数 | 只取到形参的个数 |
实参个数小于形参个数 | 多的形参定义为undefined,结果为NaN |
1.4 函数返回值 return
1.4.1 return 语句
// 声明函数
function 函数名(){
...
return 需要返回的值;
}
// 调用函数
函数名(); // 此时调用函数就可以得到函数体内return 后面的值
- 在使用 return 语句时,函数会停止执行,并返回指定的值
- 如果函数没有 return ,返回的值是 undefined
1.4.2 return 终止函数
return 语句之后的代码不被执行
function add(num1, num2){
//函数体
return num1 + num2; // 注意:return 后的代码不执行
alert('我不会被执行,因为前面有 return');
}
var resNum = add(21,6); // 调用函数,传入两个实参,并通过 resNum 接收函数返回值
alert(resNum); // 27
1.4.3 区别与小结
break、continue、return 的区别
- break:结束当前循环体(如 for、while)
- continue:跳出本次循环,继续执行下次循环(如for、while)
- return:不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码
return 小结
- 函数都是有返回值的
- 如果有 return,则返回 return 后面的值
- 如果没有 return,则返回 undefined
1.5 arguments 的使用
当我们不确定有多少个参数传递的时候,可以用 arguments 来获取。在 JavaScript中,arguments 实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。
arguments 展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点
- 具有 length 属性
- 按索引方式储存数据
- 不具有数组的 push , pop 等方法
// function fn() {
// console.log(arguments);
// }
// fn(1, 2, 3);
// 示例:利用函数求两个数的最大值
function fn() {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
var maxNumber = fn(2, 4, 5, 9);
console.log(maxNumber);
1.6 函数的两种声明方式
1.6.1 自定义函数方式(命名函数)
// 声明定义方式
function fn() {...}
// 调用
fn();
- 利用函数关键字 function 自定义函数方式
- 因为有名字,所以也被称为命名函数
- 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面
1.6.2 函数表达式方式(匿名函数)
/*这是函数表达式写法,匿名函数后面跟分号结束
var fn = function(){...};
fn(); 调用的方式,函数调用必须写到函数体下面 */
示例:
var fn = function(aru) {
console.log('我是函数表达式');
console.log(aru);
}
fn('你好!');
- fn 是变量名,不是函数名
- 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数
- 函数表达式也可以进行传递参数
2、作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
JavaScript (ES6前) 中的作用域有两种:
- 全局作用域
- 局部作用域(函数作用域)
2.1 JavaScript 作用域
2.1.1 全局作用域
作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件
2.1.2 局部(函数)作用域
作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域
2.1.3 块级作用域
JS 中有块级作用域(在ES5之后)
if(3 < 5) {
var num = 10;
}
console.log(num);
2.2 变量作用域
2.2.1 全局变量
在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)
- 全局变量在代码的任何位置都可以使用
- 在全局作用域下 var 声明的变量是全局变量
- 特殊情况下,在函数内不使用 var 声明的变量也是全局变量(不建议使用)
2.2.2 局部变量
在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)
- 局部变量只能在该函数内部使用
- 在函数内部 var 声明的变量是局部变量
- 函数的形参实际上是局部变量
2.2.3 区别
- 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
- 局部变量:只有函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间
2.3 作用域链
var num = 10;
function fn1() { // 外部函数
var num = 20;
function fn2() { // 内部函数
console.log(num);
}
}
- 只要是代码,就至少有一个作用域
- 写在函数内部的叫局部作用域
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
3、预解析
JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。
- 预解析:js 引擎会把 js 里面所有的 var 还有 function 提升到当前作用域的最前面
- 代码执行:从上到下执行JS语句
3.1 变量预解析(变量提升)
变量预解析也叫做变量提升、函数提升
变量提升:变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升
console.log(num); // 结果是多少?
var num = 10; // undefined
//相当于执行了以下代码
var num; // 变量声明提升到当前作用域最上面
console.log(num);
num = 10; // 变量的赋值不会提升
3.2 函数预解析(函数提升)
函数提升: 函数的声明会被提升到当前作用域的最上面,但是不会调用函数
fn();
var fn = function() {
console.log('22'); // 报错
}
//相当于执行了以下代码
var fn;
fn(); //fn没赋值,没这个,报错
var fn = function() {
console.log('22'); //报错
}
3.3 预解析案例
// 案例1
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}
// 相当于执行了以下操作
var num;
function fun() {
var num;
console.log(num);
num = 20;
}
num = 10;
fun();
var num = 10;
function fn() {
console.log(num);
var num = 20;
console.log(num);
}
fn();
// 相当于以下代码
var num;
function fn() {
var num;
console.log(num);
num = 20;
console.log(num);
}
num = 10;
fn();
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a);
console.log(b);
var a = '123';
}
// 相当于以下代码
var a;
function f1() {
var b;
var a;
b = 9;
console.log(a);
console.log(b);
a = '123';
}
a = 18;
f1();