【前端基础-JavaScript】JS作用域

1.函数

<script>
    // 利用函数计算1-100之间的累加和
    // 1.声明函数
    function getSum() {
        var sum = 0;
        for (var i = 1; i <= 100; i++) {
            sum += i;
        }
        console.log(sum);
    }
    // 2.调用函数
    getSum();
    getSum();
</script>

break、continue、return 的区别

  • break : 结束当前循环体(如 for、while)
  • continue :跳出本次循环,继续执行下次循环(如for、while)
  • return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码
实参与形参个数不匹配
参数个数说明
实参个数等于形参个数输出正确结果
实参个数多于形参个数只取到形参个数
实参个数小于形参个数多的形参定义为undefined,结果为NaN

1.1 arguments的使用

当我们不确定有多少个参数传递的时候,可以用 arguments 来获取。在 JavaScript 中,arguments 实际上它是当前函数的一个内置对象。

所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。

  • arguments存放的是传递过来的实参
  • arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:

①:具有 length 属性

②:按索引方式储存数据

③:不具有数组的 push , pop 等方法

//arguments的使用
function fn(){
    console.log(arguments);  //里面存储了所有传递过来的实参
    console.log(arguments.length); // 3
    console.log(arguments[2]); // 3
}
fn(1,2,3);
fn(1,2,3,4,5);

利用函数求任意个数的最大值

<script>
    //arguments的使用
    function getMax(){
        var max = arguments[0];
        for(var i = 1;i < arguments.length;i++){
            if(arguments[i] > max){
                max = arguments[i];
            }
        }
        return max;
    }
    console.log(getMax(1,2,3));
    console.log(getMax(1,2,3,4,5));
    console.log(getMax(11,2,34,5,100));
</script>

1.2 函数封装案例

案例1 翻转任意一个数组
<script>
    //利用函数翻转任意数组reverse翻转
    function reverse(arr){
        var newArr = [];
        for(var i = arr.length-1;i >= 0; i--){
            newArr[newArr.length] = arr[i];
        }
        return newArr;
    }
    var arr1 = reverse([1,2,3,4,5]);
    console.log(arr1);
    var arr2 = reverse(['red','yellow','green']);
    console.log(arr2);
</script>

在这里插入图片描述

案例2 冒泡排序
function sort(arr) {
    for (var i = 0; i < arr.length - 1; i++) {
        for (var j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j+1]) { 
	            var temp = arr[j];
	            arr[j] = arr[j + 1]; 
	            arr[j + 1] = temp;
            }
        }
    }
    return arr;
}
案例3 输出任意年2月份天数

用户输入年份,输出当前年份2月份的天数,如果是闰年,则2月份是29天;如果是平年,则2月份是28天

function backDay(){
    var year = prompt('请输入要查询的年份:');
    if(isRun(year)){
        alert('你输入的'+year+'是闰年,'+year+'年的二月有29天');
    }else{
        alert('你输入的'+year+'是平年,'+year+'年的二月有28天');
    }
}
backDay();
function isRun(year){
    var flag = false;
    if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0){
        flag = true;
    }
    return flag;
}

1.3 函数的两种声明方式

1.3.1 自定义函数方式(命名函数)

利用函数关键字 function 自定义函数方式。

// 声明定义方式
function fn() {...}

// 调用  
fn();  
  1. 因为有名字,所以也被称为命名函数
  2. 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面
1.3.2 函数表达式方式(匿名函数)

利用函数表达式方式的写法如下:

// 这是u函数表达式写法,匿名函数后面跟分号结束
var fun = function(){};

// 调用的方式,函数调用必须写到函数体下面
fun();
  • 因为函数没有名字,所以也称为匿名函数

  • 这个fun 里面存储的是一个函数,fun为变量名,不是函数名

  • 函数调用的代码必须写到函数体后面

  • 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数

  • 函数表达式也可以进行传递参数

    <script>
        var fun = function(aru){
            console.log('我是函数表达式');
            console.log(aru);
        }
        fun('pink老师');
    </script>
    

2. 作用域

通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了命名冲突。

JavaScript (ES6前) 中的作用域有两种:

  • 全局作用域:作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件
  • 局部作用域(函数作用域):作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域

全局变量和局部变量

  • 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
  • 局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间

2.1 作用域链

  1. 只要是代码,就至少有一个作用域
  2. 写在函数内部的叫局部作用域
  3. 就近原则
  4. 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
  5. 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
var num = 10;
function fn() { //外部函数
    var num = 20;
    function fun() { //内部函数
        console.log(num);  // 20 ,一级一级访问
    }
    fun();
}
fn();//20
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);
            console.log(b);
        }
    }
}
fn1();

在这里插入图片描述

2.2 预解析

JavaScript 代码是由浏览器中的 JavaScript 解析器来执行。JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。

  • 预解析:js引擎会把js里面所有的varfunction提升到当前作用域的最前面
  • 代码执行:从上到下执行JS语句

预解析只会发生在通过 var 定义的变量和 function 上。学习预解析能够让我们知道为什么在变量声明之前访问变量的值是 undefined,为什么在函数声明之前就可以调用函数。

2.2.1 变量预解析(变量提升)

变量预解析也叫做变量提升、函数提升

变量提升: 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升

console.log(num); // undefined
var num = 10;

相当于执行了以下代码

var num;
console.log(num);
num = 10;
2.2.2 函数预解析(函数提升)

函数提升: 函数的声明会被提升到当前作用域的最上面,但是不会调用函数。

fn();				//11
function fn() {
    console.log('11');
}
2.2.3 练习
// 练习1
var num = 10;
fun();
function fun() {
    console.log(num);	//undefined
    var num = 20;
}
// 最终结果是 undefined

上述代码相当于执行了以下操作

var num;
function fun() {
    var num;
    console.log(num);
    num = 20;
}
num = 10;
fun();
// 练习2
var num = 10;
function fn(){
    console.log(num);		//undefined
    var num = 20;
    console.log(num);		//20
}
fn();

上述代码相当于执行了以下操作

var num;
function fn(){
    var num;
    console.log(num);
    num = 20;
    console.log(num);
}
num = 10;
fn();
// 练习3
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);	//undefined
    console.log(b);	//9
    a = '123';
}
a = 18;
f1();
// 练习4
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
    var a = b = c = 9;
    // 相当于 var a = 9; b = 9;c = 9;  b和c的前面没有var声明,当全局变量看
    // 集体声明 var a = 9,b = 9,c = 9;
    console.log(a);
    console.log(b);
    console.log(c);
}

上述代码相当于执行了以下操作

function f1() {
    var a;
    a = b = c = 9;
    console.log(a);	//9
    console.log(b);	//9
    console.log(c);	//9
}
f1();
console.log(c);	//9
console.log(b);	//9
console.log(a);	//报错 a是局部变量
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值