zoukankan      html  css  js  c++  java
  • 函数

    搜狗:hanshu韩束  digui递归 jianjiediaoyong间接调用 lianshidiaoyong链式调用 arguments参数 return 返回值   gouzaohanshu构造函数   

    要使用面向对象编程,不要面向过程编程。

    对象:就是任意值的集合。

    使用花括号表示: {  ...  }  如果没有值,那么就表示空对象

    对象:任意值的集合

    创建对象的方式一:字面量创建方式

    //创建一个喵星人对象,花括号里面是他的属性(方法是属性的另一种别称),属性都是以键值对存在的,属性之间用逗号隔开

    <script>
      var cat={ 
        "name":"zheng",
        "age":18,
        "family":["father","mother"],//属性可以是数组
        "speak":function(){//属性可以是函数
           console.log("喵喵!");
        }
        "friend":{//属性还可以是对象
          "name":"jerry",
          "age":19
        }
      };
    </script>

    --------

    创建对象的方式二:构造函数创建法

    var obj=new Object();

    --------

    创建对象的方式二:ECMAScript 5版本提供的创建方法(存在兼容性问题)

    Object.create();

    -------

    对象属性的访问,修改,赋值,增加等操作

    对上面喵星人对象增删改查

    函数的定义, 普通函数 构造函数 本质 作为数据,递归, 链式调用,间接调用, arguments参数 return返回值
    函数的定义:
    //函数:一次申明,四次使用(调用)
    //函数分为:命名函数(有函数名称的函数) 和 匿名函数(没有名称的函数)
    //命名函数
    function add(a,b){
    //函数体,属于局部作用域
    return a+b;// return 表示函数一死,可以烧纸,return后面的是函数返回值
    console.log("return 后面的代码永远不会执行。");
    };
    add(3,8);
    //匿名函数
    window.onload=function(){
    //函数体,属于局部作用域
    alert("hellow");
    };

    //------函数执行过程-------
    function add(a,b){
    var result=a+b;
    return result;
    }
    /*
    -------上述函数每次被调用时都会发生的事情-------
    1,浏览器全局对象window下面创建一个add方法
    2,在add方法下面创建一个局部作用域
    3,在局部作用域中创建变量 a=undefined , b=undefined , result=undefined
    4,执行函数add(1,2);
    5,给每个变量赋值 a=1 , b=2 , result=3
    6,函数执行完毕,第一个要做的就是删除 add方法里面的局部作用域以及里面的变量,所以在外面无法访问里面的变量*/

    //------------------------------------------
    //------为什么要使用函数-------
    /*1,复用代码
    2,易于修改,维护
    3,增加程序的可读性*/

    //以下函数对可读性的优化
    //下面代码每次看的话都要分析如何实现,怎么判断春夏秋冬,
    //每次查看都要分析,细节暴露太多了,所以可读性不是很强。这里就需要封装函数了
    function doThings(month){
    if (month>=3 && month<=5) {
    //踏春
    }else if(month>=6 && month<=8){
    //游泳
    }else if(month>=9 && month<=11){
    //秋收
    }else{
    //冬天睡觉
    }
    }
    //什么时候可以使用函数?
    //1,代码中有重复代码,或者有相似代码时,需要封装函数。
    //2,功能实现时有很多代码,细节暴露太多,可读性很差时,就需要封装函数。
    //
    //把上面函数封装成可阅读性比较强,不暴露细节,直接读函数名称就可以知道做什么?
    //在实现比较强的阅读性时,不要暴露具体实现的函数过程,直接一个函数名即可。
    function isSpring(month){
    return month>=3 && month<=5;
    }
    function isSummer(month){
    return month>=6 && month<=8;
    }
    function isAutumn(month){
    return month>=9 && month<=11;
    }
    function isWinter(month){
    return month>12 && month<=2
    }
    function doThings(month){
    if (isSpring()) {
    //踏春
    }else if(isSummer()){
    //游泳
    }else if(isAutumn()){
    //秋收
    }else{
    //冬天睡觉
    }
    }
    </script>
    <script>
    //-------------函数的本质---------------
    /*函数二象性
    1,函数可以调用
    2,函数其实是对象:{}
    定义对象的方式:
    a,字面量的方式: var a={...}
    b,构造函数的方式: var obj=new Object();
    var arr=new Array();
    添加属性和方法:
    var person={};
    person.name="zheng";
    person.setName=function(name){
    this.name=name;
    }

    var Person(arguments){
    name:"zheng",
    age:"18",
    addredd:"China"
    }
    定义函数的方式:
    a: function Person(arguments){...}
    b: var fn = new Person(a,b,c);
    */
    //-----以下是对象的操作-------
    /*var a={
    "name":"zheng",
    "age":18,
    "love":"you"
    }
    a.name="love";
    a.setAge=function(age){
    return a.age=age;
    }
    console.log(a.name);
    console.log(a.setAge(88));
    */
    //-----以下是函数的操作-------
    function add(a,b){
    age="zheng";
    //设置age属性
    return a+b
    }
    console.log(add.name);//返回 add,这里name是函数关键字 表示返回当前函数的函数名称
    //给函数add设置age属性
    add.setage=function(age){
    this.age=age;
    }
    add.age="love";//重新设置 age 属性值
    console.log(add.age);//返回 love
    add.setage("you");//修改age的值
    console.log(add.age);//返回 you
    console.log(add(1,3));//输出 4
    console.log(add);//输出add函数本体

    //给add函数对象添加一个start函数
    add.start=function(){
    console.log("hello");
    }
    add.start();//执行start方法,输出hello
    </script>

    <script>
    //---------函数作为数据值来使用----------
    //值的集合是数组,键值对出现的就是对象
    //值的集合是数组
    var arr=[1,"a",function(){}];
    for(var p in arr){
    console.log(p);//输出的索引值 0 1 2
    console.log(arr[p]);//arr[p] 输出的是arr中的对象
    }
    //键值对是对象
    var array={"a":"love","b":"you","c":function(){}};
    for(var p in array){
    console.log(p);//输出array的属性
    console.log(array[p]);//输出array的属性值
    }

    //---------函数作为参数来使用----------
    //这里的函数作为参数使用
    // setTimeout(function(){alert(1)},1000);//一秒钟后跳出弹窗
    setTimeout(fn,1000);//函数名称表示函数本体,fn()表示立即执行该函数本体。
    function fn(){
    alert(1);
    }

    //---------函数作为返回值来使用----------
    function add(){
    return function(){alert(2)};
    }
    /*var newFn=add();//返回 return 后面的匿名函数本体
    newFn();//函数本体后面添加小括号,表示立即执行该函数
    */
    add();//得到 function(){alert(2)}; 这个返回值,是一个匿名函数本体。
    add()();//表示执行匿名函数本体
    </script>

    //========函数的三种定义方式============
    //-----第一,二种函数定义方式:------
    字面量:
    function声明:
    function add(){...body...} //这里可以不要使用分号,这是函数
    调用: add();

    var赋值表达式:
    var add=function(){...body...};//这里一定要使用分号,这是语句
    调用: add();

    var add=function fn(){...}
    add(); //只能在外部调用,不能再函数体内调用
    fn();//这么调用是错误的,fn属于局部变量,不可以在外面调用

    //-----第三种函数定义方式:------
    构造函数:
    申明:var fn=new Function("a","b","return a+b;");
    调用:fn();

    //============函数定义的区别===============
    字面量于构造函数的区别:
    1,字面量定义:直观,简洁,方便书写
    2,构造函数:笨重,复杂,效率低(解析字符串是变量是还函数体,实例化构造函数,函数体多的时候很难看)
    构造函数的定义方式复杂难懂,效率较低,一般不用它来定义函数
    使用构造函数的方式定义函数,不会被提前,函数调用必须在定义之后

    声明方式:var声明方式 和 function声明方式 的区别:
    1,使用var声明方式 是一个条语句,不会申明提前,所以最后要加分号;
    2,使用function声明方式 是一个函数,会被申明提前,所以最后不要加分号。
    3,预解析的过程的不同,如下代码:
    <script>
    //这里是预解析的时候已经定义了function add(),
    //所以可以提前输出:function add(){return "a";}
    //使用function声明的方式定义函数,声明会被提前,函数调用在定义前后都无所谓
    console.log(add());//输出 a
    function add(){
    return "a";
    }
    //-----
    console.log(add());
    var add=function(){return "a";}
    //预解析:
    //var add=nudefined
    //预解析完了再逐行执行代码。
    //所以add是一个变量,不能当做函数执行add();
    //-----
    var ad=function(){return "b";}
    console.log(ad());
    //预解析:
    //var ad=undefined;
    //预解析完成,再重头开始逐行执行代码
    //给 ad 进行赋值 ad=function(){return "b";}
    //所以这里的 ad是一个函数 ad();
    </script>

    //使用时怎么选择函数
    //构造函数 傻大黑粗效率低,一般不建议使用
    //var 和 function 两种都差不多,一般都是根据团队风格进行选择的。
    ======================
    <script>
    //使用构造函数实现:21 * 32 + 24 / 3 - 5
    var multiply=new Function("a","b", "return a*b;");//所有参数都必须使用字符串的形式,包括函数体。
    // console.log(multiply("21","32"));//调用该方法时,只需要带参数即可,函数体不用写。
    var divide=new Function("a","b","return a/b;");//所有参数都必须使用字符串的形式,包括函数体。
    // console.log(divide("24","3"));//调用该方法时,只需要带参数即可,函数体不用写。
    var substract=new Function("a","b","return a-b;");//所有参数都必须使用字符串的形式,包括函数体。
    // console.log(substract("333","222"));//调用该方法时,只需要带参数即可,函数体不用写。

    //等价下行:var add=new Function("a","b","return +a + +b;");//+a,+b表示取正,-a表示取负,!表示取反
    var add=new Function("a","b","return parseInt(a)+parseInt(b);");//所有参数都必须使用字符串的形式,包括函数体。
    // console.log(add("22","33"));//调用该方法时,只需要带参数即可,函数体不用写。
    var mul=multiply("21","32");//返回:672
    var divide=divide("24","3");//返回:8
    var add=add(mul,divide);
    console.log(add);//返回 680
    var sub=substract(add,"5"); //返回 675
    console.log(sub);//返回 675
    </script>

    //========函数定义的位置============
    //具体哪里可以访问,请使用搜狗:zuoyongyu:作用域的知识
    1,全局作用域
    function add(){...} 在哪里都可以调用

    2,函数作用域
    //fn1()函数只能在substract函数中进行访问,不可以在全局中访问。
    function substract(){
    fn1();//可以访问
    function fn1(){
    fn1();//可以访问
    function fn3(){
    fn1();//可以访问
    }
    }
    fn1();//可以访问
    function fn2(){
    fn1();//可以访问
    }
    }

    3,不建议在代码块中定义函数:
    在javascript中不存在 if/for代码块的作用域,里面的函数预解析为window全局作用域
    if(true){
    function add(argument){...}
    }else{
    function substract(argument){...}
    }
    //函数预解析时就提前声明了:
    window下面的属性及其方法:
    function add(argument){...}
    function abstract(argument){...}
    再逐行执行代码

    ------如果为真,就可以执行add()函数,否则就可以执行substract()函数-------
    if(true){
    var add=function(){...};
    }else{
    var substract=function(){...};
    }
    函数是在预解析之后再赋值的:
    var add=undefined;
    var substract=undefined;
    再逐行执行代码
    ------
    B:JS中没有块级作用域,所以不会在if中发生预解析,在外部预解析的时候,if中声明的所有函数都会被提前,所以无法达到按需定义的目的。
    C:方法的调用必须指定对象,一般通过 对象.函数名() 的方式调用
    D:内部函数可以访问外部函数的变量(作用域链的机制)
    ------

    4,函数作为对象的属性值:
    <script>
    var person={
    name:"zheng",
    age:18,
    address:"China",
    setAddress:function(address){
    this.address=address;
    }
    };
    console.log(person.name);//输出:zheng
    console.log(person.name="liang");//输出:liang
    person.setName=function(name){this.name=name;}//添加设置修改姓名的方法
    person.setName("zhu");//重新把name设置为:zhu
    console.log(person.name);//输出:zhu
    console.log(person.address);//输出:China
    person.setAddress("American");//重新把address设置为:American
    console.log(person.address);//输出:American
    </script>
    <script>
    //如果输入两个数字类型,就相加,否则提示请输入数字类型的参数
    var add=function(a,b){
    if (isNumber(a) && isNumber(b)) {
    return parseInt(a)+parseInt(b);//等价:return +a + +b; 一元运算符: +取正,-取负 !取反
    }else{
    return "请输入数字类型的参数";
    }
    }
    function isNumber(a){
    return isNaN(a)?false:true;//如果isNaN(a)=true,那么返回false ,否则返回true
    }
    console.log(add("333","bbb"));
    console.log("33","22");
    </script>

    //------函数的调用------
    <script>
    //命名函数的调用
    function add(a,b){
    return a*b;
    }
    add();//命名函数的调用

    //匿名函数的调用
    //1,使用 变量名+() 进行调用
    var add=function(a,b){
    return a*b;
    }
    add();//

    //2,匿名函数自我执行
    /*function(){console.log(1);}();
    在预解析时:function后面一定要跟上一个函数名称,
    但这里没有函数名称,所以会报错。解决办法如下:*/

    //匿名函数自执行方法一:
    //把匿名函数自我执行后的结果赋值给变量a即可,函数名称+()表示立即执行函数本体。
    /*var a =function(a,b){return 3*4}();
    console.log(a);

    //匿名函数自执行方法二,三效果一模一样
    //匿名函数自执行方法二:
    (function(){console.log(2)}());
    //匿名函数自执行方法三:
    (function(){console.log(3)})()
    //匿名函数自执行方法四:
    //!表示取反,+表示取正,-表示取负数,只要不让匿名函数的function打头,那就可以匿名函数自执行
    !function(){console.log(4)}();
    +function(){console.log(4)}();
    -function(){console.log(4)}();
    !+~-function(){console.log(4)}();
    //匿名函数自执行方法五:
    console.log(function(){return 5;}());*/

    <script>
    (function(){
    function add(a,b){
    return a+b;
    }
    console.log(add(1,3));//而这里返回的4
    })();
    console.log(add(1,3));//这里调用报错,因为add函数是在匿名函数的作用域内,不可以当做全局变量来使用
    </script>

    //------递归函数------
    5的阶乘:5*4*3*2*1
    //递归函数,类似于循环
    //1,一定有一个终结点退出函数执行
    //2,同理一直进行自我调用
    <script>
    function factorial(num){
    if (num<=1) return 1;
    return num*factorial(num-1);
    }
    console.log(factorial(5));

    //上面的递归等同于下面的函数:
    /*5*4*3*2*1
    5!
    5*4!
    5*4*3!*/
    var sum=1;
    function a(num){
    var i=1;
    while (i<=num) {
    sum=sum*i;
    i++;
    }
    return sum;
    }
    console.log(a(5));
    </script>

    <script>
    //求阶乘,这里没有终止条件,值域溢出,所以死循环
    function factorial(num){
    return num*factorial(num-1);
    }
    factorial(5);
    </script>

    <!-- 对象调用方法 -->
    <script>
    var operation={
    //加法
    add:function(a,b){
    return a+b;
    },
    //减法
    substract:function(a,b){
    return a-b;
    },
    //乘法
    multiply:function(a,b){
    return a*b;
    },
    //除法
    divide:function(a,b){
    return a/b;
    },
    //使用不合法的字符串时,只能使用:对象["@"]()运行函数
    "@":function(){
    console.log("999");
    alert("1");
    }
    }
    //使用合法字符串命名,可以使用以下两种方法进行调用函数
    console.log(operation["add"](3,6));
    console.log(operation.add(3,6));
    //使用不合法的字符串时,只能使用: 对象["@"]() 运行函数
    operation["@"]();

    var key="add";
    // []方括号中,有双引号的表示字符串,没有双引号的表示变量,谨记
    console.log(operation[key](1,3));//返回:4 这里的是变量:key="add"
    console.log(operation["key"]());// 返回:key 这里的key是对象operation中的方法。

    //-------链式调用方法-------
    // $("p").html("love you forever").css("backgrond","red")...
    var operation={
    //加法
    add:function(a,b){
    console.log(a+b);
    return this;//返回的是operation对象
    },
    //减法
    substract:function(a,b){
    console.log(a-b);
    return this;//返回的是operation对象
    }
    }
    // operation.add(2,3); 返回的是 operation 对象
    // operation.substract; 返回的是 operation 对象
    //所以可以使用下面的链式调用,否则是不可以的。
    operation.add(2,3).substract(33,3);
    </script>
    <script>
    //这是需要鼠标点击才可以调用点击方法
    document.onclick=function(){
    alert("1");
    }
    //不用点击直接调用方法,任意方法直接在方法名称后面添加 (),就会立马执行该方法
    document.onclick();
    </script>
    <script>
    //什么是构造函数
    //普通函数有return 则返回 return后面的值,如果没有return,则返回undefined
    //函数名称小写用于区分:普通函数,不是严格规定
    //函数名称大写的用于区分:构造函数,不是严格规定
    function add(a,b){return a+b;}
    //普通函数的调用:函数名称()
    add(3,4);

    // function Person(){...}
    //new Person() 用于实例化构造函数
    // var Obj=new Person();
    //Person();这么调用就是普通函数
    //Array();这是普通函数
    //Object();这是普通函数
    console.log(Array());//返回 []
    console.log(Object());//返回 {}
    var arr=new Array();//实例化一个数组 返回的永远是对象
    var obj=new Object();//实例化一个对象 返回的永远是对象

    ////-------实例化一个Person--------
    /////构造函数,顾名思义:被构造的对象也必须是一个函数。
    function Person(){
    this.name="zheng";//这里一定要使用this.属性,否则后面输出都是undefined.
    this.age=18;//这里一定要使用this.属性,否则后面输出都是undefined.
    var address="China";//实例化后,输出为undefined
    }
    var xm=new Person();//实例化一个Person对象
    console.log(xm);//Person {name: "zheng", age: 18} address定义错误不是属性
    console.log(xm.name);//输出 zheng
    console.log(xm.age);//输出 18
    console.log(xm.address);//输出 undefined
    </script>

    <script>
    //创建一个空的Person对象
    var Person=function(){};
    //实例化Person对象
    var per=new Person();
    //给对象添加属性
    per.name="zheng";
    per.age="18";
    per.sex="male";
    //实例化一个数组
    var arr=new Array();
    //给数组arr添加属性
    arr[0]="zheng";
    arr[1]="liang";
    //遍历per对象并输出属性及其属性值
    for(var p in per){
    console.log(p+":"+per[p]);
    }
    //遍历数组arr并输出值
    for (var i = 0; i < arr.length; i++) {
    console.log(arr[i]);
    }
    </script>
    <script>
    //------间接调用--------
    var name="xm";
    var person={};
    person.name="xh";
    person.getName=function(){
    return this.name;
    }
    console.log(person.getName());//输出:xh
    //这里的window用于改变person.getName里面的this变成:window,即返回window.name的值
    console.log(person.getName.call(window));//输出:xm
    //这里的window用于改变person.getName里面的this变成:window,即返回window.name的值
    console.log(person.getName.apply(window));//输出:xm

    var arr=[2,5];
    function add(a,b){
    return a+b;
    }
    //直接调用
    console.log(add(3,6));
    //使用了间接调用,call(指定作用域对象,argument1,argumen2...)
    console.log(add.call(window,2,5));
    //这里间接调用了window下面的arr的数组值, apply(指定作用域对象,数组)
    console.log(add.apply(window,arr));
    //间接调用:
    //1,对象没有call和apply方法,只有函数有
    //2,apply可以将数组和类数组一次性的传递进函数中,call只能一个一个的传
    </script>
    //------arguments 参数------
    //参数分为:实参,形参
    1,当参数为基本数据类型时,只是进行了复制操作,不不会修改原来的值。
    2,当参数为引用类型时,因为两个引用地址相同,指向同一个值。如果修改其中一个,另一个也会被修改。
    //三种情况:
    1,实参=形参
    <script>
    //函数中的参数:形式参数 实际参数
    function add(a,b){//这里的 a,b是形式参数,占位符的作用
    return a+b;
    }
    add(3,8);//这里的3 ,8 是实际参数
    //本质上就是复制一个副本: 形参=实参 ,对于原来的值是不改变的。
    // var a=3; var b=8;

    //参数为对象时,参数为引用类型,那么传递的是地址。修改一个同时也会修改另一个
    var person={};
    var setName=function(obj){//这里的参数是对象,给指定对象设置name属性
    obj.name="zheng";
    }
    setName(person);//这里的person是对象,给person对象设置name属性
    console.log(person.name);
    </script>

    2,实参<形参
    <script>
    //求数的幂 Math.pow(base,power);
    function pow(base,power){
    return Math.pow(base,power);
    }
    console.log(pow(3,4));//返回 81
    console.log(pow(3,2));//返回 9

    function pow(base,power){
    // if (!power) power=2;//如果b为空:!power=true,如果b不存在为真的,那么返回b=2.
    //短路操作
    power=power || 2;//或逻辑 一个为真即为真 如果power=power返回true,那么power=power,否则b=2;
    return Math.pow(base,power);
    }
    console.log(pow(4));//返回 16
    console.log(pow(3));//返回 9

    //$("p");//默认省略document
    //在JQuery中的参数: $("p",document):表示在文档中查找P标签。
    //也可指定某个对象:$("p",document.getElementById("box")),
    //指定id="box"的对象下面查找p标签。
    </script>

    3,实参>形参
    <script>
    function add(){
    //任何函数都有返回值,返回return后面的值,如果省略return或者return后面没有值,则返回undefined
    if (arguments.length==0) return;
    var sum=0;
    for (var i = 0; i < arguments.length; i++) {
    sum+=arguments[i];
    }
    return sum;
    }
    console.log(add()); // 返回 undefined
    console.log(add(1,3,4));//返回 8
    </script>
    <script>
    // 输入任意个数字参数,输出最小值
    function mix(){
    var len=arguments.length;
    if (len==0) return;
    if (len==1) return arguments[0];
    var mi=0;
    for (var i = 1; i < len; i++) {
    //思路决定出路
    // 这里是精华所在,前后对比,把较小的一个赋值给arguments[i]
    arguments[i]= arguments[i-1]<arguments[i]?arguments[i-1]:arguments[i];
    mi = arguments[i];
    }
    return mi;
    }
    console.log(mix(1,3,444,2,5245,7373,2452,-11,-23432,-234,-245));
    console.log(mix());
    console.log(mix(888))
    </script>

    //arguments
    //参数是每个函数都有的,是一个局部变量
    //类数组对象,但不是数组的实例。可以使用arguments[index]进行取值.
    <script>
    //合法标识符:不能以数字,关键字,保留字开头,以字母,数字,下划线组成的字符串;
    //这里arguments的索引是 "0" 到 "5" ,数字是不合法的标识符,所以只能使用双引号。
    //以下就是类数组对象:
    var arguments={
    "0":"argument1",
    "1":"argument2",
    "2":"argument3",
    "3":"argument4",
    "4":"argument5",
    "5":"argument6"
    };
    //遍历arguments类数组对象
    for(var p in arguments){
    console.log(p+":"+arguments[p]);
    }

    //1.对象的长度不能用.length获取,用js原生的Object.keys可以获取到
    console.log(arguments.length);//返回 undefined
    var keys=Object.keys(arguments)//使用原生Object.keys,获取键值对中键的集合,都是数组
    var values=Object.values(arguments)//使用原生Object.values,获取键值对中值的集合,都是数组
    console.log(keys.length);//两种都可以获得对象的长度
    console.log(values.length);//两种都可以获得对象的长度
    //但是,如果arguments作为函数中的参数,是可以通过arguments.length获得实际参数个数。
    //函数是一个特殊对象,也可以通过add.length 获得形式参数个数
    <script>
    function add(a,b,c){
    console.log(arguments.length);//返回 5 调用函数是写入的实际参数
    console.log(add.length);//返回 3,定函数时,定义的形式参数
    console.log(arguments.callee.length);//返回 3 形式参数,函数固定的形式参数长度
    return +a + +b + +c;//一元运算符,+取正,-取负,!取反
    }
    // console.log(add(1,3,5));
    console.log(add(1,3,6,7,8));//返回:10 只对前面3个参数进行相加

    </script>
    //------
    function fn(arguments){
    console.log(argument);
    function fn1(arguments){
    console.log(argument);
    }
    fn1(2);//输出2
    }
    fn(1);//输出1
    //arguments是每个函数中独有的,不同作用域不同
    //预解析:
    /*fn函数作用域:
    var argument=undefined;
    fn1函数作用:
    var argument=undefined;
    */
    </script>
    //--------
    // "use strict" //表示使用严格模式
    // var num=1;//这样定义num变正确
    // num=1;//这样定义num变就会报错
    </script>
    <script>
    //判断传入参数是否等于实际参数
    function add(a,b){
    //console.log(arguments.length);//返回 5实际参数,我们实际传入的参数
    //console.log(arguments.callee.length);//返回 2 形式参数,函数固定的形式参数
    // console.log(add.length);返回 2 //形式参数,函数固定的形式参数,可以在函数外面进行调用
    if (arguments.length!==add.length) throw new Error("请输入:"+add.length+"个参数");
    return a+b;
    }
    // console.log(add(2,4));//返回 6
    console.log(add(1,3,4,5,6));//参数不对,参数过多。返回:text2.html:13 Uncaught Error: 请输入:2个参数
    </script>
    //---------------
    <body>
    <p id="test" style="background-color: red; color: blue;">我是一个段落!</p>
    <script type="text/javascript">
    //在使用参数给对象设置CSS属性时,都是用p.style[property]=value,这样绝对没错
    //如果使用p.style.property=value。读取时使用,设置时有可能会报错。
    var p=document.getElementById('test');
    function css(value,property){//必要参数一定要放在第一个,可传可不传放在后面
    if (arguments.length<=0 || arguments.length>=3) throw new Error("请输入:"+arguments.length+"参数");
    if (property==undefined) p.style.backgroundColor=value;
    if (arguments.length==2) p.style[property]=value;
    }
    css("orange");//第二个参数省略,默认 property=undefined
    // css("green","backgroundColor");
    </script>
    </body>
    <script type="text/javascript">
    //-----什么可以当做变量-------
    //1,什么都不传
    var a=2;
    function fn(){
    function(){alert(a);}
    }
    //2,数字
    function fn(num){console.log(num);}
    fn(2);
    //3,字符串
    //4,boolean
    function a(){}
    function b(){}
    //如果传进来的是布尔值,一定使用要把细节封装成a,b函数。经验之谈。
    function fn(boolean){
    if (true) {
    a();
    }else{
    b();
    }
    }
    //5,undefined
    function add(a,b){
    if (b==undefined) return a;
    return a+b;
    }
    console.log(add(6,undefined));//返回 NaN,非数字
    function pow(bace,power){
    //短路操作,如果power=power=true则power=power power=undefined=false 则power=2。
    power=power || 2;
    return Math.pow(bace,power);
    }
    console.log(pow(3,6));
    //6,null
    //以上都是单个参数传递
    //
    //7,传多个参数,如数组:[1,2,3,4,5]
    $.each([1,2,3,4,5], function(index, val) {
    console.log(index);
    console.log(val);
    });
    for (var i = 0; i < [1,2,3,4,5].length; i++) {
    console.log(index);
    console.log(val);
    }
    //8,传对象:{"a":"1","b":"2","c":"3"}
    $.each({"a":"1","b":"2","c":"3"}, function(index, val) {
    console.log(index);
    console.log(val);
    });

    //下面代码使用对象作为参数进行代码优化:
    function setPerson(name,sex,age,add,phone){
    var person={};
    person.name=name;
    person.sex=sex;
    person.age=age;
    person.add=add;
    person.phone=phone;
    }
    //可读性,可写性不强,很容易弄错参数顺序导致错误,所以下面可以使用对象代替
    setPerson("zhengl","male",18,"中国China","182...");

    //当参数超过三个或者三个以上,建议适用对象进行代码优化如下:
    var person={};
    function setPerson(obj){
    person.name=obj.name || "xh";//如果没有设置该属性,则设置一个默认值
    person.age=obj.age || 18;//如果没有设置该属性,则设置一个默认值
    person.add=obj.add || "中国China";//如果没有设置该属性,则设置一个默认值
    person.sex=obj.sex || "male";//如果没有设置该属性,则设置一个默认值
    person.phone=obj.phone || "110";//如果没有设置该属性,则设置一个默认值
    }
    //经过代码优化:对象属性不用按顺序进行书写,甚至不写都不会报错。
    setPerson({
    name:"zheng",
    age:18,
    sex:"male"
    // add:"中国China", 两个属性值没写,使用默认值
    // phone:"187" 两个属性值没写,使用默认值
    });
    console.log(person.age);
    console.log(person.add);
    console.log(person.phone);

    //9,函数作为参数,就叫回调函数
    $.each(obj,function(){...})
    setInterval(function(){},1000)
    </script>
    <script type="text/javascript">
    /*
    //--------返回值:--------
    return
    1,表示 函数的结束。
    2,表示 返回return 后面的值。如果后面没有值,则返回undefined

    return 表示在函数中使用,函数返回一个值。

    continue 用于循环,表示跳出本次循环,执行下一次循环

    break 跳出整个循环,执行循环以外的代码*/

    //1,没有返回值: 默认undefined
    function fn(){}
    function fn1 () {
    return;//表示返回值为undefined
    }
    function fn2(a,b){
    if (b<0) return;//表示函数结束执行
    return a/b;//表示返回值
    }
    console.log(fn());//返回 undefined
    console.log(fn1());//返回 undefined
    //2,数字做返回值
    //3,字符串作为返回值
    alert(1,2,3,4);返回字符串:1,2,3
    alert([1,2,3,4]);//返回字符串:1,2,3 默认会隐式转换:[1,2,3,4].toString();
    alert([1,2,3,4].toString());返回字符串:1,2,3
    //4,boolea return true/false
    //5,null
    //6,数组 返回多个值
    function fn(a,b){return [a+b,a,b];}
    //7,对象
    function getPerson(){
    return {//不用创建对象了,直接返回一个对象即可
    name:"zheng",
    age:18
    };
    }
    console.log(getPerson());//{name: "zheng", age: 18}

    //一下代码风格要小心,return在解析时,系统会自动给return添加分号;,从而报错。
    /*function getPerson()
    {
    return //return在解析时,系统会自动给return添加分号;,从而报错。
    {
    name:"zheng",
    age:18
    };
    }
    console.log(getPerson());//{name: "zheng", age: 18}*/
    //8,函数
    function fn(){
    return function (){
    console.log("one");
    }
    }
    // 返回:
    // ƒ fn(){
    // return function (){
    // console.log("one");
    // }
    // }
    console.log(fn);
    //返回:ƒ (){ console.log("one"); }
    console.log(fn());
    //返回:one
    console.log(fn()());
    //------
    document.write([1,3,5]);//返回 1,3,5 进行了隐式转换[1,3,5].toString();
    document.write({"name":"zheng","age":18,toString:function(){
    document.write("love");
    }});//返回:[object Object]
    console.log({"name":"zheng","age":18,function(){
    document.write("love");
    }});//返回:{name: "zheng", age: 18, function: ƒ}

    /*为了写出更优雅的函数,会将函数作为参数传递到另一个函数中,组成一个新功能的函数:
    两个功能:
    1,传进来函数的功能。
    2,接收函数的功能。
    一个函数实现一个功能,把多个函数组合成一个新的函数,就实现了一个复合的功能。*/
    </script>
    //------关于局部作用域,调用一次就创建一次,也删除一次-------
    <script type="text/javascript">
    function count(){
    var num=1;
    return function(){
    return num++;//先返回 num,再num+1
    // return ++num;//先num+1,再返回 num
    }
    }
    console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除
    console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除
    console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除
    var fn=count();//这里只调用一次函数,只开辟一个局部作用域,所以里面的num执行几次就会加1几次。
    console.log(fn());//fn()=count()();
    console.log(fn());//fn()=count()();
    console.log(fn());//fn()=count()();
    //返回:1 ,1 ,1 ,1 ,2 ,3

    // 1、 count()()这样调用,每次都会创建一个新的局部作用域,num的值会不断地被初始化为1

    // 2、 return num++表示先返回num的值,再将num加1

    // 3、 先将count()赋给fn,此时count()只调用了一次,接下来多次调用fn()的时候,count函数并没有多次调用,num只会在count函数调用的时候被初始化,所以多次调用fn()的时候num不会被多次初始化;由于fn相当于count函数的内层函数(var fn=count();这行代码执行后,就调用了count(),调用count后就将里面的函数赋值给了fn,所以说fn就相当于函数的内层函数了。),可以访问count中的变量num,所以多次调用fn函数,会将num的值累加;
    </script>

    函数的定义, 普通函数 构造函数 本质 作为数据,递归, 链式调用,间接调用,  arguments参数 return返回值函数的定义:   //函数:一次申明,四次使用(调用)   //函数分为:命名函数(有函数名称的函数) 和 匿名函数(没有名称的函数)   //命名函数   function add(a,b){   //函数体,属于局部作用域   return a+b;// return 表示函数一死,可以烧纸,return后面的是函数返回值   console.log("return 后面的代码永远不会执行。");   };   add(3,8);   //匿名函数    window.onload=function(){   //函数体,属于局部作用域   alert("hellow");   };
       //------函数执行过程-------   function add(a,b){   var result=a+b;   return result;   }   /*   -------上述函数每次被调用时都会发生的事情-------   1,浏览器全局对象window下面创建一个add方法   2,在add方法下面创建一个局部作用域   3,在局部作用域中创建变量 a=undefined , b=undefined , result=undefined   4,执行函数add(1,2);   5,给每个变量赋值 a=1 , b=2 , result=3   6,函数执行完毕,第一个要做的就是删除 add方法里面的局部作用域以及里面的变量,所以在外面无法访问里面的变量*/
    //------------------------------------------   //------为什么要使用函数-------   /*1,复用代码   2,易于修改,维护   3,增加程序的可读性*/
       //以下函数对可读性的优化   //下面代码每次看的话都要分析如何实现,怎么判断春夏秋冬,   //每次查看都要分析,细节暴露太多了,所以可读性不是很强。这里就需要封装函数了   function doThings(month){   if (month>=3 && month<=5) {   //踏春   }else if(month>=6 && month<=8){   //游泳   }else if(month>=9 && month<=11){   //秋收   }else{   //冬天睡觉   }   }   //什么时候可以使用函数?   //1,代码中有重复代码,或者有相似代码时,需要封装函数。   //2,功能实现时有很多代码,细节暴露太多,可读性很差时,就需要封装函数。   //   //把上面函数封装成可阅读性比较强,不暴露细节,直接读函数名称就可以知道做什么?   //在实现比较强的阅读性时,不要暴露具体实现的函数过程,直接一个函数名即可。   function isSpring(month){     return month>=3 && month<=5;   }   function isSummer(month){     return month>=6 && month<=8;   }   function isAutumn(month){     return month>=9 && month<=11;   }   function isWinter(month){     return month>12 && month<=2   }   function doThings(month){      if (isSpring()) {      //踏春      }else if(isSummer()){      //游泳      }else if(isAutumn()){      //秋收      }else{      //冬天睡觉      }   }</script><script>//-------------函数的本质---------------/*函数二象性1,函数可以调用2,函数其实是对象:{}定义对象的方式:a,字面量的方式: var a={...}b,构造函数的方式: var obj=new Object();var arr=new Array();添加属性和方法:var person={};person.name="zheng";person.setName=function(name){this.name=name;}
    var Person(arguments){name:"zheng",age:"18",addredd:"China"}定义函数的方式:a: function Person(arguments){...}b: var fn = new Person(a,b,c);*///-----以下是对象的操作-------/*var a={"name":"zheng","age":18,"love":"you"}a.name="love";a.setAge=function(age){return a.age=age;}console.log(a.name);console.log(a.setAge(88));*///-----以下是函数的操作-------function add(a,b){age="zheng";//设置age属性return a+b}console.log(add.name);//返回 add,这里name是函数关键字 表示返回当前函数的函数名称//给函数add设置age属性add.setage=function(age){this.age=age;}add.age="love";//重新设置 age 属性值console.log(add.age);//返回 loveadd.setage("you");//修改age的值console.log(add.age);//返回 youconsole.log(add(1,3));//输出 4console.log(add);//输出add函数本体
    //给add函数对象添加一个start函数add.start=function(){console.log("hello");}add.start();//执行start方法,输出hello</script>
    <script>//---------函数作为数据值来使用----------//值的集合是数组,键值对出现的就是对象//值的集合是数组var arr=[1,"a",function(){}];for(var p in arr){console.log(p);//输出的索引值 0 1 2console.log(arr[p]);//arr[p] 输出的是arr中的对象}//键值对是对象var array={"a":"love","b":"you","c":function(){}};for(var p in array){console.log(p);//输出array的属性console.log(array[p]);//输出array的属性值}
    //---------函数作为参数来使用----------//这里的函数作为参数使用// setTimeout(function(){alert(1)},1000);//一秒钟后跳出弹窗setTimeout(fn,1000);//函数名称表示函数本体,fn()表示立即执行该函数本体。function fn(){alert(1);}
    //---------函数作为返回值来使用----------function add(){return function(){alert(2)};}/*var newFn=add();//返回 return 后面的匿名函数本体newFn();//函数本体后面添加小括号,表示立即执行该函数*/add();//得到 function(){alert(2)}; 这个返回值,是一个匿名函数本体。add()();//表示执行匿名函数本体</script>
    //========函数的三种定义方式============//-----第一,二种函数定义方式:------字面量:   function声明:  function add(){...body...}  //这里可以不要使用分号,这是函数调用: add();
    var赋值表达式:var add=function(){...body...};//这里一定要使用分号,这是语句调用: add();
    var add=function fn(){...}add(); //只能在外部调用,不能再函数体内调用fn();//这么调用是错误的,fn属于局部变量,不可以在外面调用//-----第三种函数定义方式:------构造函数:申明:var fn=new Function("a","b","return a+b;");调用:fn();
    //============函数定义的区别===============字面量于构造函数的区别:1,字面量定义:直观,简洁,方便书写2,构造函数:笨重,复杂,效率低(解析字符串是变量是还函数体,实例化构造函数,函数体多的时候很难看)        构造函数的定义方式复杂难懂,效率较低,一般不用它来定义函数         使用构造函数的方式定义函数,不会被提前,函数调用必须在定义之后
    声明方式:var声明方式 和 function声明方式 的区别:1,使用var声明方式 是一个条语句,不会申明提前,所以最后要加分号;2,使用function声明方式 是一个函数,会被申明提前,所以最后不要加分号。3,预解析的过程的不同,如下代码:<script>//这里是预解析的时候已经定义了function add(),//所以可以提前输出:function add(){return "a";}//使用function声明的方式定义函数,声明会被提前,函数调用在定义前后都无所谓console.log(add());//输出 afunction add(){return "a";}//-----console.log(add());var add=function(){return "a";}//预解析://var add=nudefined//预解析完了再逐行执行代码。//所以add是一个变量,不能当做函数执行add();//-----var ad=function(){return "b";}console.log(ad());//预解析://var ad=undefined;//预解析完成,再重头开始逐行执行代码//给 ad 进行赋值 ad=function(){return "b";}//所以这里的 ad是一个函数 ad();</script>
    //使用时怎么选择函数//构造函数 傻大黑粗效率低,一般不建议使用//var 和 function 两种都差不多,一般都是根据团队风格进行选择的。======================<script>//使用构造函数实现:21 * 32 + 24 / 3 - 5var multiply=new Function("a","b", "return a*b;");//所有参数都必须使用字符串的形式,包括函数体。// console.log(multiply("21","32"));//调用该方法时,只需要带参数即可,函数体不用写。var divide=new Function("a","b","return a/b;");//所有参数都必须使用字符串的形式,包括函数体。// console.log(divide("24","3"));//调用该方法时,只需要带参数即可,函数体不用写。var substract=new Function("a","b","return a-b;");//所有参数都必须使用字符串的形式,包括函数体。// console.log(substract("333","222"));//调用该方法时,只需要带参数即可,函数体不用写。//等价下行:var add=new Function("a","b","return +a + +b;");//+a,+b表示取正,-a表示取负,!表示取反var add=new Function("a","b","return parseInt(a)+parseInt(b);");//所有参数都必须使用字符串的形式,包括函数体。// console.log(add("22","33"));//调用该方法时,只需要带参数即可,函数体不用写。var mul=multiply("21","32");//返回:672var divide=divide("24","3");//返回:8var add=add(mul,divide);console.log(add);//返回 680var sub=substract(add,"5"); //返回 675console.log(sub);//返回 675</script>
    //========函数定义的位置============//具体哪里可以访问,请使用搜狗:zuoyongyu:作用域的知识1,全局作用域function add(){...} 在哪里都可以调用
    2,函数作用域//fn1()函数只能在substract函数中进行访问,不可以在全局中访问。function substract(){fn1();//可以访问function fn1(){fn1();//可以访问function fn3(){fn1();//可以访问}}fn1();//可以访问function fn2(){fn1();//可以访问}}
    3,不建议在代码块中定义函数:在javascript中不存在 if/for代码块的作用域,里面的函数预解析为window全局作用域if(true){function add(argument){...}}else{function substract(argument){...}}//函数预解析时就提前声明了:window下面的属性及其方法:function add(argument){...}function abstract(argument){...}再逐行执行代码
    ------如果为真,就可以执行add()函数,否则就可以执行substract()函数-------if(true){var add=function(){...};}else{var substract=function(){...};}函数是在预解析之后再赋值的:var add=undefined;var substract=undefined;再逐行执行代码------B:JS中没有块级作用域,所以不会在if中发生预解析,在外部预解析的时候,if中声明的所有函数都会被提前,所以无法达到按需定义的目的。C:方法的调用必须指定对象,一般通过 对象.函数名() 的方式调用D:内部函数可以访问外部函数的变量(作用域链的机制)------
    4,函数作为对象的属性值:<script>var person={name:"zheng",age:18,address:"China",setAddress:function(address){this.address=address;}};console.log(person.name);//输出:zhengconsole.log(person.name="liang");//输出:liangperson.setName=function(name){this.name=name;}//添加设置修改姓名的方法person.setName("zhu");//重新把name设置为:zhuconsole.log(person.name);//输出:zhuconsole.log(person.address);//输出:Chinaperson.setAddress("American");//重新把address设置为:Americanconsole.log(person.address);//输出:American</script><script>//如果输入两个数字类型,就相加,否则提示请输入数字类型的参数var add=function(a,b){if (isNumber(a) && isNumber(b)) {return parseInt(a)+parseInt(b);//等价:return +a + +b; 一元运算符: +取正,-取负 !取反}else{return "请输入数字类型的参数";}}function isNumber(a){return isNaN(a)?false:true;//如果isNaN(a)=true,那么返回false ,否则返回true}console.log(add("333","bbb"));console.log("33","22");</script>
    //------函数的调用------<script>//命名函数的调用function add(a,b){return a*b;}add();//命名函数的调用
    //匿名函数的调用//1,使用 变量名+() 进行调用var add=function(a,b){return a*b;}add();//
    //2,匿名函数自我执行/*function(){console.log(1);}();在预解析时:function后面一定要跟上一个函数名称,但这里没有函数名称,所以会报错。解决办法如下:*///匿名函数自执行方法一://把匿名函数自我执行后的结果赋值给变量a即可,函数名称+()表示立即执行函数本体。/*var a =function(a,b){return 3*4}();console.log(a);
    //匿名函数自执行方法二,三效果一模一样//匿名函数自执行方法二:(function(){console.log(2)}());//匿名函数自执行方法三:(function(){console.log(3)})()//匿名函数自执行方法四://!表示取反,+表示取正,-表示取负数,只要不让匿名函数的function打头,那就可以匿名函数自执行!function(){console.log(4)}();+function(){console.log(4)}();-function(){console.log(4)}();!+~-function(){console.log(4)}();//匿名函数自执行方法五:console.log(function(){return 5;}());*/
    <script>(function(){function add(a,b){return a+b;}console.log(add(1,3));//而这里返回的4})();console.log(add(1,3));//这里调用报错,因为add函数是在匿名函数的作用域内,不可以当做全局变量来使用</script>
    //------递归函数------5的阶乘:5*4*3*2*1//递归函数,类似于循环//1,一定有一个终结点退出函数执行//2,同理一直进行自我调用<script>function factorial(num){if (num<=1) return 1;return num*factorial(num-1);}console.log(factorial(5));
    //上面的递归等同于下面的函数:/*5*4*3*2*15!5*4!5*4*3!*/var sum=1;function a(num){var i=1;while (i<=num) {sum=sum*i;i++;}return sum;}console.log(a(5));</script>
    <script>//求阶乘,这里没有终止条件,值域溢出,所以死循环function factorial(num){return num*factorial(num-1);}factorial(5);</script>
    <!-- 对象调用方法 --><script>var operation={//加法add:function(a,b){return a+b;},//减法substract:function(a,b){return a-b;},//乘法multiply:function(a,b){return a*b;},//除法divide:function(a,b){return a/b;},//使用不合法的字符串时,只能使用:对象["@"]()运行函数"@":function(){console.log("999");alert("1");}}//使用合法字符串命名,可以使用以下两种方法进行调用函数console.log(operation["add"](3,6));console.log(operation.add(3,6));//使用不合法的字符串时,只能使用: 对象["@"]() 运行函数operation["@"]();
    var key="add";// []方括号中,有双引号的表示字符串,没有双引号的表示变量,谨记console.log(operation[key](1,3));//返回:4  这里的是变量:key="add"console.log(operation["key"]());// 返回:key  这里的key是对象operation中的方法。
    //-------链式调用方法-------// $("p").html("love you forever").css("backgrond","red")...var operation={//加法add:function(a,b){console.log(a+b);return this;//返回的是operation对象},//减法substract:function(a,b){console.log(a-b);return this;//返回的是operation对象}}// operation.add(2,3); 返回的是 operation 对象// operation.substract; 返回的是 operation 对象//所以可以使用下面的链式调用,否则是不可以的。operation.add(2,3).substract(33,3);</script><script>//这是需要鼠标点击才可以调用点击方法document.onclick=function(){alert("1");}//不用点击直接调用方法,任意方法直接在方法名称后面添加 (),就会立马执行该方法document.onclick();</script><script>//什么是构造函数//普通函数有return 则返回 return后面的值,如果没有return,则返回undefined//函数名称小写用于区分:普通函数,不是严格规定//函数名称大写的用于区分:构造函数,不是严格规定 function add(a,b){return a+b;}//普通函数的调用:函数名称()add(3,4);// function Person(){...}//new Person() 用于实例化构造函数// var Obj=new Person();//Person();这么调用就是普通函数//Array();这是普通函数//Object();这是普通函数console.log(Array());//返回 []console.log(Object());//返回 {}var arr=new Array();//实例化一个数组 返回的永远是对象var obj=new Object();//实例化一个对象 返回的永远是对象
    ////-------实例化一个Person--------/////构造函数,顾名思义:被构造的对象也必须是一个函数。function Person(){this.name="zheng";//这里一定要使用this.属性,否则后面输出都是undefined.this.age=18;//这里一定要使用this.属性,否则后面输出都是undefined.var address="China";//实例化后,输出为undefined}var xm=new Person();//实例化一个Person对象console.log(xm);//Person {name: "zheng", age: 18} address定义错误不是属性console.log(xm.name);//输出 zhengconsole.log(xm.age);//输出 18console.log(xm.address);//输出 undefined</script>
    <script>//创建一个空的Person对象var Person=function(){};//实例化Person对象var per=new Person();//给对象添加属性per.name="zheng";per.age="18";per.sex="male";//实例化一个数组var arr=new Array();//给数组arr添加属性arr[0]="zheng";arr[1]="liang";//遍历per对象并输出属性及其属性值for(var p in per){console.log(p+":"+per[p]);}//遍历数组arr并输出值for (var i = 0; i < arr.length; i++) {console.log(arr[i]);}</script><script>//------间接调用--------var name="xm";var person={};person.name="xh";person.getName=function(){return this.name;}console.log(person.getName());//输出:xh//这里的window用于改变person.getName里面的this变成:window,即返回window.name的值console.log(person.getName.call(window));//输出:xm//这里的window用于改变person.getName里面的this变成:window,即返回window.name的值console.log(person.getName.apply(window));//输出:xm
    var arr=[2,5];function add(a,b){return a+b;}//直接调用console.log(add(3,6));//使用了间接调用,call(指定作用域对象,argument1,argumen2...)console.log(add.call(window,2,5));//这里间接调用了window下面的arr的数组值, apply(指定作用域对象,数组)console.log(add.apply(window,arr));//间接调用://1,对象没有call和apply方法,只有函数有//2,apply可以将数组和类数组一次性的传递进函数中,call只能一个一个的传</script>//------arguments 参数------//参数分为:实参,形参1,当参数为基本数据类型时,只是进行了复制操作,不不会修改原来的值。2,当参数为引用类型时,因为两个引用地址相同,指向同一个值。如果修改其中一个,另一个也会被修改。//三种情况:1,实参=形参<script>//函数中的参数:形式参数 实际参数function add(a,b){//这里的 a,b是形式参数,占位符的作用return a+b;}add(3,8);//这里的3 ,8 是实际参数//本质上就是复制一个副本:  形参=实参 ,对于原来的值是不改变的。// var a=3;  var b=8;
    //参数为对象时,参数为引用类型,那么传递的是地址。修改一个同时也会修改另一个var person={};var setName=function(obj){//这里的参数是对象,给指定对象设置name属性obj.name="zheng";}setName(person);//这里的person是对象,给person对象设置name属性console.log(person.name);</script>
    2,实参<形参<script>//求数的幂  Math.pow(base,power);function pow(base,power){return Math.pow(base,power);}console.log(pow(3,4));//返回 81console.log(pow(3,2));//返回 9
    function pow(base,power){// if (!power) power=2;//如果b为空:!power=true,如果b不存在为真的,那么返回b=2.//短路操作power=power || 2;//或逻辑 一个为真即为真 如果power=power返回true,那么power=power,否则b=2;return Math.pow(base,power);}console.log(pow(4));//返回 16console.log(pow(3));//返回 9//$("p");//默认省略document//在JQuery中的参数: $("p",document):表示在文档中查找P标签。//也可指定某个对象:$("p",document.getElementById("box")),//指定id="box"的对象下面查找p标签。</script>
    3,实参>形参<script>function add(){//任何函数都有返回值,返回return后面的值,如果省略return或者return后面没有值,则返回undefinedif (arguments.length==0) return;var sum=0;for (var i = 0; i < arguments.length; i++) {sum+=arguments[i];}return sum;}console.log(add()); // 返回 undefinedconsole.log(add(1,3,4));//返回 8</script><script>// 输入任意个数字参数,输出最小值function mix(){var len=arguments.length;if (len==0) return;if (len==1) return arguments[0];var mi=0;for (var i = 1; i < len; i++) {//思路决定出路// 这里是精华所在,前后对比,把较小的一个赋值给arguments[i]arguments[i]= arguments[i-1]<arguments[i]?arguments[i-1]:arguments[i];mi = arguments[i];}return mi;}console.log(mix(1,3,444,2,5245,7373,2452,-11,-23432,-234,-245));console.log(mix());console.log(mix(888))</script>
    //arguments//参数是每个函数都有的,是一个局部变量//类数组对象,但不是数组的实例。可以使用arguments[index]进行取值.<script>//合法标识符:不能以数字,关键字,保留字开头,以字母,数字,下划线组成的字符串;//这里arguments的索引是 "0" 到 "5" ,数字是不合法的标识符,所以只能使用双引号。//以下就是类数组对象:var arguments={"0":"argument1","1":"argument2","2":"argument3","3":"argument4","4":"argument5","5":"argument6"};//遍历arguments类数组对象for(var p in arguments){console.log(p+":"+arguments[p]);}
    //1.对象的长度不能用.length获取,用js原生的Object.keys可以获取到console.log(arguments.length);//返回 undefinedvar keys=Object.keys(arguments)//使用原生Object.keys,获取键值对中键的集合,都是数组var values=Object.values(arguments)//使用原生Object.values,获取键值对中值的集合,都是数组console.log(keys.length);//两种都可以获得对象的长度console.log(values.length);//两种都可以获得对象的长度//但是,如果arguments作为函数中的参数,是可以通过arguments.length获得实际参数个数。//函数是一个特殊对象,也可以通过add.length 获得形式参数个数<script>function add(a,b,c){console.log(arguments.length);//返回 5 调用函数是写入的实际参数console.log(add.length);//返回 3,定函数时,定义的形式参数console.log(arguments.callee.length);//返回 3 形式参数,函数固定的形式参数长度return +a + +b + +c;//一元运算符,+取正,-取负,!取反}// console.log(add(1,3,5));console.log(add(1,3,6,7,8));//返回:10 只对前面3个参数进行相加
    </script>//------function fn(arguments){console.log(argument);function fn1(arguments){console.log(argument);}fn1(2);//输出2}fn(1);//输出1//arguments是每个函数中独有的,不同作用域不同//预解析:/*fn函数作用域:var argument=undefined;fn1函数作用:var argument=undefined;*/</script>//--------// "use strict" //表示使用严格模式// var num=1;//这样定义num变正确// num=1;//这样定义num变就会报错</script><script>//判断传入参数是否等于实际参数function add(a,b){//console.log(arguments.length);//返回 5实际参数,我们实际传入的参数//console.log(arguments.callee.length);//返回 2 形式参数,函数固定的形式参数// console.log(add.length);返回 2 //形式参数,函数固定的形式参数,可以在函数外面进行调用if (arguments.length!==add.length) throw new Error("请输入:"+add.length+"个参数");return a+b;}// console.log(add(2,4));//返回 6console.log(add(1,3,4,5,6));//参数不对,参数过多。返回:text2.html:13 Uncaught Error: 请输入:2个参数</script>//---------------<body>    <p id="test" style="background-color: red; color: blue;">我是一个段落!</p><script type="text/javascript"> //在使用参数给对象设置CSS属性时,都是用p.style[property]=value,这样绝对没错//如果使用p.style.property=value。读取时使用,设置时有可能会报错。var p=document.getElementById('test');function css(value,property){//必要参数一定要放在第一个,可传可不传放在后面if (arguments.length<=0 || arguments.length>=3) throw new Error("请输入:"+arguments.length+"参数");if (property==undefined) p.style.backgroundColor=value;if (arguments.length==2) p.style[property]=value;}css("orange");//第二个参数省略,默认 property=undefined// css("green","backgroundColor");</script> </body> <script type="text/javascript"> //-----什么可以当做变量-------//1,什么都不传var a=2;function fn(){function(){alert(a);}}//2,数字function fn(num){console.log(num);}fn(2);//3,字符串//4,booleanfunction a(){}function b(){}//如果传进来的是布尔值,一定使用要把细节封装成a,b函数。经验之谈。function fn(boolean){if (true) {a();}else{b();}}//5,undefinedfunction add(a,b){if (b==undefined) return a;return a+b;}console.log(add(6,undefined));//返回 NaN,非数字function pow(bace,power){//短路操作,如果power=power=true则power=power  power=undefined=false 则power=2。power=power || 2;return Math.pow(bace,power);}console.log(pow(3,6));//6,null//以上都是单个参数传递////7,传多个参数,如数组:[1,2,3,4,5]$.each([1,2,3,4,5], function(index, val) {console.log(index);console.log(val);});for (var i = 0; i < [1,2,3,4,5].length; i++) {console.log(index);console.log(val);}//8,传对象:{"a":"1","b":"2","c":"3"}$.each({"a":"1","b":"2","c":"3"}, function(index, val) {console.log(index);console.log(val);});
    //下面代码使用对象作为参数进行代码优化:function setPerson(name,sex,age,add,phone){var person={};person.name=name;person.sex=sex;person.age=age;person.add=add;person.phone=phone;}//可读性,可写性不强,很容易弄错参数顺序导致错误,所以下面可以使用对象代替setPerson("zhengl","male",18,"中国China","182...");
    //当参数超过三个或者三个以上,建议适用对象进行代码优化如下:var person={};function setPerson(obj){person.name=obj.name || "xh";//如果没有设置该属性,则设置一个默认值person.age=obj.age || 18;//如果没有设置该属性,则设置一个默认值person.add=obj.add || "中国China";//如果没有设置该属性,则设置一个默认值person.sex=obj.sex || "male";//如果没有设置该属性,则设置一个默认值person.phone=obj.phone || "110";//如果没有设置该属性,则设置一个默认值}//经过代码优化:对象属性不用按顺序进行书写,甚至不写都不会报错。setPerson({name:"zheng",age:18,sex:"male"// add:"中国China", 两个属性值没写,使用默认值// phone:"187" 两个属性值没写,使用默认值});console.log(person.age);console.log(person.add);console.log(person.phone);
    //9,函数作为参数,就叫回调函数$.each(obj,function(){...})setInterval(function(){},1000)</script> <script type="text/javascript"> /*//--------返回值:-------- return 1,表示 函数的结束。2,表示 返回return 后面的值。如果后面没有值,则返回undefined
    return 表示在函数中使用,函数返回一个值。
    continue 用于循环,表示跳出本次循环,执行下一次循环
    break  跳出整个循环,执行循环以外的代码*/
    //1,没有返回值: 默认undefinedfunction fn(){}function fn1 () {return;//表示返回值为undefined}function fn2(a,b){if (b<0) return;//表示函数结束执行return a/b;//表示返回值}console.log(fn());//返回 undefinedconsole.log(fn1());//返回 undefined//2,数字做返回值//3,字符串作为返回值alert(1,2,3,4);返回字符串:1,2,3 alert([1,2,3,4]);//返回字符串:1,2,3 默认会隐式转换:[1,2,3,4].toString();alert([1,2,3,4].toString());返回字符串:1,2,3//4,boolea  return true/false//5,null//6,数组 返回多个值function fn(a,b){return [a+b,a,b];}//7,对象function getPerson(){return {//不用创建对象了,直接返回一个对象即可name:"zheng",age:18};}console.log(getPerson());//{name: "zheng", age: 18}
    //一下代码风格要小心,return在解析时,系统会自动给return添加分号;,从而报错。/*function getPerson(){return //return在解析时,系统会自动给return添加分号;,从而报错。{name:"zheng",age:18};}console.log(getPerson());//{name: "zheng", age: 18}*///8,函数function fn(){return function (){console.log("one");}}// 返回:// ƒ fn(){// return function (){// console.log("one");// }// }console.log(fn);//返回:ƒ (){ console.log("one"); }console.log(fn());//返回:oneconsole.log(fn()());//------document.write([1,3,5]);//返回 1,3,5 进行了隐式转换[1,3,5].toString();document.write({"name":"zheng","age":18,toString:function(){document.write("love");}});//返回:[object Object]console.log({"name":"zheng","age":18,function(){document.write("love");}});//返回:{name: "zheng", age: 18, function: ƒ}
    /*为了写出更优雅的函数,会将函数作为参数传递到另一个函数中,组成一个新功能的函数:两个功能:1,传进来函数的功能。2,接收函数的功能。一个函数实现一个功能,把多个函数组合成一个新的函数,就实现了一个复合的功能。*/</script>    //------关于局部作用域,调用一次就创建一次,也删除一次-------<script type="text/javascript"> function count(){ var num=1; return function(){ return num++;//先返回 num,再num+1 // return ++num;//先num+1,再返回 num } } console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除 console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除 console.log(count()());//每次调用普通函数,都会创建一个新的局部作用域,函数执行完连被删除 var fn=count();//这里只调用一次函数,只开辟一个局部作用域,所以里面的num执行几次就会加1几次。 console.log(fn());//fn()=count()(); console.log(fn());//fn()=count()(); console.log(fn());//fn()=count()(); //返回:1 ,1 ,1 ,1 ,2 ,3  // 1、 count()()这样调用,每次都会创建一个新的局部作用域,num的值会不断地被初始化为1
     // 2、 return num++表示先返回num的值,再将num加1
     // 3、 先将count()赋给fn,此时count()只调用了一次,接下来多次调用fn()的时候,count函数并没有多次调用,num只会在count函数调用的时候被初始化,所以多次调用fn()的时候num不会被多次初始化;由于fn相当于count函数的内层函数(var fn=count();这行代码执行后,就调用了count(),调用count后就将里面的函数赋值给了fn,所以说fn就相当于函数的内层函数了。),可以访问count中的变量num,所以多次调用fn函数,会将num的值累加;</script> 

  • 相关阅读:
    非科班学习路线
    非科班秋招面试总结
    招银网络Java面经
    派分糖果
    修改CentOS7网卡名称为传统名称eth0格式
    浅谈$* 和$@的区别
    Cobbler无人值守安装
    使用kickstart + pxe 部署无人值守安装
    CentOS 7 忘记root密码解决方法
    linux系统开机流程详解
  • 原文地址:https://www.cnblogs.com/Knowledge-is-infinite/p/10964635.html
Copyright © 2011-2022 走看看