JavaScript函数进阶、严格模式、闭包、递归

本文详细探讨了JavaScript中的函数定义和调用,重点解析了this指向及其改变方法,包括call()、apply()和bind()。接着介绍了严格模式的开启及其影响,阐述了高阶函数的概念,并详细讲解了闭包的定义、作用及示例。最后,通过递归的概念和实际应用,展示了如何利用递归实现阶乘计算和数据遍历。
摘要由CSDN通过智能技术生成

1. 函数的定义和调用

	<script>
		//定义函数三种方法
		//1 函数声明方式 function 关键字
		function fn(){}
		//2 函数表达式(匿名函数)
		var fn1 = function(){}
		//3 new关键字
		new Function('参数1','参数2','函数体');
		//参数必须为字符串形式
		var fn2 = new Function('a','b','console.log(a+b)');
		//第三种方式执行效率低,也不方便书写,因此较少使用
		//所有函数都是 Function 的实例(对象)  
		//函数也属于对象
	</script>

2. this指向、改变this指向

函数内部的this指向

在这里插入图片描述

改变函数内部的this指向

call()方法

call()方法一般用于继承

<script>
        var o = {
            name:'hjc'
        }
        function Person(name){
            console.log(this);
            this.name = name;
        }
        Person('lwq');  //指向window
        Person.call(o,'lwq');   //指向o对象
    </script>

apply()方法

apply()方法一般用于跟数组有关系. 比如借助于数学对象实现数组最大值最小值

<script>
		//1.理解代码
        var o = {
            name:'hjc'
        }
        function fn(a,b){
            console.log(this);
            console.log(a+b);
        }
        //参数必须以数组的方式
        fn.apply(o,[1,2]);
        
        //2.实际demo
        var arr = [1,2,3,4,5,7];
        var max = Math.max.apply(Math,arr); //返回数组中最大值
        var min = Math.min.apply(Math,arr); //返回数组中最小值
        console.log(max,min);
    </script>

bind()方法

不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.

 <script>
        var hjc = {
            name:'hjc'
        }
        function sum(a,b,c){
            console.log(this);
            console.log(a+b+c);
        }
        // bind只会绑定,不会执行,需要调用执行
        var obj = sum.bind(hjc,1,2,3);
        obj();
    </script>

bind方法的实际小demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <script>
        var btns = document.querySelectorAll('button');
        for(var i=0;i<btns.length;i++){
            btns[i].onclick = function(){
                console.log(this);
                this.disabled = true;
                setTimeout(function(){
                    // console.log(this); bing绑定的this是指向当前点击按钮 不绑定的话 this指向的是window
                    this.disabled = false;
                    
                }.bind(this),2000);
            }
        }
        console.log(btns);
    </script>
</body>
</html>

3. 严格模式

关键词 use strict

3.1 开启严格模式

	<script>
	//1.在子调用函数下开启严格模式
	(function(){
		'use strict';
		var num = 10;	//严格模式下 没有声明的变量会报错
		console.log(num);
	})();
	//2.为函数开启严格模式
	function fn1(){
		//未开启严格模式
	}
	function fn2(){
		'use strict';
		//本函数内部开启严格模式
	}
	</script>
	<script>
	//3.在这个script标签中,开启严格模式
	'use strict';
	</script>

3.2 严格模式下的变化

	<script>
	'use strict'
	num = 10 
	console.log(num)//严格模式后使用未声明的变量
	--------------------------------------------------------------------------------
	var num2 = 1;
	delete num2;//严格模式不允许删除变量
	--------------------------------------------------------------------------------
	function fn() {
	 console.log(this); // 严格模式下全局作用域中函数中的 this 是 undefined
	}
	fn();  
	---------------------------------------------------------------------------------
	function Star() {
		 this.sex = '男';
	}
	// Star();严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.
	var ldh = new Star();
	console.log(ldh.sex);
	----------------------------------------------------------------------------------
	setTimeout(function() {
	  console.log(this); //严格模式下,定时器 this 还是指向 window
	}, 2000);  
	
	</script>

4. 高阶函数

高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出

	<script>
		//1.将函数作为参数
		function move(a,b,callback){
			console.log(a+b);
			callback&&callback(); //回调函数:执行完这个函数,再调用这个函数
		}
		move(1,2,function(){
			console.log('我执行完了');
		})
		//2.将函数作为返回值
		function fn(a){
			var num = a;
			//在函数内部调用另外一个函数,也属于闭包
			function fn1(){
				console.log(num);
			}
			fn1();
		}
		fn(5);  //输出5
	</script>

5. 闭包

5.1 什么是闭包

闭包(closure)指有权访问另一个函数作用域中变量的函数。简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量

	<script>
		function fn(a){
			var num = a;
			//在函数内部调用另外一个函数,也属于闭包
			function fn1(){
				console.log(num);
			}
			fn1();
		}
		fn(5);  //输出5
	</script>

5.2 闭包的作用

延伸变量的作用范围

	<script>
	 function fn() {
	   var num = 10;
	   function fun() {
	       console.log(num);
	 	}
	    return fun;
	 }
	var f = fn();
	f();
	</script>

5.3 demo案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>demo3</title>
</head>
<body>
    <ul>
        <li>窗前明月光</li>
        <li>疑是地上霜</li>
        <li>举头望明月</li>
        <li>低头思故乡</li>
    </ul>
    <script>
        //获取点击当前li的索引号
        var lis = document.querySelectorAll('li');
        for(var i=0;i<lis.length;i++){
            
            (function(i){
                lis[i].onclick = function(){
                console.log(i);
            }
            })(i)
        }
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>demo3</title>
</head>
<body>
    <ul>
        <li>窗前明月光</li>
        <li>疑是地上霜</li>
        <li>举头望明月</li>
        <li>低头思故乡</li>
    </ul>
    <script>
        //2秒后打印点击当前li的内容
        var lis = document.querySelectorAll('li');
        for(var i=0;i<lis.length;i++){
            (function(i){
                lis[i].onclick = function(){
                setTimeout(function(){
                console.log(lis[i].innerHTML);
                },2000);
            }
            })(i);
        }
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>demo4</title>
</head>
<body>
    <script>
        /*需求分析
        打车起步价13(3公里内),  之后每多一公里增加 5块钱.  用户输入公里数就可以计算打车价格
        如果有拥堵情况,总价格多收取10块钱拥堵费*/
        var car = (function(){
            var start = 13; //起步价
            var total = 0;  //总价
            return {
                price : function(n){
                    if(n<=3){
                        total = start;
                    }else{
                        total = start + (n-3) * 5;
                    }
                    return total;
                },
                yongdu : function(flag){
                    if(flag){
                        total +=10;
                    }
                    return total;
                }
            }
        })();
        console.log(car.price(5));
        console.log(car.yongdu(true));
    </script>
</body>
</html>

6.递归

在一个函数内部调用其本身,这个函数叫递归函数

6.1用递归做1-n的阶乘

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>阶乘</title>
</head>
<body>
    <script>
        function fn(n){
            if(n==1){
                return 1;
            }
            console.log(fn.prototype);
            return n * fn(n-1);
        }
        console.log(fn(3));
    </script>
</body>
</html>

6.2 利用递归遍历数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>demo7</title>
</head>
<body>
    <script>
         var data = [{
            id: 1,
            name: '家电',
            goods: [{
                id: 11,
                gname: '冰箱',
                goods: [{
                id: 111,
                gname: '海尔'
                }, {
                id: 112,
                gname: '美的'
                },

                        ]

            }, {
                id: 12,
                gname: '洗衣机'
            }]
            }, {
            id: 2,
            name: '服饰'
            }];
            function getData(data,id){
                var o = {};
                data.forEach(function(item){
                    // console.log(item.goods);
                    if(item.id === id){
                        o = item;
                        return o;
                    }
                    else if(item.goods && item.goods.length >0){
                        o = getData(item.goods,id);
                    }
                });
                return o;
            }
            console.log(getData(data,11));
    </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值