JavaScript-18

1.函数进阶

  • 函数的定义和使用
    • 函数声明方式function关键字(命名函数)
    • 函数表达式(匿名函数)
    • new Function()
      • Function里面的参数必须都是字符串格式
      • 第三种方式执行效率低,也不方便书写,因此较少使用
      • 所有函数都是Function的实例(对象)
      • 函数也属于对象
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //函数的定义方式
10             //1.自定义函数
11             function fn(){};
12             //2.函数表达式
13             var fun = function(){};
14             //3.利用new Function('参数1','参数2','函数体');
15             var f = new Function('a','b','console.log(a+b)');
16             f(1,2);
17             //4.所有的函数都是Function的实例对象
18         </script>
19     </body>
20 </html>
复制代码
  • 函数的调用方式
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //函数的调用方式
10             
11             //1.普通函数
12             function fn(){
13                 console.log("普通函数");
14             }
15             // fn();
16             // fn.call();
17             //2.对象的方法
18             var obj = {
19                 sayHi: function(){
20                     console.log("Hi");
21                 }
22             }
23             obj.sayHi();
24             //3.构造函数
25             function Star(){};
26             new Star();
27             //4.绑定时间的函数
28             // btn.onclick = function(){};
29             //点击按钮就可以调用这个函数
30             //5.定时器函数
31             setInterval(function(){},1000);
32             //这个函数是定时器自动每秒钟调用一次
33             //6.立即执行函数
34             (function(){console.log("怎么也飞不出,花花的世界~~~")})()
35             //立即执行函数是自动调用
36         </script>
37     </body>
38 </html>
复制代码
  • this
调用方式 this指向
普通函数调用 window
构造函数调用 实例对象,原型对象里面的方法也指向实例对象
对象方法调用 该方法所属对象
事件绑定调用 绑定事件对象
定时器函数 window
立即执行函数 window

 

复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //函数的调用方式
10             //函数的不同决定了this的指向不同
11             //1.普通函数 this指向window
12             function fn(){
13                 console.log("普通函数"+this);
14             }
15             // fn();
16             // fn.call();
17             //2.对象的方法 this指向对象
18             var obj = {
19                 sayHi: function(){
20                     console.log("Hi"+this);
21                 }
22             }
23             // obj.sayHi();
24             //3.构造函数 this指向的是实例对象,原型对象里面的this指向的也是实例对象
25             function Star(){};
26             new Star();
27             //4.绑定时间的函数 this指向函数的调用者btn
28             // btn.onclick = function(){};
29             //点击按钮就可以调用这个函数
30             //5.定时器函数 this指向window
31             setInterval(function(){},1000);
32             //这个函数是定时器自动每秒钟调用一次
33             //6.立即执行函数this指向window
34             (function(){console.log("怎么也飞不出,花花的世界~~~")})()
35             //立即执行函数是自动调用
36         </script>
37     </body>
38 </html>
复制代码
  • 改变函数内部this指向

    JavaScript为我们提供了一些函数方法帮助我们改变函数内部this指向问题,常用的有bind()、call()、apply()三种方法

    • call方法

      call方法调用一个对象,简单理解为调用函数的方式,但是它可以改变函数的this指向

    • apply()方法
      • fun.apply(thisArg,[argsArray])
      • thisArg:在fun函数运行时指定的this值
      • argsArray:传递的值,必须包含在数组里面
      • 返回值值就是函数的返回值,因为它必须是调用函数
    • bind()方法:不会调用函数
      • fun.bind(thisArg,arg1,arg2,…)
      • thisArg:在fun函数运行时指定this的值
      • arg1、arg2:传递其他参数
      • 返回由指定的this值和初始化参数改造的原函数拷贝
复制代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script type="text/javascript">
            //改变函数内this指向,js提供了三种方式call()、apply()、bind()
            //1.call()
            var o = {
                name: 'bbh'
            };
            function fn(arr,num){
                console.log(this);
                console.log(arr+num)
            }
            // fn.call(o);
            //call第一个可以调用函数,第二个可以改变函数内部的this指向
            //call的主要作用可以实现继承
            //2.apply()应用运用的意思
            // fn.apply(o,['bbh','56']);
            //(1)也是调用函数,第二个可以改变函数内部的this指向
            //(2)但是他的参数必须是数组、伪数组
            //(3)apply的主要应用比如我们可以利用apply借助于数学内置对象找最大值
            //3.bind()绑定捆绑的意思
            var res = fn.bind(o);
            //(1)不会调用原来的函数 可以改变原来函数内部this指向
            //(2)返回的是原函数改变this之后产生的新函数
            console.log(res);
        </script>
    </body>
</html>
复制代码
  • bind方法应用
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <button>点击</button>
 9         <script type="text/javascript">
10             //1.如果有的函数我们不需要立即调用,但是又想改变函数内部的this指向
11             //2.我们有一个按钮当我们点击了之后就禁用这个按钮,3秒之后启动
12             var btn = document.querySelector("button");
13             btn.onclick = function(){
14                 this.disabled = true;
15                 setTimeout(function(){
16                     this.disabled = false;
17                     //这个this指向的btn
18                 }.bind(this),3000)
19             }
20         </script>
21     </body>
22 </html>
复制代码
  • call、apply、bind总结
    • 相同点
      • 都可以改变函数内部的this指向
    • 区别点
      • call和apply会调用函数,并且改变函数内部this指向
      • call和apply传递的参数不一样,call传递参数arg1,arg2,…形式,apply必须数组形式[arg]
      • bind不会调用函数,可以改变函数内部this指向
    • 主要应用场景
      • call经常做继承
      • apply经常跟数组有关系,比如借助数学对象实现数组最大值和最小值
      • bind不调用函数,但是还想改变this指向,比如改变定时器里的this指向

2.严格模式

  JavaScript除了提供正常模式外,还提供了严格模式(strict mode)。即在严格的条件下运行JS代码

  • 严格模式
    • 消除了JavaScript语法的一些不合理,不严谨之处,减少了一些怪异行为
    • 消除代码运行的一些不安全之处,保证代码运行的安全
    • 提高编译器效率,增加运行速度
    • 禁用了在ECMAScript的未来版本中可能会使用的一些语法,例如一些保留字:class
  • 开启严格模式:严格模式可以应用到整个脚本或个别函数中。我们价格严格模式分为脚本开启严格模式和函数开启严格模式
    • 脚本开启严格模式
      • 为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句"use strict"
    • 函数开启严格模式
      • 需要把"use strict"声明放在函数题所有语句之前
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <!-- 为整个脚本(script标签)开启严格模式 -->
 9         <script type="text/javascript">
10             'use strict';
11             //下面的js代码会按照严格模式执行代码
12         </script>
13         <script type="text/javascript">
14             (function(){
15                 'use strict';
16             })()
17         </script>
18         <!-- 为某个函数开启严格模式 -->
19         <script type="text/javascript">
20             function fn(){
21                 //此时只是给函数fn开启严格模式
22                 'use strict';
23             }
24             function fun(){
25                 //里面还是按照普通模式执行
26             }
27         </script>
28     </body>
29 </html>
复制代码
  • 严格模式中的变化
    • 变量规定
      • 严格模式中,变量都必须先用var声明,然后再使用
      • 严禁删除已经声明的变量
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <!-- 为整个脚本(script标签)开启严格模式 -->
 9         <script type="text/javascript">
10             'use strict';
11             //下面的js代码会按照严格模式执行代码
12             //1.变量名必须先声明再使用
13             // num = 1;
14             // console.log(num);// num is not defined
15             //2.我们不能随意删除已经声明好的变量
16             // var num = 10;
17             // delete num;//Delete of an unqualified identifier in strict mode
18             
19         </script>
20         
21     </body>
22 </html
复制代码
    • 严格模式下this指向问题
      • 严格模式下全局作用域中的函数this指向的是undefined
      • 严格模式下,如果构造函数不加new调用,this就会报错
    • 函数变化
      • 函数不能有重名的参数
      • 函数必须声明在顶层,不允许在非函数代码块内声明函数

 3.高阶函数

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

  • 函数作为参数传递
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //高阶函数-函数可以作为参数传递
10             function fn(a,b,callback){
11                 console.log(a+b);
12                 callback&&callback();
13             }
14             fn(1,2,function(){
15                 console.log("success");
16             });
17         </script>
18     </body>
19 </html>
复制代码
  • 闭包

  闭包指有权访问另一个函数作用域中的变量的函数

复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //闭包(closure)指有权访问另一个函数作用域中变量的函数
10             //闭包:我们fun这个函数作用域 访问了另外一个函数fn里面的局部变量
11             //我们fn 外面的作用域可以访问fn,内部的额局部变量
12             //闭包的主要作用,延伸了变量的作用范围
13             function fn(){
14                 var num = 10;
15                 function fun(){
16                     console.log(num);
17                 }
18                 return fun;
19             }
20             var f = fn();
21             /*  
22                 类似于
23                 f = function fun(){
24                     console.log(num);
25                 }
26             */
27            f();
28         </script>
29     </body>
30 </html>
复制代码
  • 循环注册点击事件
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <ul class="nav">
 9             <li>榴莲</li>
10             <li>臭豆腐</li>
11             <li>鲱鱼罐头</li>
12             <li>大猪蹄子</li>
13         </ul>
14         <script type="text/javascript">
15             //闭包应用-点击li输出当前li的索引号
16             var lis = document.querySelectorAll(".nav li");
17             //1.利用动态添加属性的方式
18             // for(var i = 0 ; i < lis.length ; i++){
19             //     lis[i].index = i;
20             //     lis[i].onclick = function(){
21             //         console.log(this.index);
22             //     }
23             // }
24             //2.利用闭包的方式得到当前小li的索引号
25             for(var i = 0 ; i < lis.length ; i++){
26                 //利用for循环创建了4个执行函数
27                 (function(i){
28                     lis[i].onclick = function(){
29                         console.log(i);
30                     }
31                 })(i);
32             }
33         </script>
34     </body>
35 </html>
复制代码
  • 定时器中的闭包
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <ul class="nav">
 9             <li>榴莲</li>
10             <li>臭豆腐</li>
11             <li>鲱鱼罐头</li>
12             <li>大猪蹄子</li>
13         </ul>
14         <script type="text/javascript">
15             //闭包应用-3秒钟之后,打印所有li元素的内容
16             var lis = document.querySelectorAll(".nav li");
17             for(var i = 0 ; i < lis.length ; i++){
18                 (function(i){
19                     setTimeout(function(){
20                         console.log(lis[i].innerText);
21                     },3000);
22                 })(i)
23             }
24         </script>
25     </body>
26 </html>
复制代码
  • 打车价格
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //闭包应用-计算打车价格
10             //打车起步价13(3公里内),之后每多一公里增加5块钱,用户输入公里数就可以计算打车价格
11             //如果有拥堵情况,总价格多收取10块钱拥堵费
12             var res = (function(){
13                 var start = 13;//起步价
14                 var total = 0;//总价
15                 return {
16                     price: function(n){//正常价格
17                         if(n <= 3)
18                             total = 13;
19                         else{
20                             total = (n-3)*5 + 13;
21                         }
22                         return total;
23                     },
24                     yongdu: function(flag){//拥堵价格
25                         return flag ? total+10 : total;
26                     }
27                 }
28             })();
29             console.log(res.price(5));
30             console.log(res.yongdu(true));
31         </script>
32     </body>
33 </html>
复制代码
  • 闭包总结
    • 闭包是一个函数(一个作用域可以访问另一个函数的作用域)
    • 闭包的作用:延伸变量的作用范围

4.递归

  如果一个函数可以在内部调用其本身,这个函数就是递归函数

复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //递归函数:函数内部自己调用自己,这个函数就是递归函数
10             //由于递归很容易发生“栈溢出”错误,所以必须要加退出条件(return)
11             var num = 0;
12             function fn(){
13                 console.log("bbh");
14                 if(num == 5){
15                     return;//递归函数里面必须添加退出条件
16                 }
17                 num++;
18                 fn();
19             }
20             fn();
21         </script>
22     </body>
23 </html>
复制代码
  • 利用递归函数求解数学题
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //递归函数:函数内部自己调用自己,这个函数就是递归函数
10             //由于递归很容易发生“栈溢出”错误,所以必须要加退出条件(return)
11             function fn(n){
12                 if(n == 1){
13                     return 1;
14                 }
15                 return n*fn(n-1);
16             }
17             var res = fn(3);
18             console.log(res);
19         </script>
20     </body>
21 </html>
复制代码
  • 利用递归求斐波那契序列
复制代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script type="text/javascript">
            //利用递归函数求斐波那契序列
            //用户输入一个数字n,就可以求出这个数字对应的兔子序列值
            function fn(n){
                if(n == 1 || n == 2){
                    return 1;
                }else{
                    return fn(n-1)+fn(n-2);
                }
            }    
            console.log(fn(8))
        </script>
    </body>
</html>
复制代码
  • 根据id返回数据对象
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             //根据id返回数据对象
10             var data = [{
11                     id: 1,
12                     name: '家电',
13                     goods: [{
14                         id: 11,
15                         gname: '冰箱'
16                     }, {
17                         id: 22,
18                         gname: '洗衣机',
19                         goods: [{
20                                 id: 2201,
21                                 gname: '滚筒洗衣机'
22                             },
23                             {
24                                 id: 2202,
25                                 gname: '壁挂洗衣机'
26                             }
27                         ]
28                     }]
29                 },
30                 {
31                     id: 2,
32                     name: '服饰'
33                 }
34             ]
35             //我们想要做输入id号,就可以返回数据对象
36             //1.利用foreach遍历里面的每一个对象
37             function getId(json, id) {
38                 var res = {};
39                 json.some(function(value) {
40                     if (value.id == id) {
41                         res = value;
42                         return value.id == id;
43                     } else if(value.goods && value.goods.length > 0){
44                             res = getId(value.goods, id);
45                     }
46                 });
47                 return res;
48             }
49             console.log(getId(data, 2202));
50         </script>
51     </body>
52 </html>
复制代码
  • 深拷贝和浅拷贝
    • 浅拷贝知识拷贝一层,更深层次对象级别的只拷贝引用
    • 深拷贝拷贝多层,每一级别的额数据都会拷贝
    • 浅拷贝
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             var obj = {
10                 id: 1,
11                 name: 'bbh',
12                 msg: {
13                     age:18
14                 }
15             };
16             var o = {};
17             // for(var k in obj){
18             //     o[k] = obj[k];
19             // }
20             // o.msg.age = 30;
21             // console.log(o);
22             // console.log(obj);
23             console.log("---------------------");
24             //ES6提供的浅拷贝语法糖
25             //注意:浅拷贝只拷贝一层,当拷贝的数据里还存在复杂类型数据时,
26             //只会拷贝其地址,对数据进行修改时会影响到原来的数据
27             Object.assign(o,obj);
28             o.msg.age = 30;
29             console.log(obj);
30             console.log(o);
31         </script>
32     </body>
33 </html>
复制代码
    • 深拷贝
复制代码
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8">
 5         <title></title>
 6     </head>
 7     <body>
 8         <script type="text/javascript">
 9             var obj = {
10                 id: 1,
11                 name: 'bbh',
12                 msg: {
13                     age:18
14                 },
15                 sing: function(){
16                     
17                 }
18             };
19             var o = {};
20             function fn(obj,o){
21                 for(k in obj){
22                     //判断属性值属于哪种数据类型
23                     //1.获取属性值 obj[k]
24                     //2.判断这个值是否为数组
25                     //3.判断是否为对象
26                     if(obj[k] instanceof Array){
27                         o[k] = [];
28                         fn(obj[k],o[k]);
29                     }else if(obj[k] instanceof Object){
30                         o[k] = {};
31                         fn(obj[k],o[k]);
32                     }else{
33                         o[k] = obj[k];
34                     }
35                 }
36             }
37             //深拷贝封装函数
38             fn(obj,o);
39             o.msg.age = 30;
40             console.log(o);
41             console.log(obj);
42         </script>
43     </body>
44 </html>
复制代码
posted @   Miraitowa56  阅读(4412)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示