精华内容
下载资源
问答
  • JavaScript函数详解

    2020-10-24 16:23:40
    本文由简入深,详细介绍了javascript函数问题,非常的详尽,非常的实用,这里推荐给大家,是篇不可多得的
  • JS函数详解

    万次阅读 多人点赞 2019-07-10 22:56:56
    目录 1.函数概念,声明及调用 2.函数表达式(匿名函数) 3.函数传参 4.修改input的值 5.函数的不定参(可变...8.JS预解析机制(变量提升Hoisting) 9.作用域 10.window 11.全局污染(命名冲突问题) 12.作...

    目录

    1.函数概念,声明及调用

    2.函数表达式(匿名函数)

    3.函数传参

    4.修改input的值

    5.函数的不定参(可变参)—关键字arguments

    6.函数返回值

    7.封装获取元素的方法

    8.获取计算后样式—getComputedStyle(el)

    8.JS预解析机制(变量提升Hoisting)

    9.作用域

    10.window

    11.全局污染(命名冲突问题)

    12.作用域链(scope chain)

    13.闭包

    14.this当前执行代码的环境对象

    15.严格模式下的this指向

    16.this指向的修改

    16.1 function.call()

    16.2 function.apply()

    16.3 function.bind()

    16.4 bind方法原理分析:


    函数的基本概念、声明及调用;函数作用域、作用域链、闭包;this指向及修改和绑定this指向等。

    1.函数概念,声明及调用

    JS中的函数:把一段需要重复使用的代码,用function语法包起来,方便重复调用,分块和简化代码。复杂一点的,也会加入封装、抽象、分类等思想。

    声明方式:严格意义上两种方式,但还有匿名函数

    • 方式一:
    function 方法名(){
         //要执行的代码
    }
    • 方式二:ES6中声明方式箭头函数,()=>{} 
    • 方式三:匿名函数,将函数存到变量里 var func = function(){};

    函数调用:两种方式调用

    • 调用方式一:名字(); 函数可以多次调用
    //函数声明
    function fn(){
        console.log(1);
    }
    
    //函数的调用
    fn();

    调用方式二:在事件中调用,直接写函数名,不使用括号

    //函数声明
    function fn(){
        console.log(1);
    }
    
    //函数在事件中的调用
    document.onclick = fn;

    2.函数表达式(匿名函数)

    函数表达式:就是把函数存到变量里。

    匿名函数:没有名字的函数;

    匿名函数在使用时只有两种情况:

    • 匿名函数自执行:声明后不需要调用就直接执行
    (function(){
        console.log("匿名函数自执行");
    })();
    • 函数表达式:把函数存到变量,或将函数存到数组的对应位置里等,调用时通过变量或数组对应位置进行调用。调用时需要写括号。
    //2,函数表达式:把函数存到变量或数组等里,调用时通过变量进行调用
    var fn = function(){
        console.log("函数表达式:将函数存到变量里");
    };
    fn();//调用时需要写括号
    
    //2,函数表达式:把函数存到数组第0位,调用时通过数组第0位进行调用
    var arr = [];
    arr[0] = function(){
         console.log("函数表达式:将函数存到数组的对应位置");
    };
    arr[0]();//调用时需要写括号要写括号

    结果:

    事件函数扩展:给元素添加事件的说法是不正确的。事件时元素本身就具有的特征,只是触发事件后,默认没有相关的一些处理。这种操作其实就是给元素的某个事件添加一个事件处理函数。当事件被触发后,判断到属于该事件类型,就触发该事件函数的处理函数。

    可以通过console.dir()把对象的所有属性和方法打印出来,查看对象或元素本身具有的事件。

    <script>
           //事件时元素本身就具有的特征,只不过,触发事件后,默认没有相关的一些处理。事件函数其实就是给元素的某个时间添加一个事件处理函数。
           //可以通过console.dir()把对象的所有属性和方法打印出来
           document.onclick = function(){
               console.log("事件的处理函数");
           };
           //当被触发后,判断到属于该事件类型,就触发该事件函数的处理函数
           if(typeof document.onclick == "function"){
             document.onclick();
           }
    </script> 

     结果:

    3.函数传参

    获取元素,最好从父级元素获取,全部从document中获取,可能会出现混乱。

    • 形参:形式上的参数——给函数声明一个参数;
    • 实参:实际的参数——在函数调用时给形参赋的值
    function func(形参1,形参2){
        //函数执行代码
    }
    
    func(实参1,实参2);//调用时传参

    什么时候使用到传参?当有两段代码本身的功能极其相似,只有个别地方不一样时,就可以把两段代码合并成一个函数,然后把两段代码中不一致的内容通过传参传进去。

    案例:自定义(多个模块)选项卡封装

    <!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">
        <script src="../index.js"></script>
        <title>选项卡封装</title>
        <style>
            body { margin: 0; padding: 0; }
            .tab .active { background: red; }
            .cont div { display: none; }
            .cont .show { background: #000; font-size: 60px; color: white; width: 220px; height: 220px; display: block;  }
        </style>
    </head>
    <body>
    <div id="wrap1" class="wrap">
        <div class="tab">
            <button class="active">选项卡一</button>
            <button>选项卡二</button>
            <button>选项卡三</button>
        </div>
        <div class="cont">
            <div class="show">内容一</div>
            <div>内容二</div>
            <div>内容三</div>
        </div>
    </div>
    
    <div id="wrap2" class="wrap">
            <div class="tab">
                <button class="active">选项卡一</button>
                <button>选项卡二</button>
                <button>选项卡三</button>
            </div>
            <div class="cont">
                <div class="show">内容一</div>
                <div>内容二</div>
                <div>内容三</div>
            </div>
    </div>
    <div id="wrap3" class="wrap">
            <div class="tab">
                <button class="active">选项卡一</button>
                <button>选项卡二</button>
                <button>选项卡三</button>
            </div>
            <div class="cont">
                <div class="show">内容一</div>
                <div>内容二</div>
                <div>内容三</div>
            </div>
    </div>
    <script>
    
        //通过id获取元素
        /*
        var wrap1 = _id("wrap1");
        var wrap2 = _id("wrap2");
        var wrap3 = _id("wrap3");
        
        tab(wrap1);
        tab(wrap2);
        tab(wrap3);
        */
       //通过数组方式获取一组
        var wraps = _selectorAll(document,".wrap");//注意这里的parent父级已经是body了, 所以最好使用document
        for (var i = 0; i < wraps.length; i++) {
            tab(wraps[i]);
        }
        function tab(wrap){
            var btn = _selectorAll(wrap,".tab button");
            var divs = _selectorAll(wrap,".cont div");
    
            var num = 0;//记录当前样式
            for (var i = 0; i < btn.length; i++) {
                btn[i].index = i;
                btn[i].onclick = function(){
                    //清除当前样式
                    btn[num].classList.remove("active");
                    divs[num].classList.remove("show");
    
                    this.classList.add("active");
                    divs[this.index].classList.add("show");
    
                    num = this.index;
                };
            }
        }
    </script>
    </body>
    </html>

    index.js:

    function _id(idName){
        return document.getElementById(idName);
    }
    function _selector(parent,selector){
        return parent.querySelector(selector);
    }
    function _selectorAll(parent,selectors){
        return parent.querySelectorAll(selectors);
    }

     结果:

    4.修改input的值

    value和innerHTML都可以用来获取和修改元素的值(或内容);value只能获取特定的textarea和input的值,但是innerHTML可以获取所有HMTL元素的值。

    不同之处如下:
    1)value可以用来修改(获取)textarea和input的value属性的值或元素的内容;
    2)innerHTML用来修改(获取)HTML元素(如div)html格式的内容。

    <!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">
        <script src="../index.js"></script>
        <title>修改input的值</title>
        <style>
            .wrap input, .wrap button { display: none; }
            li { height: 30px; line-height: 30px; }
        </style>
    </head>
    <body>
        <div class="wrap">
            <ul>
                <li>
                    <span id="first">这是第一个列表</span>
                    <a href="javascript:;">修改</a>
                    <input type="text">
                    <button>确定</button>
                </li>
                <li>
                    <span>这是第二个列表</span>
                    <a href="javascript:;">修改</a>
                    <input type="text">
                    <button>确定</button>
                </li>
                <li>
                    <span>这是第三个列表</span>
                    <a href="javascript:;">修改</a>
                    <input type="text">
                    <button>确定</button>
                </li>
                <li>
                    <span value="asf">这是第四个列表</span>
                    <a href="javascript:;">修改</a>
                    <input type="text">
                    <button>确定</button>
                </li> 
            </ul>
        </div>
        <script>
            var lis = _selectorAll(document,"li");
            for (var i = 0; i < lis.length; i++) {
                modify(lis[i]);
            }
            function modify(li){
                var modify = _selector(li,"a");
                var span = _selector(li,"span");
    
                var input = _selector(li,"input");
                var btn = _selector(li,"button");
                //1.点击修改,“这是第一个列表”span标签隐藏,“修改”标签隐藏;input和确定按钮显示
                modify.onclick = function(){
                    span.style.display = "none";
                    this.style.display = "none";
                    input.style.display = "inline-block";
                    btn.style.display = "inline-block";
    
                    //注意:span标签只能通过.innerHTML获取元素的值,而不能通过.value
                    //2.将span标签的文字内容赋值给input输入框
                    input.value = span.innerHTML;
                };
                //3.点击确定按钮,先验证是否为空;再还原会span标签和修改a标签
                btn.onclick = function(){
                    var txt = input.value;
                    if(txt === ""){
                        alert("请输入内容");
                    }else{
                        input.style.display = "none";
                        this.style.display = "none";
                        span.style.display = "inline-block";
                        modify.style.display = "inline-block";
    
                        //4.将修改后的值赋给span标签
                        span.innerHTML = txt;
                    }
                };
            }
        </script>
    </body>
    </html>

    结果:

     

    5.函数的不定参(可变参)—关键字arguments

    案例:购物车商品累计。事先不知道用户买多少商品

    不定参(可变参)使用关键字:arguments,代表所有实参的集合。通过下标获取参数的每一位;通过length获取实参的个数;

    集合是类数组,可以使用下标,但是没有数组中的各种方法。

    <!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>可变参(不定参):arguments</title>
    </head>
    <body>
        <script>
            //arguments 代表所有实参的集合(类数组),可以通过下标获取各个实参,通过length获取集合长度
            function args(){
                console.log(arguments);
                console.log("arguments的各个参数为:");
                for (var i = 0; i < arguments.length; i++) {
                    console.log(arguments[i]);
                }
            } 
            
            args(23,45,999,10.90,"can","不定参");
        </script>
    </body>
    </html>

    结果:

     

    6.函数返回值

    函数返回值即函数执行之后的返回结果。

    1. 所有函数都会有函数返回值即函数执行后一定会返回一个结果,如果没有定义默认返回undefined;
    2. 在函数中,return后定义返回值;
    3. 在函数中,return之后的代码就不会再执行了
    4. return只能用于函数中,用在其他地方会报错
    <script>
            function func1(){
               console.log("函数func1执行内容");
            } 
            function func2(){
               console.log("函数func2执行内容");
               return 1;
               var a = 2;
               console.log(a);
            } 
            //如果没有定义默认返回undefined
            console.log("func1返回结果:"+func1());//undefined
            console.log("func2返回结果"+func2());//1
    </script>

    结果:发现return后的代码没有继续执行

    7.封装获取元素的方法

    封装通过id/CSS选择器获取(一般在父级下获取,所以传入父级和选择器名字)获取多个元素的方法,然后返回获取到的值

    //通过id名获取元素
    function _id(idName){
        return document.getElementById(idName);
    }
    
    //通过CSS选择器获取一个元素
    function _selector(parent,selector){
        return parent.querySelector(selector);
    }
    
    //通过CSS选择器获取一组元素
    function _selectorAll(parent,selectors){
        return parent.querySelectorAll(selectors);
    }

    使用:

    var wrap1 = _id("wrap1");
    var wrap2 = _id("wrap2");
    var wrap3 = _id("wrap3");
    
    var wraps = _selectorAll(document,".wrap");
    
    var btn = _selectorAll(wraps,".tab button");
    var divs = _selectorAll(wraps,".cont div");

    8.获取计算后样式—getComputedStyle(el)

    点击时获取box的宽度,在原有基础上+100

    • 从style中获取的是行间样式,但是通常样式不会写在行间;
    • 获取计算后样式:getComputedStyle(el)获取元素的计算后样式。属于window的方法,即window.getComputedStyle(el)。在JS中使用window下的方法时,window可以不写;
    • getComputedStyle(el)方法不兼容IE6,7,8
    • 计算后样式:优先级最高的样式,即当前显示出来的样式
    • 使用getComputedStyle(el)是获取window下所有的样式,getComputedStyle(el)['样式名']即可获取到特定样式
    • 写样式名时,使用驼峰样式的名字(否则IE下会有兼容问题),如margin-left必须写成marginLeft。
    • IE下获取元素的计算后样式,需要使用el.currentStyle['样式名']
    • 兼容IE和其他浏览器:判断el.currentStyle返回true即表示IE,否则就是其他浏览器,然后在对应浏览器下使用对应方法
    • 获取计算后样式会经常使用,因此可以封装成方法,进行复用
    • getComputedStyle(el)和el.currentStyle获取不到伪元素的样式,因为伪元素不是DOM的内容
    • 伪类样式计算后样式可以获取到,伪元素获取不到

    标准浏览器下:transition:.5s;设置过渡效果的时间,否则div会直接变到从100+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">
        <script src="../index.js"></script>
        <title>getComputedStyle(el)</title>
        <style>
            #box { width: 100px; height: 100px; background: red; transition:.5s; }
        </style>
    </head>
    <body>
        <div id="box"></div>
        <script>
            //需求:点击div,div的width在原有基础上+100px
            var box = _id("box");
            var ss = 0;
            box.onclick = function(){
                //直接获取box.style.width是获取不到的,因为样式时写到style标签,而非行间样式
                //console.log(box.style.width);//获取不到值
    
                //使用getComputedStyle(el)['样式名']即可获取到当前显示出来的样式
                var curStyle = getComputedStyle(box)['width'];
                //获取到的结果是“100px”,需要将其进行转为数字。width最后有可能会有小数点,所以最好使用parseFloat()。大多数情况下parseInt()亦可
                //但是parseInt(curStyle);才能去掉px进行相加
                //注意px前面的数字千万不要加引号
                this.style.width = parseInt(curStyle) + 100 + 'px';
            };
        </script>
    </body>
    </html>

    结果:

    不断点击后:

    兼容问题:发现在IE6,7,8下并不支持getComputedStyle(el)方法

    解决:通过el.currentStyle判断返回true代表在IE浏览器下,为false就不是在IE浏览器下。在IE浏览器下必须使用el.currentStyle才行

    //解决浏览器兼容问题:通过el.currentStyle判断返回true代表在IE浏览器下,为false就不是在IE浏览器下。在IE浏览器下必须使用el.currentStyle才行
    function currStyle(el,styleName){
        // var curStyle = '';
        // if(el.currentStyle){
        //     curStyle = el.currentStyle[styleName];
        // }else{
        //     curStyle = getComputedStyle(el)[styleName];
        // }
        // return curStyle;
        //使用三元获取返回值
        return el.currentStyle?el.currentStyle[styleName]:getComputedStyle(el)[styleName];
    }
    <!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">
        <script src="../index.js"></script>
        <title>getComputedStyle(el)</title>
        <style>
            #box { width: 100px; height: 100px; background: red; transition:.5s; }
        </style>
    </head>
    <body>
        <div id="box"></div>
        <script>
            //需求:点击div,div的width在原有基础上+100px
            var box = _id("box");
    
            box.onclick = function(){
                //直接获取box.style.width是获取不到的,因为样式时写到style标签,而非行间样式
                //console.log(box.style.width);//获取不到值
    
                //使用getComputedStyle(el)['样式名']即可获取到当前显示出来的样式
                // var curStyle = getComputedStyle(box)['width'];
                var curStyle = currStyle(box,'width');
                //获取到的结果是“100px”,需要将其进行转为数字。width最后有可能会有小数点,所以最好使用parseFloat()。大多数情况下parseInt()亦可
                //但是parseInt(curStyle);才能去掉px进行相加
                //注意px前面的数字千万不要加引号
                this.style.width = parseInt(curStyle) + 100 + 'px';
            };
        </script>
    </body>
    </html>

    结果:

    8.JS预解析机制(变量提升Hoisting)

    JS预解析机制(变量提升(Hoisting)):JS在读取到一个script标签(或者一个函数作用域)时,会先进行一个预解析的过程,在这个过程中,会把var声明的变量和function声明的函数体,提升到整个scriptt标签(或者一个函数作用域)最前边去。在预解析完之后,JS才会从上到下一行一行解析代码并执行。

    • var在预解析时,会把声明提升到最前边(赋值前打印返回undefined)。只提升声明,不会把赋值过程进行提升。
    • function的函数体在预解析时,会把整个函数体提升至最前边。(函数体:function fn(){ console.log(1);})
    • 函数表达式(函数表达式:var fn = function(){};)只会提升函数表达式的声明,不会执行(真正执行函数表达式前调用会返回undefined)
    • 在预解析时,会先预解析var(包括变量声明和函数表达式的变量声明),把var放在最前面,然后再预解析function,所以当var和function重名时,function会覆盖var;
       //JS var变量的预解析
        console.log("var变量的预解析:"+a);//undefined
        var a = 0;
    
        //JS函数体的预解析
        console.log("函数体的预解析:"+fn);
        function fn(){
            console.log("函数");
        }
        //JS函数表达式的预解析
        console.log("函数表达式的预解析:"+fnn);
        var fnn = function(){
            console.log("函数表达式");
        };

    结果:

    在预解析时,会先预解析var,把var放在最前面,然后再预解析function,所以当var和function重名时,function会覆盖var:

        /*
            解析过程:先预解析var声明的a,再预解析函数体a,后面覆盖前面,所以最后结果是function函数体
            var a;
            function a(){console.log("函数a");};//此函数体解析后会覆盖变量a
        */
        console.log(a);
        var a = 0;
        function a(){
            console.log("函数a");
        }

    结果:

    JS预解析示例:

        //JS预解析过程:遇到Script标签或一个函数作用域,会先进行预解析,先预解析var声明的变量(包括普通变量声明和函数表达式声明),再声明function函数体,如果有重名function声明会覆盖var声明
        /*
            预解析之后代码:
            var a;//变量a
            var a;//函数表达式a(函数表达式也是var声明)
            function a(){//函数体
                console.log(1);
            };
    
            console.log(a);//打印函数体a
            var a = 10;
            console.log(a);//10
            console.log(a);//10
            a = function(){
                console.log(2);//打印函数表达式a
            };
            console.log(a);
    
        */
        console.log(a);
        var a = 10;
    
        console.log(a);
        function a(){
            console.log(1);
        };
    
        console.log(a);
        var a = function(){
            console.log(2);
        };
    
        console.log(a);

    结果:

    JS预解析机制不是良好的编码习惯,不利于代码维护,建议不要使用,编码时建议先声明,再使用。

    扩展:从概念的字面意义上说,“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确。实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。

    ES6之后就不能像JS预解析这么编写JS代码了。

    9.作用域

    通常来说一段程序代码中使用的变量和函数并不总是可用的,限定其可用性的范围即作用域,作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突。

    通俗的说,作用域:数据起作用的范围(某条数据可以在什么范围内使用)

    前端权威官方MDN:https://developer.mozilla.org/en-US/docs/Glossary/Scope

    作用域的分类:

    1. - 全局作用域:通过var或function声明在全局(声明在任意函数之外和代码块之外)中的数据,在全局的任意地方都可以调用或修改(即全局变量)和在window下的属性
    2. - 局部作用域:
    • 函数作用域:声明在函数内部的某个数据(var,function,参数),就只能在函数内部使用(函数的局部作用域)
    • 块级作用域(ES6新增)

    全局作用域:

        //声明在全局中的变量
        var a = 0;
        console.log(a);//可在全局任意地方调用
        function fn(){
            console.log(a);//可在函数中调用
            a = 10;//可在任意地方修改全局中的变量
        }
        fn();
        console.log(a);

    结果:

    10.window

    • 在JS中,默认情况下 var声明的全局变量和function声明的全局函数会挂载在window上(所以要避免声明全局变量和全局函数)
    • 在JS中,默认全局数据都会保存在window下(ES6之前)
    • 另外window是JS在浏览器里的顶层对象,所以window的属性和方法也都是全局的
    • 在JS中,调用window下的属性和方法,默认可以不写window,所以如果在函数里面声明变量没有写var,会把其当做window的一个属性;(不规范写法,要避免)
        //var声明的全局变量和function声明的全局函数,都默认挂载在window上
        var a = 0;
        console.log(window);
    
        function fn(){
            b = 10;
            console.log(1);
        }
        fn();
        console.log(b);//此处b没有写声明的var所以,b=10即为window.b = 10;相当于挂载在window上的全局变量
    
        //在JS中,默认全局数据都会保存在window下
        //window是浏览器的最顶层对象,所以默认window下的属性和方法都是全局的。所以window下的方法和属性,默认可以不写window

     结果:全局变量a和全局函数fn()都默认挂载在window上。而且,此处b没有写声明的var,所以,b=10即相当于window.b = 10;也是挂载在window上的全局变量:

    11.全局污染(命名冲突问题)

    全局变量污染:大家都在全局中写代码,很容易造成命名冲突,导致代码冲突。ES6中代码冲突会直接报错。所以要养成好的习惯不要在全局去声明变量

    <!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>全局污染</title>
    </head>
    <body>
        <div id="list"></div>
        <div class="memulist"></div>
        <script>
            var list = document.getElementById("list");
            var list = document.querySelector(".memulist");
            console.log(list);
        </script>
    </body>
    </html>

     结果:发现最后获取的只有一个元素,所以很容易造成代码冲突

    解决:不要声明全局变量

    (function(){
         var list = document.getElementById("list");
         console.log(list);
    })();
    
    (function(){
          var list = document.querySelector(".memulist");
          console.log(list);
    })();

    结果: 

    JS中提供了id使用的简便方法,直接调用id名即可:但尽量不要这么写,不规范:

    console.log(list);

    匿名函数:匿名函数自执行本身就是为了避免在全局写代码,避免冲突的。匿名函数自执行也叫开启一个新的命名空间。即开启新的作用域,此作用域和其他的不会冲突。

    12.作用域链(scope chain)

    作用域链决定了哪些数据能被函数访问。当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充。

    作用域链:JS中数据的查找规则。

    作用域链查找过程:在JS中我们调用一条数据时,会先在当前作用域进行查找,如果找不到,就从向上找父作用域的数据,还找不到就接着向上,一直找到全局作用域(window对象),window都找不到就报错。

        //调用fn()时,在其子函数fn2()被调用时,首先会在fn2()自己的作用域内找变量a
        //找不到就在其父级作用域即fn()作用域中找,即a=10,然后打印a=10
        function fn(){
            var a = 10;
            function fn2(){
                console.log(a);
            }
            fn2();
        }
        fn();

     结果:

    作用域链查找关系图:

     作用域链示例:

    <script>
        function fn(){
            var b = 0;
            return function(){
                b++;
                console.log(b);
            };
        }
        var f = fn();
        console.log(f);//ƒ (){ b++; console.log(b); }
        f();//1
        f();//2
        f();//3
        fn()();//1
    </script> 

    结果:

    解析(函数拆分)三个f():

    注意:这里的var f = fn();是将函数fn()的返回值函数体f(){ b++; console.log(b); };赋给变量f,但是并没有执行该返回值函数体,当f()调用时,便执行了该函数体。f此时是fn的子函数,那它可以访问和更改父级fn的作用域中的b。

    b变量会一直赋值,是因为JS的垃圾回收机制决定的,只要检测都有引用存在,就不会释放。

    <!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>作用域链示例-函数拆分</title>
    </head>
    <body>
    <script>
        // function fn(){
        //     var b = 0;
        //     return function(){
        //         b++;
        //         console.log(b);
        //     };
        // }
        // var f = fn();
        // f();//1
        // f();//2
        // f();//3
        // fn()();//1
        //这里的var f = fn();是将函数fn()的返回值函数体function(){ b++; console.log(b); };赋给变量f,但是并没有执行该返回值函数体,当f()调用时,便执行了该函数体
        //即这里的三个f()相当于,在函数fn()中写了三个子函数,再进行调用
        //由于b变量对于fn1(),fn2(),fn3()都是父级变量,所以每次b++都会将b的值+1,所以最后得到的值即1,2,3
        function fn(){
            var b = 0;
            function fn1(){
                b++;
                console.log(b);
            }
            fn1();
            function fn2(){
                b++;
                console.log(b);
            }
            fn2();
            function fn3(){
                b++;
                console.log(b);
            }
            fn3();
        }
    
        fn();
    </script>    
    </body>
    </html>

    结果:所以执行三个f();和执行三个fn();得到的结果是不一样的。

    以上进一步分解:

     

    <script>
        // function fn(){
        //     var b = 0;
        //     return function(){
        //         b++;
        //         console.log(b);
        //     };
        // }
        // var f = fn();
        // f();//1
        // f();//2
        // f();//3
        // fn()();//1
        //这里的var f = fn();是将函数fn()的返回值函数体function(){ b++; console.log(b); };赋给变量f,但是并没有执行该返回值函数体,当f()调用时,便执行了该函数体
        //即这里的三个f()相当于,在函数fn()中写了三个子函数,再进行调用
        //由于b变量对于fn1(),fn2(),fn3()都是父级变量,所以每次b++都会将b的值+1,所以最后得到的值即1,2,3
        function fn(){
            var b = 0;
            // function fn1(){
            //     b++;
            //     console.log(b);
            // }
            // fn1();
            // function fn2(){
            //     b++;
            //     console.log(b);
            // }
            // fn2();
            // function fn3(){
            //     b++;
            //     console.log(b);
            // }
            // fn3();
            function fnn(){
                b++;
                console.log(b);
            }
            fnn();
            fnn();
            fnn();
    
        }
        fn();
    </script>   

    结果:所以调用三次f()和再fn()函数里执行三次fnn()是一样的

    函数拆分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>作用域链示例——函数拆分fn()()</title>
    </head>
    <body>
    <script>
        // function fn(){
        //     var b = 0;
        //     return function(){
        //         b++;
        //         console.log(b);
        //     };
        // }
        // var f = fn();
        // f();//1
        // f();//2
        // f();//3
        // fn()();//1
    
        //此处的fn()();第一个括号表示执行fn()函数,第二个括号表示执行fn()函数中返回值中的函数,所以fn()()相当于整个fn函数再执行一次
        //函数每次调用,都相当于把这个代码复制出来执行了一遍。所以fn()();每次执行都是重新执行一遍代码,相当于以下:
        function fn(){
            var b = 0;
            return function(){
                b++;
                console.log(b);
            };
        }
        function fnA(){
            var b = 0;
            return function(){
                b++;
                console.log(b);
            };
        }
        fn()();//1
        fnA()();//1
    </script>
    </body>
    </html>

    结果:

    函数每次调用,如fn()和fnA()之间没有任何关联,都相当于把这个代码复制出来执行了一遍。

    13.闭包

    闭包是对作用域链的一种表现和使用。

    函数对象可以通过作用域链相互关联起来,函数体内的数据(变量和函数声明)都可以保存在函数作用域内,这种特性在计算机科学文献中被称为“闭包”。既函数体内的数据被隐藏于作用于链内,看起来像是函数将数据“包裹”了起来。从技术角度来说,js的函数都是闭包:函数都是对象,都关联到作用域链,函数内数据都被保存在函数作用域内。

    fn()();调用函数后的返回值还是一个函数,也对其进行执行

    函数的每次执行之间没有任何关系。每次执行都相当于在JS内部吧代码重新写了一遍。

    面试时:闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

    闭包:

    • 形式:函数嵌套函数;
    • 作用:子函数可以访问父函数的作用域,但是父级不能访问子级的。

    闭包示例:

    <!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>闭包</title>
    </head>
    <body>
    <script>
        function fn(){
            var a = 0;
            function fn2(){
                console.log(a);//fn2是fn的子函数,所以可以访问父级作用域的a
            }
            fn2();
        }
        fn();
        console.log(a);//在fn函数作用域外,不能访问其子级作用域fn中的变量a
    </script>
    </body>
    </html>

    结果:

    闭包应用:i传参给了fn函数,而点击事件是fn函数的子函数,所以也可以获取到fn函数中的i

    <!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>闭包应用</title>
    </head>
    <body>
        <button>按钮一</button>
        <button>按钮二</button>
        <button>按钮三</button>
        <script>
            var btns = document.querySelectorAll("button");
            for (var i = 0; i < btns.length; i++) {
                fn(i);
            }
            //i传参给了fn函数,而点击事件是fn函数的子函数,所以也可以获取到fn函数中的i
            function fn(index){
                btns[index].onclick = function(){
                    console.log(index);
                };
            }
        </script>
    </body>
    </html>

    结果:按钮进行循环后会将当前index传参给fn函数,当点击按钮时,再通过父级作用域获取到父级的index

    闭包应用二:(匿名函数自执行方式)页面刷新时解析for循环并将index传给fn,并且立即执行fn函数,当点击按钮时,再通过父级作用域fn获取到index

    <script>
            var btns = document.querySelectorAll("button");
            for (var i = 0; i < btns.length; i++) {
                (function fn(index){
                    btns[index].onclick = function(){
                        console.log(index);
                    };
                })(i);
            }
            //i传参给了fn函数,而点击事件是fn函数的子函数,所以也可以获取到fn函数中的i
            // function fn(index){
            //     btns[index].onclick = function(){
            //         console.log(index);
            //     };
            // }
        </script>

    结果:

    闭包应用三:点击按钮后,再立即执行一个匿名函数自执行。匿名函数自执行后,得到的是一个函数返回值,当点击时再执行该函数中的内容

        <script>
            var btns = document.querySelectorAll("button");
            for (var i = 0; i < btns.length; i++) {
                //匿名函数自执行后,得到的是一个函数返回值,当点击时再执行该函数中的内容
                btns[i].onclick = (function fn(index){
                    return function(){
                        console.log(index);
                    };
                })(i);
            }
        </script>

    结果:

    14.this当前执行代码的环境对象

    默认情况下:

    • 函数外:window
    • 函数内:函数中的this指向谁,取决于这个函数是怎么调用的
    • 严格模式下,默认为undefined
    1. 作为对象的属性(方法,事件(方法的一种))调用,指向当前对象
    2. 其余情况执行window
    <script>
    //函数外:window
    // 函数内:函数中的this指向谁,取决于这个函数是怎么调用的
        // 作为对象的属性(方法)调用,指向当前对象
        // 其余情况执行window
    
    function fn(){
        console.log(this);
    }
    //直接调用函数,this代表window
    console.log("没有作为对象的属性进行调用,而是直接调用:");
    fn();//this指向window 
    
    //作为对象的属性或方法调用
    //作为对象的属性进行调用
    console.log("作为对象的属性进行调用:");
    document.fn = fn;
    document.fn();//this 执行document
    
    //事件里,把this绑定在事件上
    console.log("作为对象的属性(事件)进行调用:");
    document.onclick = fn;
    document.onclick();//this 执行document
    
    //数组里,把函数放到数组里,再由数组调用,此时this指向当前数组
    console.log("作为对象(数组)进行调用:");
    var arr = [fn,1,2];
    arr[0]();//this指向当前数组
    
    //obj对象里
    console.log("作为对象(object对象)进行调用:");
    var obj = {
        fn:fn
    };
    obj.fn();//this指向object对象
    </script>

    结果:

    15.严格模式下的this指向

     在script标签最上面加上 'use strict';,加上'use strict'后预解析已经不能使用,会报错。

    严格模式下的function指向问题:在严格模式下,function如果不是作为对象的属性和方法被调用(即直接调用方法)就指向undefined。

    <script>
    'use strict';
    function fn(){
        console.log(this);
    };
    console.log("严格模式下,函数直接被调用(没有通过函数的属性或方法被调用,this就指向undefined):");
    //严格模式下,函数直接被调用(没有通过函数的属性或方法被调用,this就指向undefined)
    fn();
    
    //通过函数的属性或方法被调用,就指向被调用的对象
    console.log("通过函数的属性或方法被调用,就指向被调用的对象:");
    document.onclick = fn;
    document.onclick();
    
    </script>

    结果:

    16.this指向的修改

    16.1 function.call()

    1. function.call(this指向谁,参数1,参数2...)调用函数,并修改函数中的this指向;
    2. 执行函数的call方法,会调用该函数,并且修改函数中 的this指向;
    3. call中的第0个参数,代表当前函数执行时,函数中的this指向谁
    4. 其他参数都是给函数传的实参
    5. 注意修改执行为body时,一定要使用document.body
    <script>
    function fn(a,b){
        console.log(this,a,b);
    }
    //直接执行,this指向window
    console.log("直接调用函数,this指向window:");
    fn(1,2);//window
    
    //通过call更改当前函数的this指向
    //更改this指向为document
    console.log("调用函数的call方法,更改this指向document:");
    fn.call(document,'a','b');//document 
    
    //更改this指向为document.body
    console.log("调用函数的call方法,更改this指向document.body:");
    fn.call(document.body,'a','b');//body
    
    </script>  

    结果:

    16.2 function.apply()

    1. function.apply(this指向谁,[参数1,参数2...])调用函数,并修改函数中的this指向
    2. 指向函数的apply方法,会调用该函数,并且修改函数中的this指向;
    3. apply中的第0个参数,代表当前执行时,函数中的this指向谁;
    4. apply中第1个参数是个数组,数组中代表了我们要往函数中传递的参数;且所有参数只能放在一个数组里,有多个数组时,除了第一个,其他数值的参数不会被接收
    5. apply和call唯一的区别在于,call方法直接在方法里传参,而apply是将所有参数已数组形式进行传递;
    6. 注意修改执行为body时,一定要使用document.body
    <script>
    function fn(a,b){
        console.log(this,a,b);
    }
    //直接调用,this指向window
    console.log("直接调用,this指向window:");
    fn('s','r');
    
    //调用函数的apply方法,更改this指向为document
    console.log("调用函数的apply方法,更改this指向document:");
    fn.apply(document,['2','4']);
    
    //调用函数的apply方法,更改this指向document.body
    console.log("调用函数的apply方法,更改this指向document.body:");
    fn.apply(document.body,['2','4']);
    </script> 

    结果: 

    16.3 function.bind()

    1. function.bind(指向,参数1,参数2,...)绑定this指向
    2. 调用函数的bind方法,会返回一个绑定了this执行的新函数;
    3. 第0个参数是bind返回的新函数的this指向
    4. 返回新函数的this指向被绑定了,不能再被更改
    5. 新函数的this指向在修改原函数this指向时就已经被绑定,一旦被绑定不能再次修改

    总结:调用函数的bind方法,会生成新的函数,绑定的this指向是针对新函数的,新函数this指向被绑定后,不能再继续被绑定(call和apply也不行);如果调用时再传入新的参数,会将新的参数和被绑定的参数进行合并,被绑定的参数会一直存在;而原函数的this指向一直没有变,还可以继续调用bind方法,生成新的函数,同时给新的函数绑定新的this指向

    <script>
    function fn(a,b){
        console.log(this,arguments);
    }
    //直接调用函数,this指向window
    console.log("直接调用函数,this指向window:");
    fn(1,2);//window
    
    //使用函数的bind方法
    console.log("使用函数的bind方法,返回新的函数:");
    var fn2 = fn.bind(document,3,4);
    console.log(fn2 == fn);//false 新函数和旧函数不是同一个
    
    console.log("原函数的this指向:");
    fn(5,6);//原函数的this指向不变,依然是window,且还可以继续调用bind方法
    
    console.log("新的函数的this指向:");
    console.log("如果新的函数调用时传入新的参数,会将绑定的参数和新传入的参数进行合并:");
    fn2(7,8);//3,4,7,8  新函数的this指向即原函数绑定的this指向
    
    //新函数的this指向在修改原函数this指向时就已经被绑定,一旦被绑定不能再次修改,且被绑定的参数也不能再被修改
    //只是如果调用新函数时传入新参数,会合并两次的参数
    console.log("新函数的this指向再修改原函数this指向时就已经被绑定,一旦被绑定不能再次修改:");
    fn2.call(window,9,0);//这里即使再次更改this指向,fn2新函数的this指向永远不会再改变
    
    //再次调用fn的bind方法
    console.log("再次调用fn的bind方法,返回新的函数:");
    var fn3 = fn.bind(document.body,'a','b');
    console.log(fn3 == fn);
    fn3('c','d');
    </script> 

    结果:

    16.4 bind方法原理分析:

    为什么调用bind生成的新函数,this指向被绑定后就不能再绑定了?bind方法在ES5.1后才出来,如果想实现此功能,可以自己写可以再次绑定的bind方法。

    自己实现bind方法:

    参数:fn 要绑定this函数;_this返回新函数this指向谁

    <script>
    //为什么调用bind生成的新函数,this指向被绑定后就不能再绑定了
    //自己实现bind方法的原理
    //fn要绑定的新函数,_this给新函数绑定的this指向,...arg传参(展开运算符ES6新增)
    function bind(fn,_this,...arg){
        return function(...args2){
            fn.call(_this,...arg,...args2);
        };
    }
    
    function fn(){
        console.log(this,arguments);
    }
    //调用bind方法,返回新的函数function(){ fn.call(_this); };
    var fn2 = bind(fn,document,11);
    //执行fn2()即执行返回的新函数,并给新的函数绑定this指向
    fn2(2,3);//document
    fn();
    
    //重新调用绑定函数,并返回新的函数同时给其绑定this执行
    var fn3 = bind(fn,document.body,12);
    fn3(4,5);//this
    </script> 

    结果:

    展开全文
  • COM组件中调用JavaScript函数详解及实例 要求是很简单的,即有COM组件A在IE中运行,使用JavaScript(JS)调用A的方法longCalc(),该方法是一个耗时的操作,要求通知IE当前的进度。这就要求使用回调函数,设其名称为...
  • Javascript构造函数是非常强大的,它可能也是Javascript能被充分利用的特点之一。但是如果你想真正的了解Javascript,你还是应该明白构造函数是如何工作的。本文,我们将从三个方面来讲述构造函数
  • js函数详解

    2018-12-11 16:41:29
    文章目录一、函数的命名二、函数调用的模式1.方法调用模式2.函数调用模式3.构造函数调用模式4.apply或call调用模式 一、函数的命名 函数使用function关键字来定义。它可以用在函数定义表达式或者函数声明语句里。在...

    一、函数的命名

    函数使用function关键字来定义。它可以用在函数定义表达式或者函数声明语句里。在这两种形式中,函数定义都从function关键字开始。
    1.表达式

    var a = function(){};//函数表达式实际上就是声明了一个变量,然后把一个函数的对象赋值给它
    

    2.函数声明

    function a(){};
    

    区别:函数声明,会将声明提前,在还未执行的时候就会解析,这样如果一个作用域有两个相同的函数名,那么值就会被覆盖,保存的是最后的那个,但是函数表达式就不会这样,它会在代码执行的时候被解析。

    二、函数调用的模式

    1.方法调用模式

    在JavaScript中函数也是一种对象,函数可以作为对象的属性,此时函数也称为对象的方法。

    var object={
    	op:1;
    	oq:2;
    	add:function(){
    		this.sum = this.op+this.oq;//this指代当前对象
    	}
    }
    onject.add();//作为方法调用,先调用方法,然后获取方法的值,执行object.rel;
    object.rel;//结果是3
    

    2.函数调用模式

    function a(){};
    a();//作为函数调用
    

    **区别:**方法调用和函数调用的主要不同在于执行环境也就是上下文。

    举例说明:

    var o={    //对象o
        m:function(){    //对象中的方法m()
            var self=this;    //将this值保存至一个变量中
            console.log(this===o)    //true,this就是对象o
            f();    //调用嵌套函数f
     
            function f(){
                console.log(this===o);    //false:this指向的是全局对象或者undefined
                console.log(self===o);    //true:self指向外部函数的this值
            }
        }
    }
    //调用
    o.m();
    

    此处特别要注意嵌套函数里面的this不是指向外层函数的this,如果想访问外部的this,需要将它保存在变量self中(当然可以随便命名),这个变量和内部函数都在同一个作用域中。
    注意
    作为对象调用的时候this指向的是该对象;
    作为函数调用的时候this指向的是全局变量,在浏览器中全局变量就是window,这里会隐式声明一个全局变量。

    举例说明:

    //这里写一个坐标平移的对象
    var point = { 
    x : 0, 							//两个属性
    y : 0, 
    moveTo : function(x, y) {         //函数作为对象的方法调用
        var moveX = function(x) {      // 内部函数,作为函数调用
        this.x = x;                   //this 绑定到了哪里?我们期望的是该对象的属性x
       }; 
       var moveY = function(y) {     // 内部函数
       this.y = y;                   //this 绑定到了哪里?
        }; 
       moveX(x);       			//调用(此处内部函数调用,隐式生成了一个全局变量x)
       moveY(y);     			//调用
       } 
    }; 
    point.moveTo(1, 1); 
    point.x; //==>0 	 			 //原来对象的属性x和y并没有发生变化,说明之前的this指向的并不是外部的对象,而是全局变量
    point.y; //==>0 
    x; //==>1 
    y; //==>1
    

    针对这种情况,我们可以通过将外部this保存在一个变量中(因为在js中this是动态变化的)以下做出改进函数:

    var point = { 
    x : 0, 
    y : 0, 
    moveTo : function(x, y) { 
         var that = this; ///特别注意
        var moveX = function(x) { 
        that.x = x; //改变
        }; 
        var moveY = function(y) { 
        that.y = y; ///改变
        } 
        moveX(x); 
        moveY(y); 
        } 
    }; 
    point.moveTo(1, 1); 
    point.x; //==>1 
    point.y; //==>1
    

    3.构造函数调用模式

    如果函数或者方法前面带有关键字new,它就构成了构造函数调用,有个不成文的规定,构造函数的函数名首字母要大写。构造函数通常不使用return关键字,常用于初始化对象

    function Point(x, y){ 
       this.x = x; 
       this.y = y; 
    };
    var point = new Point(1,2);//作为构造函数调用
    

    凡是没有形参的构造函数都可以省略圆括号,如下是等价的:

    var object = Object();
    var object = Object;
    

    4.apply或call调用模式

    JavaScript中函数也是对象,这是js的特殊之处,那么我们知道对象有属性和方法,apply和call就是函数对象的方法。这两个方法允许切换函数执行的上下文环境(就是this绑定的对象),apply和call的功能相同,只是实现的时候call是将每个参数分别传入,而apply是将参数放进一个数组装入。

    var func = function(arg1,arg2){   
    };
    

    //这里的this是自己想要指定的上下文,可以是js的任何一个对象,这样就能改变上下文了。

    func.call(this,arg1,arg2);
    func.apply(this,[arg1],[arg2]);
    

    举例说明:

    我们使用构造函数生成了一个对象 p1,该对象同时具有 moveTo 方法;使用对象字面量创建了另一个对象 p2,我们看到使用 apply 可以将 p1 的方法应用到 p2 上,这时候 this 也被绑定到对象 p2 上。另一个方法 call 也具备同样功能,不同的是最后的参数不是作为一个数组统一传入,而是分开传入的。

    function Point(x,y){//构造函数
               this.x = x;
               this.y = y;
               this.moveTo = function(x,y){
                   this.x = x;
                   this.y = y;
               };
           };
            var p1 = new Point(2,3);//构造函数调用
            var p2 = {  //创建一个对象字面量
                x:0,//注意这里是逗号
                y:0;
            };
            p1.moveTo(1,1);//调用方法
            p1.moveTo.apply(p2,[5,4]);
    

    下面这个更容易理解:

    function hello(thing) {
      console.log(this + " says hello " + thing);
    }
    
    hello.call("Yehuda", "world") //=> Yehuda says hello world
    
    展开全文
  • JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A。我们就说函数A叫做回调函数。如果没有名称(函数表达式),就叫做匿名回调函数。因此callback 不一定...
  • JavaScript笔记 函数详解

    千次阅读 2020-09-22 11:07:23
    这里写自定义目录标题函数的参数函数的返回值应用函数简化编程 函数的定义和调用 多条语句1,组合成一个"语句块"集体使用 //定义一个函数,函数就是一组语句的集合 function haha(){ console.log(1); console....

    函数的定义和调用

    多条语句1,组合成一个"语句块"集体使用

    	//定义一个函数,函数就是一组语句的集合
    	function haha(){
    		console.log(1);
    		console.log(2);
    		console.log(3);
    		console.log(4);
    	}
    	//调用函数
    	haha();
    

    在这里插入图片描述

    定义一个函数,用关键字function来定义,function就是英语功能的意思.表示这里面定义的语句,完成了一些功能.function后面有一个空格,后面就是函数名字,函数的名字也是关键字,命名规范和变量命名是一样的.名字后面一对圆括号,里面放置参数,然后就是大括号,大括号里面是函数的语句

    	function 函数名(){
    }
    

    函数如果不掉用,那么里面的语句就一辈子不会执行,不调用等于白写
    调用一个函数的方法非常简单,函数名后面加一个(),()是一个运算符,表示执行一个函数

    	函数名();
    

    一旦调用了函数,函数内部的语句就会执行

    能够感觉到,函数就是一些语句的集合,让语句成为一个军团,集体作战,要不出动都不出动,要出动就全出动,得到调用才出动
    函数的意义1:在出现大量程序相同的时候,可以封装为一个function,这样只用调用一次,就能执行很多语句

    函数的参数

    定义在函数内部的语句都是相同的,但实际上我们可以通过参数这个东西来让语句有差别
    定义函数的时候,内部语句可能有一些悬而未决的量,就是变量,这些变量,我们要求在定义的时候都罗列在小括号中:

    	function fun(a){
    		console.log("我第"+a+"次说爱你");
    		}
    

    调用的时候,要把这个变量的真实的值,一起写在括号里,这样随着函数的调用,这个值页传给了a

    	fun(88);
    

    在这里插入图片描述

    罗列在function小括号中的参数,叫做形式参数;调用时传递的数值,叫做实际参数。
    在这里插入图片描述

    参数可以有无数个,用逗号隔开。

    	//有多少形式参数都可以,都罗列出来
    	function fun(a,b){
    		console.log(a + b);
    	}
    	
    	fun(3,5);	//输出8
    	fun(8,11);	//输出19
    
    

    函数的意义2:我们在调用一个函数的时候,不用关心函数内部的实现细节,甚至这个函数是你上网抄的,可以运用。所以这个东西,给我们团队开发带来了好处。

    定义函数的时候,参数是什么类型的没写,不需要指定类型:

    	function sum(a,b){
    	console.log(a + b);
    		}
    
    

    也就是说调用的时候,传进去什么什么类型,就是a、b什么类型

    	sum("5",12);
    

    在这里插入图片描述

    我们还可以发现,定义的时候和调用的时候参数个数可以不一样多,不报错。

    	sum(10);
    

    在这里插入图片描述

    	sum(10,20,32,23,22,2,4);
    

    在这里插入图片描述

    只有前两个参数被形参接收了,后面的参数无视了

    函数的返回值

    函数可以通过参数来接收东西,更可以通过return的语句来返回值,“吐出”东西。

    	function sum(a,b){
    		return a + b;		//现在这个函数的返回值就是a+b的和
    	}
    	
    	console.log(sum(3,8));  //sum没有输出功能,就要用console.log输出
    	//sum(3,8)实际上就成为了一个表达式,需要计算
    	//计算后就是11,console.log(11);
    

    函数只能有唯一的return,有if语句除外

    程序遇见了return,将立即返回结果,返回调用它的地方,而不执行函数内的剩余的语句。

    	function fun(){
    		console.log(1);
    		console.log(2);
    		return;			   //返回一个空值
    		console.log(3);  //这行语句不执行,因为函数已经return了
    	}
    	
    	fun();
    

    在这里插入图片描述

    函数有一个return的值,那么现在这个函数,实际上就是一个表达式,换句话说这个函数就是一个值。
    所以这个函数,可以当做其他函数的参数。

    sum(3,sum(4,5));
    

    程序从最内层做到最外层, sum(3,9) 12在这里插入图片描述

    函数可以接受很多值,返回一个值,
    函数的意义3:模块化编程,让复杂的逻辑变得简单。

    函数表达式

    定义函数除了使用function之外,还有一种方法,就是函数表达式。就是函数没有名字,称为“匿名函数”,为了今后能够调用它,我们把这个匿名函数,直接赋值给一个变量。

    	var haha = function(a,b){
    	return a + b;3	}
    

    以后想调用这个函数的时候,就可以直接使用haha变量来调用。

    	console.log(haha(1,3));
    

    如果现在这个函数表达式中的function不是匿名的,而是有名字的:

    	var haha = function xixi(a,b){
    		return a + b;
    	}
    

    那么JS表现非常的奇怪,在外部只能用haha()来调用,xixi()非引发错误!

    在这里插入图片描述

    也就是说,JS这个奇怪的特性,给我们提了个醒,定义函数,只能用这两种方法,但是不能杂糅:

    	function haha(){
    		2
    	}
    
    	var haha = function(){
    		2
    	}
    

    错误的

    	var xixi = function haha(){
    		2
    	}
    

    函数声明的提升(预解析)

    	//先调用
    	fun();	
    	//然后定义
    	function fun(){
    		alert("我是函数,我执行了!");
    	}
    

    不会引发错误,alert能够弹出。
    JS在执行前,会有一个预解析的过程,把所有的函数声明,都提升到了最最开头,然后再执行第一行语句。
    所以,function定义在哪里,都不重要,程序总能找到这个函数。

    函数声明会被提升,但是函数表达式却不会被提升

    	fun();
    		var fun = function(){   //函数表达式,而不是function定义法
    		alert("我是函数,我执行了!");
    	}
    

    在这里插入图片描述

    又给我们提了个醒,没有极特殊的理由,都要使用function haha(){} 来定义函数,而不要使用var haha= function(){}

    函数优先

    	aaa();	//现在这个aaa到底是函数,还是变量5呢?
    	//函数优先,遇见同名标识符,预解析阶段一定把这个标识符给函数
    	
    	var aaa = 5;		//定义一个变量,是5
    	
    	function aaa(){
    		alert("我是aaa函数,我执行了");
    	}
    

    面试题

    在这里插入图片描述

    函数优先,现在foo这个标识符冲突了,一个函数叫做foo,一个变量也叫作foo。预解析阶段,如果遇见标识符冲突,这个标识符给函数。
    函数优先 : 如果同一个标识符,在程序中又是变量的名字,又是函数的名字,解析器会把标识符给函数

    	a();
    	var a = 1;
    	function a(){
    		alert("我是函数");
    	}
    

    在这里插入图片描述
    在执行var a = 1之前,函数已经把function a()预解析了,程序就已经知道页面上有一个函数叫做a。但是开始执行程序之后,定义了一个变量a,所以标识符a,就又变成变量了。遇见function定义,程序会无视,因为已经预解析了。直到a()运行的时候,a就是变量,无法运行,报错。

    	function fun(){
    	var a = 1;
    	function a(){
    		alert("我是函数");
    	}
    	
    	a();
    

    在这里插入图片描述

    但是函数表达式是不会预解析的,所以预解析的就是变量a的定义,就是undefined,undefined是无法执行的。

    	a();
    	var a = 1;
    	var a = function(){
    		alert("我是函数");
    	}
    

    在这里插入图片描述
    函数是一个引用类型
    我们之前说的,基本类型:number、string、boolean、undefined、null
    引用类型也有很多种:object、function、array、RegExp、Math、Date。

    	function fun(){
    	
    	}
    	
    	console.log(typeof fun);
    

    在这里插入图片描述
    函数也是一种类型。这个类型就叫做function,是引用类型的一种。
    基本类型保存值,引用类型保存地址
    我们现在变量a = 6 ; 那么这个a变量里面存储的是6这个数值;
    而a = function(){} 那么这个a标签里面存储的是function的内存地址。

    在这里插入图片描述
    a、b指向的是内存中的同一个地址,所以a就是b,b就是a。

    	//定义了一个变量a,引用了一个funciton
    	//这个a变量存储的是这个匿名函数的内存地址
    	var a = function(){
    	alert("我是一个函数,我执行了");
    	}
    	//就是把匿名函数的地址也给了b
    	var b = a;
    	//给b添加一个属性, 以后讲对象的时候,我们再看
    	b.haha = 1;
    	//输出a的haha属性,你会发现a也有这个属性了:
    	console.log(a.haha);
    	//b的haha属性和a的同步更改的,因为都是指向的同一个对象
    	b.haha++;
    	b.haha++;
    	b.haha++;
    	console.log(a.haha);
    

    函数作用域

    函数能封闭住定义域

    一个变量如果定义在了一个function里面,那么这个变量就是一个局部变量,只在这个function里面有定义。出了这个function,就如同没有定义过一样。

    	<script type="text/javascript">
    	function fn(){
    		var a = 1;	//定义在一个函数里面的变量,局部变量,只有在函数里面有定义
    		console.log("我是函数里面的语句,我认识a值为" + a);
    	}
    	
    	fn();
    	console.log("我是函数外面的语句,我不认识a" + a);
    	</script>
    

    在这里插入图片描述

    a被var在了function里面,所以现在这个a变量只在红框范围内有定义:
    在这里插入图片描述

    JavaScript变量作用域非常的简单,没有块级作用域,管理住作用域的只有一个东西:函数。

    如果一个变量,没有定义在任何的function中,那么它将在全部程序范围内都有定义:

    	var a = 1;	//定义在全局范围内的一个变量,全局变量,在程序任何一个角落都有定义
    	
    	function fn(){
    		console.log("我是函数里面的语句,我认识全局变量a值为" + a);
    	}
    	
    	fn();
    	console.log("函数外面的语句也认识a值为" + a)
    

    在这里插入图片描述

    总结

    • 定义在function里面的变量,叫做局部变量,只在function里面有定义,出了function没有定义的。
    • 定义在全局范围内的,没写在任何function里面的,叫做全局变量,都认识。

    作用域链

    当遇见一个变量时,JS引擎会从其所在的作用域依次向外层查找,查找会在找到第一个匹配的标识符的时候停止。

    	function outer(){
    		var a = 1;		//a的作用域就是outer
    		inner();
    	function inner(){
    		var b = 2;		//b的作用域就是inner
    		console.log(a);	//能够正常输出1,a在本层没有定义,就是找上层
    		console.log(b);   //能够正常输出2
    	}
    	}
    	
    	outer();
    	console.log(a);		//报错,因为a的作用域outer
    

    在这里插入图片描述

    多层嵌套,如果有同名的变量,那么就会发生“遮蔽效应”:

    	var a = 1;		//全局变量
    	function fn(){
    		var a = 5;         //就把外层的a给遮蔽了,这函数内部看不见外层的a了。
    		console.log(a);	//输出5,变量在当前作用域寻找,找到了a的定义值为5
    	}
    	fn();
    	console.log(a);  //输出1,变量在当前作用域寻找,找到了a的定义值为1
    

    在这里插入图片描述

    作用域链:一个变量在使用的时候得几呢?就会在当前层去寻找它的定义,找不到,找上一层function,直到找到全局变量,如果全局也没有,就报错。

    	var a = 1;		//全局变量
    	var b = 2;		//全局变量
    	function outer(){
    		var a = 3;		//遮蔽了外层的a,a局部变量
    	function inner(){
    		var b = 4;  //遮蔽了外层的b,b局部变量
    		console.log(a);   //① 输出3,a现在在当前层找不到定义的,所以就上一层寻找
    		console.log(b);   //② 输出4
    	}
    	inner();		//调用函数
    	console.log(a);	//③ 输出3
    	console.log(b); //④ 输出2 b现在在当前层找不到定义的,所以就上一层寻找
    	}
    	outer();		//执行函数,控制权交给了outer
    	console.log(a);	// ⑤ 输出1
    	console.log(b); // ⑥ 输出2
    

    不写var就自动成全局变量了

    	function fn(){
    		a = 1;		//这个a第一次赋值的时候,并没有var过,
    					//所以就自动的在全局的范围帮你var了一次
    	}
    	
    	fn();
    	console.log(a);
    

    这是JS的一个机理,如果遇见了一个标识符,从来没有var过,并且还赋值了:

    absdf = 123;
    

    那么就会自动帮你在全局范围内定义var absdf;
    告诉我们一个道理,变量要老老实实写var。

    函数的参数,会默认定义为这个函数的局部变量

    	function fn(a,b,c,d){
    	}
    

    a,b,c,d就是一个fn内部的局部变量,出了fn就没有定义。

    全局变量的作用

    全局变量挺有用的,有两个功能:

    **功能1:**通信,共同操作同一个变量
    两个函数同时操作同一个变量,一个增加,一个减少,函数和函数通信。

    	var num = 0;
    	
    	function add(){
    		num++;
    	}
    	
    	function remove(){
    		num--;
    	}
    

    **功能2:**累加,重复调用函数的时候,不会重置

    	var num = 0;
    	function baoshu(){
    		num++;
    		console.log(num);
    	}
    	
    	baoshu();	//1
    	baoshu();	//2
    	baoshu();	//3
    

    如果num定义在baoshu里面,每次执行函数就会把num重置为0:

    	function baoshu(){
    		var num = 0;
    		num++;
    		console.log(num);
    	}
    	
    	baoshu();	//1
    	baoshu();	//1
    	baoshu();	//1
    

    函数的定义也有作用域

    //这个函数返回a的平方加b的平方
    function pingfanghe(a,b){
    	return  pingfang(a) + pingfang(b);
    	//返回m的平方
    	function pingfang(m){
    		return Math.pow(m,2)
    	}
    }
    
    // 现在相求4的平方,想输出16
    pingfang(4);	//报错,因为全局作用域下,没有一个函数叫做pingfang
    

    公式:

    	function{
    		function{
    		
    		}
    		();   //可以运行
    	}
    	
    	();   //不能运行,因为小函数定义在了大函数里面,离开大函数没有作用域。
    

    闭包

    一个函数可以把它自己内部的语句,和自己声明时所处的作用域一起封装成了一个密闭环境,我们称为“闭包”.

    	function outer(){
    		var a = 333;
    		function inner(){
    			console.log(a);
    		}
    		return inner;
    	}
    	
    	var inn = outer();
    	inn(); //弹出333
    

    推导过程:

    我们之前已经学习过,inner()这个函数不能在outer外面调用,因为outer外面没有inner的定义:

    	function outer(){
    		var a = 888;
    		function inner(){
    			console.log(a);
    		}
    	}
    	//在全局调用inner但是全局没有inner的定义,所以报错
    	inner();
    

    但是我们现在就想在全局作用域下,运行outer内部的inner,此时我们必须想一些奇奇怪怪的方法。
    有一个简单可行的办法,就是让outer自己return掉inner:

    	function outer(){
    		var a = 333;
    		function inner(){
    			console.log(a);
    		}
    	return inner;	//outer返回了inner的引用
    	}
    	
    	var inn = outer();	//inn就是inner函数了
    	inn();			//执行inn,全局作用域下没有a的定义
    	//但是函数闭包,能够把定义函数的时候的作用域一起记忆住
    	//能够输出333
    

    这就说明了,inner函数能够持久保存自己定义时的所处环境,并且即使自己在其他的环境被调用的时候,依然可以访问自己定义时所处环境的值。


    一个函数可以把它自己内部的语句,和自己声明时所处的作用域一起封装成了一个密闭环境,我们称为“闭包” (Closures)。

    在这里插入图片描述

    每个函数都是闭包,每个函数天生都能够记忆自己定义时所处的作用域环境。但是,我们必须将这个函数,挪到别的作用域,才能更好的观察闭包。这样才能实验它有没有把作用域给“记住”。
    我们发现,把一个函数从它定义的那个作用域,挪走,运行。嘿,这个函数居然能够记忆住定义时的那个作用域。不管函数走到哪里,定义时的作用域就带到了哪里。这就是闭包。

    闭包在工作中是一个用来防止产生隐患的事情,而不是加以利用的性质。
    因为我们总喜欢在函数定义的环境中运行函数。从来不会把函数往外挪。那为啥学习闭包,防止一些隐患,面试绝对考。

    闭包的性质

    每次重新引用函数的时候,闭包是全新的。

    	function outer(){
    		var count = 0;
    		function inner(){
    			count++;
    			console.log(count);
    		}
    		return inner;
    	}
    	
    	var inn1 = outer();
    	var inn2 = outer();
    	
    	inn1();	//1
    	inn1();	//2
    	inn1(); //3
    	inn1(); //4
    	inn2(); //1
    	inn2(); //2
    	inn1(); //5
    

    无论它在何处被调用,它总是能访问它定义时所处作用域中的全部变量

    IIFE及时调用表达式

    FFIE定义

    IIFE: Immediately Invoked Function Expression,意为立即调用的函数表达式,也就是说,声明函数的同时立即调用这个函数。
    对比一下,这是不采用IIFE时的函数声明和函数调用:

    	function foo(){
    		var a = 10;
    		console.log(a);
    	}
    	foo();
    

    下面是IIFE形式的函数调用:

    	(function foo(){
    		var a = 10;
    		console.log(a);
    	})();
    

    函数的声明和IIFE的区别在于,在函数的声明中,我们首先看到的是function关键字,而IIFE我们首先看到的是左边的(。也就是说,使用一对()将函数的声明括起来,使得JS编译器不再认为这是一个函数声明,而是一个IIFE,即需要立刻执行声明的函数。
    两者达到的目的是相同的,都是声明了一个函数foo并且随后调用函数foo。

    为什么需要IIFE?

    如果只是为了立即执行一个函数,显然IIFE所带来的好处有限。实际上,IIFE的出现是为了弥补JS在scope方面的缺陷:JS只有全局作用域(global scope)、函数作用域(function scope),从ES6开始才有块级作用域(block scope)。对比现在流行的其他面向对象的语言可以看出,JS在访问控制这方面是多么的脆弱!那么如何实现作用域的隔离呢?在JS中,只有function,只有function,只有function才能实现作用域隔离,因此如果要将一段代码中的变量、函数等的定义隔离出来,只能将这段代码封装到一个函数中。
    在我们通常的理解中,将代码封装到函数中的目的是为了复用。在JS中,当然声明函数的目的在大多数情况下也是为了复用,但是JS迫于作用域控制手段的贫乏,我们也经常看到只使用一次的函数:这通常的目的是为了隔离作用域了!既然只使用一次,那么立即执行好了!既然只使用一次,函数的名字也省掉了!这就是IIFE的由来。

    IIFE的常见形式

    根据最后表示函数执行的一对()位置的不同,常见的IIFE写法有两种,示例如下:
    **列表1:**IIFE写法一

    	(function foo(){
    		var a = 10;
    		console.log(a);
    	})();
    

    **列表2:**IIFE写法二

    	(function foo(){
    		var a = 10;
    		console.log(a);
    	}());
    

    这两种写法效果完全一样,使用哪种写法取决于你的风格,貌似第一种写法比较常见。
    其实,IIFE不限于()的表现形式[1],但是还是遵守约定俗成的习惯比较好。

    IIFE的函数名和参数

    根据《You Don’t Know JS:Scope & Clouses》[2]的说法,尽量避免使用匿名函数。但是IIFE确实只执行一次,给IIFE起个名字有些画蛇添足了。如果非要给IIFE起个名字,干脆就叫IIFE好了。
    IIFE可以带(多个)参数,比如下面的形式:

    	var a = 2;
    	(function IIFE(global){
    		var a = 3;
    		console.log(a); // 3
    		console.log(global.a); // 2
    	})(window);
    
    	console.log(a); // 2
    

    IIFE构造单例模式

    JS的模块就是函数,最常见的模块定义如下:

    	function myModule(){
    		var someThing = "123";
    		var otherThing = [1,2,3];
    	
    		function doSomeThing(){
    			console.log(someThing);
    		}
    		
    			function doOtherThing(){
    			console.log(otherThing);
    		}
    		
    		return {
    			doSomeThing:doSomeThing,
    			doOtherThing:doOtherThing
    		}
    	}
    	
    	var foo = myModule();
    	foo.doSomeThing();
    	foo.doOtherThing();
    	
    	var foo1 = myModule();
    	foo1.doSomeThing();
    

    如果需要一个单例模式的模块,那么可以利用IIFE:

    	var myModule = (function module(){
    		var someThing = "123";
    		var otherThing = [1,2,3];
    		
    		function doSomeThing(){
    			console.log(someThing);
    		}
    		
    			function doOtherThing(){
    			console.log(otherThing);
    		}
    		
    		return {
    			doSomeThing:doSomeThing,
    			doOtherThing:doOtherThing
    		}
    	})();
    	
    	myModule.doSomeThing();
    	myModule.doOtherThing();
    

    IIFE小结
    IIFE的目的是为了隔离作用域,防止污染全局命名空间。
    ES6以后也许有更好的访问控制手段(模块?类?),有待研究。

    通过数组来观察闭包

    	function outer(){
    		var a = 10;
    		function inner(){
    			a++;
    			console.log(a);
    		}
    		return inner;
    	}
    	
    	var inn = outer();
    	inn();
    	inn();
    	
    	var inn1 = outer();
    	inn1();
    	inn1();
    
    	var arr = [];
    	for(var i = 0; i < 10; i++){
    		arr[i] = function(){
    			console.log(i);
    		};
    	}
    	console.log(arr);
    	arr[0](); // 10 因为当我们for循环时每个元素对应的函数中只是记住了i这个变量  当去执行函数时  i已经变成10了
    	arr[3](); // 10
    	arr[6](); // 10
    	arr[9](); // 10
    
    	var arr = [];
    	for(var i = 0; i < 10; i++){
    	
    		(function(m){
    			arr[m] = function(){
    			console.log(m); // 每次循环时我们都是新的IIFE 里面的m都是不同的m
    				}
    			})(i);
    	}
    	
    	
    	console.log(arr);
    	arr[0](); // 0
    	arr[3](); // 3
    	arr[6](); // 6
    	arr[9](); // 9	
    
    展开全文
  • 主要给大家介绍了JS中是如何实现Laravel的route函数,文中通过示例代码介绍的很详细,相信对大家具有一定的参考价值,有需要的朋友们下面来一起看看吧。
  • Javascript 函数详解

    2020-05-07 09:33:05
    Javascript 函数 1)函数声明: 通过关键字function定义,把函数作为变量来声明 函数声明后不会立即执行,会在我们需要的时候调用到。 <script> function myFunction(a, b) { return a * b; } // js对大...

    Javascript 函数详解

    1)函数声明:
    通过关键字function定义,把函数作为变量来声明
    函数声明后不会立即执行,会在我们需要的时候调用到。

    <script>
    	function myFunction(a, b) {
    	    return a * b;
    	}
    	// js对大小写敏感,function必须小写,调用时大小写也必须一致。
    	// 函数声明不是一个可执行语句,所以不 以分号结尾。
    </script>
    

    2)函数表达式:函数表达式可以存储在变量中

    var x = function (a, b) {return a * b};
    var y = x(1, 2);
    

    3)Function() 构造函数:通过内置函数构造器Function()来定义。

    let a = new Function('a', 'b', 'return a + b');
    let b = a(1, 2);
    document.write(a); //function anonymous(a,b ) { return a + b }
    document.write(b); // 3
    
    // 构造函数:
    function myFunction(arg1, arg2) {
        this.firstName = arg1;
        this.lastName  = arg2;
    }
    var x = new myFunction("John","Doe");
    x.firstName;   //  "John"
    

    4) 自调用函数:表达式后面紧跟 () ,则会自动调用

    5)箭头函数: IE11 及更早 IE 版本不支持箭头函数
    箭头函数表达式的语法比普通函数表达式更简洁

    (参数1, 参数2,, 参数N) => { 函数声明 }
    
    (参数1, 参数2,, 参数N) => 表达式(单一)
    // 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
    
    // ES5
    var x = function(x, y) {
         return x * y;
    }
    // ES6
    const x = (x, y) => x * y;
    
    (function () {
        var x = "Hello!!";      // 我将调用自己
    })();
    

    6) 函数是对象:
    a) arguments: 隐式参数
    arguments对象是所有(非箭头)函数中都可用的局部变量。
    可以使用arguments对象在函数中引用函数的参数。
    arguments对象不是一个 Array 。它类似于Array,但除了length属性和索引元素之外没有任何Array属性
    在这里插入图片描述
    在这里插入图片描述

    7)函数的参数:(显式参数),调用函数时,传递的值就叫参数,供在函数中使用。
    多个参数由逗号(,)分隔;

    <script>
    	function way(a, b) {
    		alert(a + b);
    	}
    	way(2, 3); 
    </script>
    

    c) 带返回值的函数:使用return语句返回值;执行return时函数会停止执行,并返回指定的值。

    <script>
    	function way(a, b) {
    		return a + b;
    	}
    	let c = way(2, 3); // 5;
    </script>
    
    <script>
    	function way(a, b) {
    		return a > b;
    	}
    	let c = way(2, 3); // false;
    </script>
    
    <script>
    	let c = 0;
    	function way(a, b) {
    		if (a < b) {
    			return;
    		};
    		c = a + b;
    	}
    	let c = way(2, 3); // undefined;
    	document.write(c);  // 5
    </script>
    

    8) 闭包:
    闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

    闭包的特性:
    1.函数内再嵌套函数
    2.内部函数可以引用外层的参数和变量
    3.参数和变量不会被垃圾回收机制回收

    var add = (function () {
        var counter = 0;
        return function () {return counter += 1;}
    })();
     
    add();
    add();
    add();
    // 计数器为 3
    
    //li节点的onclick事件都能正确的弹出当前被点击的li索引
     <ul id="testUL">
        <li> index = 0</li>
        <li> index = 1</li>
        <li> index = 2</li>
        <li> index = 3</li>
    </ul>
    <script type="text/javascript">
        var nodes = document.getElementsByTagName("li");
        for(i = 0;i<nodes.length;i+= 1){
            nodes[i].onclick = function(){
                console.log(i+1);//不用闭包的话,值每次都是4
            }(i);
        }
    </script>
    

    闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境。

    展开全文
  • js运动事件函数详解

    2020-12-29 01:02:45
    本文实例为大家分享了js运动事件函数,供大家参考,具体内容如下 HTML <h2 class=title>The Dog <p class=describe>Split between cat,belong to the cat family,cat,cat,is the world's more widely in the ...
  • JavaScript构造函数详解

    2020-10-23 02:04:50
    构造函数就是初始化一个实例对象,对象的prototype属性是继承一个实例对象。本文给大家分享javascript构造函数详解,对js构造函数相关知识感兴趣的朋友一起学习吧
  • Javascript函数详解

    2017-04-21 17:46:35
    javascript函数详解说明 js中的函数是对象,每个函数都是Function类型的实例,函数名只是一个指向函数对象的指针,不会和函数绑定。js函数声明方法如下: //方法一 function sum(num1,num2){ return num1+num2; } ...
  • ES6 JavaScript 函数详解

    千次阅读 2020-07-26 13:56:54
    ES6 JavaScript 函数详解1、函数概念1.1 函数语法1.1.1 示例1.2 函数表达式1.2.1 匿名函数1.2.2 有名字的函数表达式-11.2.3 有名字的函数表达式-21.2.4 有名字的函数表达式-3(递归函数)1.3 函数/匿名函数/函数...
  • Ext.js核心函数详解

    2019-07-22 21:20:25
    资源名称:Ext.js核心函数详解资源截图: 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。
  • js的回调函数详解

    2020-10-24 22:58:25
    本文主要介绍了个人对于javascript中回调函数的理解和使用方法及示例,需要的朋友可以参考下
  • JavaScript 函数详解JavaScript 函数详解 JavaScript 函数详解
  • js的对象与函数详解

    2020-10-17 12:11:46
    今天小编就为大家分享一篇关于js的对象与函数详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
  • JavaScript中数组也是比较常用的对象之一,数组是值的有序集合,本篇文章给大家分享Javascript中Array()数组函数详解,需要的朋友可以参考下
  • javascript回调函数详解

    2020-11-28 21:40:05
    在高级语言层出不穷的年代, 各个语言都号称有着一切皆为对象的自豪说法, 而 js 作为一门脚本语言却相对于java等传统面向对象语言有很大的不同之处, 除了 js 诡异的继承体系之外, 最...javascript最独特的就是 函数 作为
  • 主要为大家详细介绍了JavaScript 节流函数 Throttle,感兴趣的小伙伴们可以参考一下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 79,462
精华内容 31,784
关键字:

js函数详解