数组、函数、作用域、预解析"/>
数组、函数、作用域、预解析
文章目录
- 一、JavaScript 数组
- 1、创建数组
- (1)new 创建数组
- (2)数组字面量创建数组
- 2、获取数组中的元素
- 3、遍历数组
- 4、数组中新增元素
- (1)通过修改 length 长度新增数组元素
- (2)通过修改数组索引新增数组元素
- 5、案例
- (1)删除指定数组元素
- (2)翻转数组
- (3)冒泡排序
- 二、JavaScript 函数
- 1、函数的使用
- (1)声明函数
- (2)调用函数
- (3)函数的封装
- 2、函数的参数
- (1)形参和实参
- (2)函数形参和实参个数不匹配问题
- 3、函数的返回值
- (1)return语句
- (2)return终止函数
- (3)return的返回值
- (4)函数没有return返回undefined
- (5)break ,continue ,return 的区别
- 4、arguments的使用
- 5、案例
- (1)判断闰年
- (2)函数相互调用
- 6、函数的两种声明方式
- (1)自定义函数方式
- (2)函数表达式方式(匿名函数)
- 三、综合案例:简易计算器
- 四、JavaScript 作用域
- 1、全局作用域、全局变量
- 2、局部作用域、局部变量
- 3、JS 没有块级作用域(在ES6之前)
- 4、全局变量和局部变量的区别
- 5、作用域链
- 五、JavaScript 预解析
- 1、变量预解析(变量提升)
- 2、函数预解析(函数提升)
- 3、解决函数表达式(匿名函数)声明调用问题
- 4 、案例
一、JavaScript 数组
- 数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。
// 普通变量一次只能存储一个值
let num = 10;
// 数组一次可以存储多个值
let arr = ['小白',2,true,4.5];
let arr = [1,2,3,4,5];
1、创建数组
(1)new 创建数组
let arr = new Array(); // 创建了一个空的数组
console.log(arr);
(2)数组字面量创建数组
- 数组的字面量是方括号 [ ]
- 声明数组并赋值称为数组的初始化
let arr0 = []; // 创建了一个空的数组
let arr1 = [1, 2, 'pink老师', true]; //创建带初始值的数组
console.log(arr0);
console.log(arr1);
2、获取数组中的元素
- 数组可以通过索引来访问、设置、修改对应的数组元素,我们可以通过“
数组名[索引]
”的形式来获取数组中的元素。
let arr = ['迪丽热巴', '古丽扎娜', '佟丽丫丫'];console.log(arr[0]); //迪丽热巴console.log(arr[1]); //古丽扎娜console.log(arr[2]); //佟丽丫丫console.log(arr[3]); // 因为没有这个数组元素 所以输出的结果是 undefined
3、遍历数组
- 遍历: 就是把数组中的每个元素从头到尾都访问一次。
- 我们可以通过 for 循环索引遍历数组中的每一项
let arr = ['red', 'green', 'blue'];for (let i = 0; i < arr.length; i++) {console.log(arr[i]);}
- 使用“
数组名.length
”可以访问数组元素的数量(数组长度)。 - 此处数组的长度是数组元素的个数 ,不要和数组的索引号混淆。
- 当我们数组里面的元素个数发生了变化,这个
length
属性跟着一起变化。
案例:
求数组[2,6,1,77,52,25,7]
中的最大值
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 求数组[2,6,1,77,52,25,7]中的最大值// 声明一个保存最大元素的变量 max。// 默认最大值可以取数组中的第一个元素。// 遍历这个数组,把里面每个数组元素和 max 相比较。// 如果这个数组元素大于max 就把这个数组元素存到 max 里面,否则继续下一轮比较。// 最后输出这个 maxlet arr = [2, 6, 1, 77, 52, 25, 7, 99];let max = arr[0];for (let i = 1; i < arr.length; i++) {if (arr[i] > max) {max = arr[i];}}console.log('该数组里面的最大值是:' + max);</script>
</head><body></body></html>
数组转换为分割字符串
要求:将数组 ['red', 'green', 'blue', 'pink']
转换为字符串,并且用 |
或其他符号
分割
输出: ‘red|green|blue|pink
’
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 将数组 ['red', 'green', 'blue', 'pink'] 转换为字符串,并且用 | 或其他符号分割// 1.需要一个新变量用于存放转换完的字符串 str。// 2.遍历原来的数组,分别把里面数据取出来,加到字符串里面。// 3.同时在后面多加一个分隔符let arr = ['red', 'green', 'blue', 'pink'];let str = '';let sep = '|';for (let i = 0; i < arr.length; i++) {str += arr[i] + sep;}console.log(str);</script>
</head><body></body></html>
4、数组中新增元素
(1)通过修改 length 长度新增数组元素
- 可以通过修改
length
长度来实现数组扩容的目的 - length 属性是可读写的
let arr = ['red', 'green', 'blue'];
console.log(arr.length); // 3
arr.length = 5; // 把我们数组的长度修改为了 5 里面应该有5个元素
console.log(arr);
console.log(arr[3]); // undefined
console.log(arr[4]); // undefined
- 其中索引号是 3,4 的空间没有给值,就是声明变量未给值,默认值就是
undefined
。
(2)通过修改数组索引新增数组元素
- 可以通过修改数组索引的方式追加数组元素
- 不能直接给数组名赋值,否则会覆盖掉以前的数据
let arr1 = ['red', 'green', 'blue'];
arr1[3] = 'pink';
console.log(arr1);
arr1[4] = 'hotpink';
console.log(arr1);
arr1[0] = 'yellow'; // 这里是替换原来的数组元素
console.log(arr1);
arr1 = '有点意思';
console.log(arr1); // 不要直接给 数组名赋值 否则里面的数组元素都没有了
案例:将数组 [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]
中大于等于 10 的元素选出来,放入新数组
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 将数组 [2, 0, 6, 1, 77, 0, 52, 0, 25, 7] 中大于等于 10 的元素选出来,放入新数组。// 1、声明一个新的数组用于存放新数据newArr。// 2、遍历原来的旧数组, 找出大于等于 10 的元素。// 3、依次追加给新数组 newArr。 let arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];let newArr = [];// 刚开始 newArr.length 就是 0for (let i = 0; i < arr.length; i++) {if (arr[i] >= 10) {// 新数组索引号应该从0开始 依次递增newArr[newArr.length] = arr[i];}}console.log(newArr); //(3)[77,52,25]</script>
</head><body></body></html>
5、案例
(1)删除指定数组元素
要求:将数组[2, 0, 6, 1, 77, 0, 52, 0, 25, 7]
中的 0 去掉后,形成一个不包含 0 的新数组。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 将数组[2, 0, 6, 1, 77, 0, 52, 0, 25, 7]中的 0 去掉后,形成一个不包含 0 的新数组。// 1、需要一个新数组用于存放筛选之后的数据。// 2、遍历原来的数组, 把不是 0 的数据添加到新数组里面(此时要注意采用数组名 + 索引的格式接收数据)。// 3、新数组里面的个数, 用 length 不断累加。let arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];let newArr = [];for (let i = 0; i < arr.length; i++) {if (arr[i] != 0) {newArr[newArr.length] = arr[i];}}console.log(newArr); // (7) [2,6,1,77,52,25,7]</script>
</head><body></body></html>
(2)翻转数组
要求: 将数组 ['red', 'green', 'blue', 'pink', 'purple']
的内容反过来存放。
输出: ['purple', 'pink', 'blue', 'green', 'red']
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 将数组 ['red', 'green', 'blue', 'pink', 'purple'] 的内容反过来存放// 1、声明一个新数组 newArr// 2、把旧数组索引号第4个取过来(arr.length - 1),给新数组索引号第0个元素 (newArr.length)// 3、我们采取 递减的方式 i--var arr = ['red', 'green', 'blue', 'pink', 'purple'];var newArr = [];for (var i = arr.length - 1; i >= 0; i--) {newArr[newArr.length] = arr[i]}console.log(newArr); // (5) ['purple', 'pink', 'blue', 'green', 'red']</script>
</head><body></body></html>
(3)冒泡排序
冒泡排序:是一种算法,把一系列的数据按照一定的顺序进行排列显示(从小到大或从大到小)。
例如,我们可以将数组 [5, 4, 3, 2, 1]
中的元素按照从小到大的顺序排序,输出: 1,2,3,4,5
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 冒泡排序// let arr = [5, 4, 3, 2, 1];let arr = [4, 1, 2, 3, 5];for (let i = 0; i <= arr.length - 1; i++) { // 外层循环管趟数 for (let j = 0; j <= arr.length - i - 1; j++) { // 里面的循环管 每一趟的交换次数// 内部交换2个变量的值 前一个和后面一个数组元素相比较if (arr[j] < arr[j + 1]) {let temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}console.log(arr); // (5) [5, 4, 3, 2, 1]</script>
</head><body></body></html>
二、JavaScript 函数
函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。
1、函数的使用
函数在使用时分为两步:声明函数和调用函数
(1)声明函数
function
是声明函数的关键字,必须小写
- 由于函数一般是为了实现某个功能才定义的, 所以通常我们将
函数名
命名为动词
,比如 getSum
// 声明函数
function 函数名() {//函数体代码
}
(2)调用函数
- 调用的时候千万不要忘记添加小括号
- 口诀:函数不调用,自己不执行。
// 调用函数
函数名(); // 通过调用函数名来执行函数体代码
(3)函数的封装
函数的封装是把一个或者多个功能通过函数的方式封装起来
,对外只提供一个简单的函数接口
案例:利用函数计算1-100之间的累加和
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 利用函数计算1-100之间的累加和 // 1. 声明函数function getSum() {let sum = 0;for (let i = 1; i <= 100; i++) {sum += i;}console.log(sum);}// 2. 调用函数getSum(); //5050getSum(); //5050</script>
</head><body></body></html>
2、函数的参数
(1)形参和实参
在声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参,而在调用该函数时,同样也需要传递相应的参数,这些参数被称为实参。
参数 | 说明 |
---|---|
形参 | 形式上的参数 函数定义的时候传递的参数 当前并不知道是什么 |
实参 | 实际上的参数 函数调用的时候传递的参数 实参是传递给形参的 |
参数的作用 : 在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去。
// 带参数的函数声明
function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的参数,用逗号分隔// 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3...);
案例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 1. 利用函数求任意两个数的和function getSum(num1, num2) {console.log(num1 + num2);}getSum(1, 3); // 4getSum(3, 8); // 11// 2. 利用函数求任意两个数之间的和function getSums(start, end) {let sum = 0;for (let i = start; i <= end; i++) {sum += i;}console.log(sum);}getSums(1, 100); // 5050getSums(1, 10); //55// 3. 注意点// (1) 多个参数之间用逗号隔开// (2) 形参可以看做是不用声明的变量</script>
</head><body></body></html>
(2)函数形参和实参个数不匹配问题
参数个数 | 说明 |
---|---|
实参个数等于形参个数 | 输出正确结果 |
实参个数多于形参个数 | 只取到形参的个数 |
实参个数小于形参个数 | 多的形参定义为undefined |
function sum(num1, num2) {console.log(num1 + num2);
}
sum(100, 200); // 形参和实参个数相等,输出正确结果
sum(100, 400, 500, 700); // 实参个数多于形参,只取到形参的个数
sum(200); // 实参个数少于形参,多的形参定义为undefined,结果为NaN
3、函数的返回值
(1)return语句
- 在使用 return 语句时,函数会停止执行,并
返回指定的值
- 如果函数没有 return ,返回的值是
undefined
// 声明函数
function 函数名(){...return 需要返回的值;
}
// 调用函数
函数名(); // 此时调用函数就可以得到函数体内return 后面的值
案例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 利用函数 求两个数的最大值function getMax(num1, num2) {// if (num1 > num2) {// return num1;// } else {// return num2;// }return num1 > num2 ? num1 : num2;}console.log(getMax(1, 3)); // 3console.log(getMax(11, 3)); // 11</script>
</head><body></body></html>
(2)return终止函数
return 后的代码不执行
function add(num1,num2) {//函数体return num1 + num2; // 注意:return 后的代码不执行alert('我不会被执行,因为前面有 return');
}
let resNum = add(21, 6); // 调用函数,传入两个实参,并通过 resNum 接收函数返回值
alert(resNum); // 27
(3)return的返回值
return 只能返回一个值。如果用逗号隔开多个值,以最后一个为准。
function fn(num1, num2) {return num1, num2; // 返回的结果是最后一个值
}
console.log(fn(1, 2)); //2
如果想返回多个值,可利用数组实现,案例如下:
//求任意两个数的 加减乘数结果
function getResult(num1, num2) {return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
}
let re = getResult(1, 2); // 返回的是一个数组
console.log(re); // (4) [3,-1,2,0.5]
(4)函数没有return返回undefined
- 函数都是有返回值的
- 如果有return 则返回
return 后面的值
- 如果没有return 则返回
undefined
(5)break ,continue ,return 的区别
break
:结束当前的循环体(如 for、while)continue
:跳出本次循环,继续执行下次循环(如 for、while)return
:不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码
4、arguments的使用
- 当我们不确定有多少个参数传递的时候,可以用
arguments
来获取。 - 在 JavaScript 中,
arguments
实际上它是当前函数的一个内置对象。 - 所有函数都内置了一个
arguments
对象,arguments
对象中存储了传递的所有实参。
arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:
- 具有 length 属性
- 按索引方式储存数据
- 不具有数组的 push , pop 等方法
案例:利用函数求任意个数的最大值
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 利用函数求任意个数的最大值function getMax() { // arguments = [1,2,3]let max = arguments[0];for (let i = 1; i < arguments.length; i++) {if (arguments[i] > max) {max = arguments[i];}}return max;}console.log(getMax(1, 2, 3)); // 3console.log(getMax(1, 2, 3, 4, 5)); // 5console.log(getMax(11, 2, 34, 444, 5, 100)); // 444</script>
</head><body></body></html>
5、案例
(1)判断闰年
要求:输入一个年份,判断是否是闰年(闰年:能被4整除并且不能被100整数,或者能被400整除)
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 利用函数判断闰年function isRunYear(year) {// 如果是闰年我们返回 true 否则 返回 false let flag = false;if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {flag = true;}return flag;}console.log(isRunYear(2000)); // trueconsole.log(isRunYear(1999)); // false</script>
</head><body></body></html>
(2)函数相互调用
用户输入年份,输出当前年份2月份的天数;
如果是闰年,则2月份是 29天, 如果是平年,则2月份是 28天。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 用户输入年份,输出当前年份2月份的天数function backDay() {let year = prompt('请您输入年份:');if (isRunYear(year)) { // 调用函数需要加小括号alert('当前年份是闰年2月份有29天');} else {alert('当前年份是平年2月份有28天');}}backDay();// 判断是否为闰年的函数function isRunYear(year) {// 如果是闰年我们返回 true 否则 返回 false let flag = false;if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {flag = true;}return flag;}</script>
</head><body></body></html>
6、函数的两种声明方式
(1)自定义函数方式
利用函数关键字 function
自定义函数方式。
// 声明定义方式
function fn() {...}
// 调用
fn();
- 因为有名字,所以也被称为
命名函数
- 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面
(2)函数表达式方式(匿名函数)
// 这是函数表达式写法,匿名函数后面跟分号结束
let fn = function(){...};
// 调用的方式,函数调用必须写到函数体下面
fn();
- 因为函数没有名字,所以也被称为
匿名函数
- 这个
fn
里面存储的是一个函数 fn
是变量名, 不是函数名- 函数表达式方式原理跟声明变量方式是一致的
- 函数调用的代码必须写到函数体后面
三、综合案例:简易计算器
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>let money = 100;let action;let select = function () {do {action = prompt("欢迎使用简易计算器:\n1、加法运算\n2、减法运算\n3、乘法运算\n4、除法运算\n5.退出\n请输入您的选项:");let number;let result = 0;switch (action) {case '1':number = getValue();result = parseFloat(number[0]) + parseFloat(number[1]);alert("结果为" + result);break;case '2':number = getValue();result = number[0] - number[1];alert("结果为" + result);break;case '3':number = getValue();result = number[0] * number[1];alert("结果为" + result);break;case '4':number = getValue();result = number[0] / number[1];alert("结果为" + result);break;case '5':alert("您正在退出!")break;default:alert("请输入正确选项!");}} while (action !== '5');}function getValue() {let value = [];for (i = 0; i < 2; i++) {value[i] = prompt("请输入一个数值")}return value;}select();</script>
</head><body></body></html>
四、JavaScript 作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围
就是这个名字的作用域
。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
JavaScript(es6前)
中的作用域有两种:
- 全局作用域
- 局部作用域(函数作用域):
1、全局作用域、全局变量
- 全局作用域作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。
- 在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)
注意: 如果在函数内部,没有声明直接赋值
的变量也属于全局变量(不建议使用)
let num = 10; // num就是一个全局变量
console.log(num); // 10function fn() {console.log(num); // 10num2 = 20; // 如果在函数内部 没有声明直接赋值的变量也属于全局变量
}fn();console.log(num); // 10
console.log(num2); // 20
2、局部作用域、局部变量
- 作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域。
- 在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)
注意: 函数的形参
也可以看做是局部变量
function fun(aru) {let num1 = 10; // num1就是局部变量 只能在函数内部使用console.log(num1); //10console.log(aru); //20
}
fun(10);
// console.log(num1); // 报错
console.log(aru); // 报错 函数的形参也可以看做是局部变量
3、JS 没有块级作用域(在ES6之前)
块作用域由 { } 包括
。
Js中没有块级作用域(在ES6之前)。
if (true) {var num4 = 123;console.log(num4); //123
}
console.log(num4); //123
使用let定义变量
是具有块级作用域
if (true) {let num4 = 123;console.log(num4); //123
}
console.log(num4); //报错for(i=0;i<2;i++){let temp=80;console.log(temp); //80
}
console.log(temp); //报错
4、全局变量和局部变量的区别
- 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
- 局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间
5、作用域链
- 只要是代码,就至少有一个作用域
- 写在函数内部的局部作用域
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
// 作用域链 : 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值 这种结构我们称为作用域链
// 就近原则
let text = 10;function fn() { // 外部函数let text = 20;function fun() { // 内部函数console.log(text); //20}fun();
}
fn();
案例:结果是几?
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 案例1 : 结果是几?function f1() {var num = 123;function f2() {var num = 0;console.log(num); // num = 0 站在目标出发,一层一层的往外查找}f2();}var num = 456;f1();// 案例2 :结果是几?var a = 1;function fn1() {var a = 2;var b = '22';fn2();function fn2() {var a = 3;fn3();function fn3() {var a = 4;console.log(a); //a的值 4console.log(b); //b的值 '22'}}}fn1();</script>
</head><body></body></html>
五、JavaScript 预解析
- JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。
- JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。
- 预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有
var
和function
声明的变量在内存中进行提前声明或者定义。 - 代码执行: 从上到下执行JS语句。
- 预解析也叫做变量、函数提升。
let
声明的变量不具备变量提升
1、变量预解析(变量提升)
- 变量提升: 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升
let
声明的变量不具备变量提升
//变量提升使num声明放在了最前面console.log(num); // undefined 坑 var num = 10;
相当于以下代码:
var num;
console.log(num);
num = 10;
2、函数预解析(函数提升)
- 函数提升: 函数的声明会被提升到当前作用域的最上面,但是不会调用函数
//函数提升使fn声明放在了最前面fn(); // 11 放在函数前后皆可function fn() {console.log(11);}
3、解决函数表达式(匿名函数)声明调用问题
- 匿名函数会进行变量提升,
变量的赋值(函数)不会提升
,因此报错 - 解决方法:函数调用的代码必须写到函数体后面
//变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升fun(); // 报错 var fun = function () {console.log("想不到吧");}
相当于以下代码:
var fun;fun();fun = function() {console.log("想不到吧");}
4 、案例
注意:
var a2 = b2 = c2 = 9;
其中,b2
和c2
直接赋值, 没有var 声明,- 相当于
var a2 = 9; b2 = 9; c2 = 9;
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 案例 1alert(a); //函数avar a = 1;alert(a); // 1function a() {return false;}// 案例 2var num = 10;fun();function fun() {console.log(num); //undefinedvar num = 20;}// 案例3var num1 = 10;function fn() {console.log(num1); //undefinedvar num1 = 20;console.log(num1); //20}fn();// 案例4var a1 = 18;f1();function f1() {var b1 = 9;console.log(a1); //undefinedconsole.log(b1); //9var a1 = '123';}console.log('-----------------------------------');// 案例5f2();console.log(c2); //9console.log(b2); //9console.log(a2); //报错function f2() {var a2 = b2 = c2 = 9; //b2 和 c2 直接赋值 没有var 声明 当 全局变量看console.log(a2); //9console.log(b2); //9console.log(c2); //9}// 相当于以下代码// function f2() {// var a2;// a2 = b2 = c2 = 9;// //相当于 var a2 = 9; b2 = 9; c2 = 9; // //b2 和 c2 直接赋值 没有var 声明 当 全局变量看// //集体声明 var a2 = 9, b2 = 9, c2 = 9;// console.log(a2); //9// console.log(b2); //9// console.log(c2); //9// }// f2();// console.log(c2); //9// console.log(b2); //9// console.log(a2); //报错</script>
</head><body></body></html>
更多推荐
数组、函数、作用域、预解析
发布评论