js函数:参数、作用域、匿名函数总结

news/2024/7/19 13:53:36 标签: js, 传值, 作用域

-------------------分割线----------------------

1.函数

返回值/参数

返回值:::::::::::::::::::::::::
js的函数在定义时不必指定返回值,而且任何函数都可以通过return随时返回值。
函数在执行完return之后停止并立即退出,因此return后面的代码永远不会执行。

    js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">sum(js-params">num1,num2){
        js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">return num1 + num2;
        alert(js-string" style="color: rgb(221, 17, 68);">"Hello World");  js-comment" style="color: rgb(153, 153, 136);">//这段代码永远不会执行
    }

参数:::::::::::::::
js函数不介意传递进来多少个参数,也不在乎传递进来的是什么参数类型。
参数在内部是由一个数组来表示的,函数接收的永远都是这个数组,函数体内部可以通过arguments对象来访问这个参数数组,从而可以获取传递给函数的每一个参数。

如下代码:

    js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">howManyArgs(js-params">){
        alert(js-built_in" style="color: rgb(0, 134, 179);">arguments.length);
    }
    
    howManyArgs(js-string" style="color: rgb(221, 17, 68);">"String",js-number" style="color: rgb(0, 128, 128);">45);  js-comment" style="color: rgb(153, 153, 136);">//2
    howManyArgs();             js-comment" style="color: rgb(153, 153, 136);">//0
    howManyArgs(js-number" style="color: rgb(0, 128, 128);">12);           js-comment" style="color: rgb(153, 153, 136);">//1

从上面的代码可以看出来,定义函数时没有给函数指定参数名字,而调用时依然可以传递进去任何数量和类型的参数,因此在js函数中:命名的参数只是提供便利,但不是必须的。理解这点很重要。

不完美的重载:::::::::::::::::
既然可以用arguments.length判断传入参数的个数,那么js函数也可以实现不完美的重载。
如下代码:

    js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">doAdd(js-params">){
        js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">if(js-built_in" style="color: rgb(0, 134, 179);">arguments.length == js-number" style="color: rgb(0, 128, 128);">1){
            alert(js-built_in" style="color: rgb(0, 134, 179);">arguments[js-number" style="color: rgb(0, 128, 128);">0] + js-number" style="color: rgb(0, 128, 128);">10);
        }
        js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">if(js-built_in" style="color: rgb(0, 134, 179);">arguments.length == js-number" style="color: rgb(0, 128, 128);">2){
            alert(js-built_in" style="color: rgb(0, 134, 179);">arguments[js-number" style="color: rgb(0, 128, 128);">0] + js-built_in" style="color: rgb(0, 134, 179);">arguments[js-number" style="color: rgb(0, 128, 128);">1]);
        }
    }
    
    doAdd(js-number" style="color: rgb(0, 128, 128);">10);   js-comment" style="color: rgb(153, 153, 136);">//20
    doAdd(js-number" style="color: rgb(0, 128, 128);">30,js-number" style="color: rgb(0, 128, 128);">20);    js-comment" style="color: rgb(153, 153, 136);">//50

arguments[i]和对应命名参数的关系:::::::::::::::::
看如下代码:

    js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">doAdd(js-params">num1,num2){
        js-built_in" style="color: rgb(0, 134, 179);">arguments[js-number" style="color: rgb(0, 128, 128);">1] = js-number" style="color: rgb(0, 128, 128);">10;          js-comment" style="color: rgb(153, 153, 136);">//重写第二个参数
        alert(js-built_in" style="color: rgb(0, 134, 179);">arguments[js-number" style="color: rgb(0, 128, 128);">0] + num2);
    }

arguments对象中的值会自动反映到对应的命名参数,但是读取这两个值不会访问相同的内存空间,
修改命名参数并不会改变arguments中对应的值
arguments对象长度是由调用函数时传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。

2.传递参数

js中所有的函数都是按值传递的。
在向参数传递基本类型时,被传递的值会被复制给一个局部变量。
在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。

来看几个例子:

    js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">addTen(js-params">num){
        num += js-number" style="color: rgb(0, 128, 128);">10;
        js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">return num;
    }
    js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var count = js-number" style="color: rgb(0, 128, 128);">20;
    js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var result = addTen(count);
    alert(count);       js-comment" style="color: rgb(153, 153, 136);">//20,没有变化
    alert(result);      js-comment" style="color: rgb(153, 153, 136);">//30

count传递给参数num,函数内部num做了修改,但是没有反映到count上。

    js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">setName(js-params">obj){
        obj.name = js-string" style="color: rgb(221, 17, 68);">"Jack";
    }
    js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var person = js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">new js-built_in" style="color: rgb(0, 134, 179);">Object();
    setName(person);
    alert(person.name);     js-comment" style="color: rgb(153, 153, 136);">//Jack

这个例子很容易让人觉得,引用类型做为函数参数传递是按引用传递的,因为局部的修改:obj.name = "Jack",反映在了全局的作用域上:person.name,事实上并不是如此。
事实上:我们创建了一个对象,并把它保存在person变量中,然后把person当做参数传递到setName()函数中复制给了obj,在这个函数内部obj和person引用的是同一个对象。

再看一个例子:

    js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">setName(js-params">obj){
        obj.name = js-string" style="color: rgb(221, 17, 68);">"Jack";
        obj = js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">new js-built_in" style="color: rgb(0, 134, 179);">Object();
        obj.name = js-string" style="color: rgb(221, 17, 68);">"Rose";
    }
    js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var person = js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">new js-built_in" style="color: rgb(0, 134, 179);">Object();
    setName(person);
    alert(person.name);       js-comment" style="color: rgb(153, 153, 136);">//Jack
    

这个例子中在setName()函数中,为obj重新定义了一个对象,另一行代码为该对象定义了一个带有不同值的name属性。如果person传递给函数setName()之后是按引用传递的,那么对obj.name的修改就会反映到person.name上,事实上person.name依然是Jack。
当在函数内部重写obj时,这个变量的引用就是一个局部变量了,这个局部变量在函数执行完毕后立即销毁。

3.执行环境及作用域

定义什么的太多了就不写了,直接上代码

    js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var color = js-string" style="color: rgb(221, 17, 68);">"blue";
    js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">changeColor(js-params">){
        js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var anotherColor = js-string" style="color: rgb(221, 17, 68);">"red";
        js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">swapColors(js-params">){
            js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var tempColor = anotherColor;
            anotherColor = color;
            color = tempColor;
            js-comment" style="color: rgb(153, 153, 136);">//这里可以访问 color,anotherColor 和tempColor
        }
        
        swapColor();
        //这里可以访问color, anotherColor
    }
    
    changeColor();  js-comment" style="color: rgb(153, 153, 136);">//这里只能访问color

上面代码中有三个执行环境:全局环境、changeColor()的局部、和swapColors()的局部环境。
全局环境中有一个color变量和changeColor()函数。
changeColor()的局部环境中有一个名为anotherColor的变量和一个swapColors()的函数,但是它也可以访问全局环境中的变量color
swapColors()局部环境中有一个变量tempColor,只能在这个环境中访问到。

无论是全局环境还是changeColor()的局部环境都无权访问tempColor,在swapColors()内部可以访问其他两个环境中的所有变量,因为那两个环境是它的父执行环境。

总结:内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数,每个环境内部没有这个变量或者函数时,都可以向上搜索变量和函数名,直到找到为止。

没有块级作用域

java等语言话括号括起来的代码块都有自己的作用域,但是js中总有例外,看下面代码:

    js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">if(js-literal" style="color: rgb(0, 128, 128);">true){
        js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var color = js-string" style="color: rgb(221, 17, 68);">"blue";
    }
    alert(color);    js-comment" style="color: rgb(153, 153, 136);">//blue

这里是在if语句中定义了一个变量color,和作用域函数里面定义变量的例子不同,在if语句中的变量声明将添加到当前的执行环境中,看下面for循环的例子:

    js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">for(js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var i = js-number" style="color: rgb(0, 128, 128);">0; i<js-number" style="color: rgb(0, 128, 128);">10; i++){
        doSomething(i);
    }
    alert(i);   js-comment" style="color: rgb(153, 153, 136);">//10

对于js,由for语句创建的变量i即使在for循环执行结束后,也依旧会存在于循环外部的执行环境。

4.匿名函数

看下面例子:

      js-built_in" style="color: rgb(0, 134, 179);">window.onload = 
           js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function(js-params">){
               alert(js-string" style="color: rgb(221, 17, 68);">"Hello World");
           };
           
       js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">var person = {
           js-attr">callName: js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function(js-params">){
               alert(js-string" style="color: rgb(221, 17, 68);">"My name is Jack");
           }
       };
       person.callName();  
           
       setTimeout(
           js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function(js-params">){alert(js-string" style="color: rgb(221, 17, 68);">"Hello World");},
           js-number" style="color: rgb(0, 128, 128);">500);

1.首先,为load事件创建了一个函数做为事件处理程序,不会直接调用这个函数,而是在页面加载时自动调用,所以没必要为这个函数命名,像这样:

    js-function">js-keyword" style="color: rgb(51, 51, 51); font-weight: bold;">function js-title" style="color: rgb(153, 0, 0); font-weight: bold;">sayHello(js-params">){alert(js-string" style="color: rgb(221, 17, 68);">"Hello World");};
    js-built_in" style="color: rgb(0, 134, 179);">window.onload = sayHello;

2.声明了一个匿名函数,做为person对象的一个属性callName,可以通过该属性来调用这个方法:
如:person.callName();

3.将匿名函数做为回调函数传递给另外一个函数,代码中将匿名函数做为一个参数传递给window对象的setTimeout()方法,该方法将在半秒后被调用。

-------------------------------------------------------end--------------------------------------------------------


http://www.niftyadmin.cn/n/798026.html

相关文章

洛谷P1576 最小花费

坑题&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;大下午yyf给我发了这么一道题&#xff0c;初看还没有思路。&#xff08;第一次这么认真的写图论 blog&#xff09;题面&#xff1a; 在n个人中&#xff0c;某些人的银行账号之间可以互相转账。这些人之间转账…

CSS样式选择器分层规则

CSS三大特性—— 继承、 优先级和层叠。继承&#xff1a;即子类元素继承父类的样式;优先级&#xff1a;是指不同类别样式的权重比较;层叠&#xff1a;是说当数量相同时&#xff0c;通过层叠(后者覆盖前者)的样式。css选择符分类  首先来看一下css选择符(css选择器)有哪些?1.…

网页中图片去色问题

网页中图片去色问题 网页中经常需要一种js效果&#xff0c;就是鼠标经过某张图片&#xff0c;图片去色。为了不加载两张图片&#xff08;一张彩色和一张灰色&#xff09;&#xff0c;在网上找到了一些方法。 方案一&#xff1a;使用grayscale.js 可以使用grayscale.js来实现…

Life Forms POJ - 3294(不小于k个字符串中的最长子串)

题意&#xff1a; 求不小于字符串一半长度个字符串中的最长字串 解析&#xff1a; 论文题例11 将n个字符串连起来&#xff0c;中间用不相同的且没有出现在字符串中的字符隔开&#xff0c; 求后缀数组&#xff0c; 然后二分答案变为判定性问题&#xff0c; 然后判断每组的后缀是…

select中option改变时跳转到其他页面

html代码&#xff1a; <div class"friend_link"> <select οnchangembar(this) name"select"> <option selected>友情链接</option> <opti…

MySQL新建用户无法登录

Access denied for user xiaoqiulocalhost (using password :NO) resolution: 删除匿名用户&#xff08;mysql.user表中user为空的用户&#xff09;delete from user where mysql.user; 生效(更改了用户表&#xff0c;用户的权限都需要执行&#xff0c;否则需要重启MySQL服务)…

mysql根据某一张表的字段更新另一张表的字段

&#xff01;FIND_IN_SET()取反表示某个字符串不存在另外一个字符串中 -- 基金经理&#xff08;根据findinfo表中的im_ids更新&#xff09; UPDATE user u INNER JOIN fundinfo f ON FIND_IN_SET(u.user_id,f.im_ids) AND !FIND_IN_SET(1,u.jobs)SET u.jobs CASE WHEN (ISNU…

实现HttpServlet HttpURLConnect获取页面

1.模拟浏览器获取http://www.51job.com的流 2.将获取的流用resp.writ() 写入到resp中 3.浏览器输入localhost&#xff1a;8080将会看到51job的界面。 public class ServletDem extends HttpServlet {Overrideprotected void doPost(HttpServletRequest req, HttpServletRespons…