JS-函数

JS-函数

  1. 函数简介

    函数也是一个对象;

    —函数中可以封装一些功能(代码),在需要时可以执行这些功能(代码);

    —函数中可以保存一些代码,在需要是时调用;

    —使用typeof检查一个函数对象时,会返回function

    —函数对象具有对象的基本功能(添加属性等功能),同时它可以封装代码;

    使用构造函数创建函数对象

    —语法:var fun = new Function();

    —可以将要封装的代码以字符串的形式传递给构造函数;

    var fun = new Function("console.log('hello,这是我的第一个函数');");

    —封装到函数中的代码不会立即执行,函数中的代码会在函数调用的时候执行

    —实际开发中,很少使用构造函数创建函数对象

    使用函数声明创建函数

    —语法:

    function 函数名([形参1,形参2,...形参N]){
    	函数体
    }
    

    注意:形参可写可不写,根据自己构建函数的情况

    使用函数表达式创建函数

    —语法:

    var 函数名 = function([形参1,...形参N]){
    	函数体
    };
    

    注意:可以理解为匿名函数赋值语句,因此后面需要加上分号;

    调用函数

    —语法:函数对象();

    —当调用函数时,函数中封装的代码就会按照顺序执行

  2. 函数的参数

    形参

    —可以在函数中()指定一个或者多个形参(形式参数)

    —多个形参之间用逗号隔开声明形参就相当于在函数内部声明了对应的变量,但是并不赋值

    实参

    —在调用函数时,可以在()中指定实参(实际参数);

    —实参将会赋值给函数中对应的形参;

    —调用函数时,浏览器不会检查实参的类型,所以要注意是否有可能接收到非法的参数,如果有可能,则需要对参数的类型进行检查;

    —调用函数时,浏览器解析器不会检查实参的数量,多余的实参不会被赋值;如果实参的数量少于形参,则没有对应实参的形参将会是undefined

    —函数的实参可以是任意的数据类型

    <script>
    	//创建函数
     	function sum(a,b){
         	console.log(a+b);
     	}
     	//调用函数
     	sum(1,2);
    </script>
    

    实参可以是任意值,也可以是一个对象!!!

    —当我们参数过多时,可以将参数封装到一个对象中,然后通过对象传递;

    <script>
    	//创建函数
     function sayHello(obj){
         console.log("Hello,everyone!My name is"+obj.name+",my age is"+obj.age);
     }
     //创建对象
     var obj={
         name:"Tom",
         age:18
     };
     //调用函数
     sayHello(obj);
    </script>
    

    实参也可以是一个函数

    注意:

    fun()—调用函数;如果将调用函数传递给实参,实际上是将函数的返回值传递给实参!!

    fun—函数对象;如果将函数对象传递给实参,相当于直接使用函数对象;

    <script>
    	//创建函数
     function fun(a){
         a(obj);
     }
     //将函数作为实参传递给形参a并调用函数
     fun(sayHello);
     //传递匿名函数
     fun(function(){alert("hello")});
    </script>
    
  3. 函数的返回值

    —可以使用return来设置函数的返回值;

    —语法:return 返回值

    return后的值将会作为函数的执行结果返回;

    —可以定义一个变量接收这个结果;

    —在函数中,return后的语句都不会执行;

    —如果return语句后不跟任何值就相当于返回一个undefined

    —如果函数中,不写return,也会返回undefined

    使用break可以退出当前循环,使用continue可以结束当次循环,而使用return可以结束整个函数,其后边的语句都不会执行;

    <script>
    	//判断是否为偶数,如果是返回true
     function isEven(num){
         return num%2==0;
     }
     //存储返回值
     var result=isEven(2);
     console.log("result = "+result);
    </script>
    

    return返回值可以是任意数据类型也可以是对象,也可以是一个函数

    <script>
    	function fun1(){
         //函数内部再次声明一个函数
         function fun2(){
             alert("我是fun1中的fun2");
         }
         //将fun2函数对象作为返回值
         return fun2;
         //将fun2函数返回值作为返回对象
         return fun2();
     }
     //调用函数fun1
     a=fun1();
     console.log(a);
    </script>
    
  4. 立即执行函数

    —函数定义完,立即被调用执行;

    —立即执行函数只会执行一次

    <script>
     //用小括号括起来的函数即为立即执行函数
    	(function(a,b){
         alert(a+b);
     })(1,2);
    </script>
    
  5. 全局作用域

    作用域:一个变量作用的范围;

    —在JS中,一共分为两种作用域:全局作用域和函数作用域(局部作用域)

    —直接编写在<script>标签中的JS代码,都在全局作用域中;

    全局作用域在页面打开时创建,在页面关闭时销毁;

    —在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,由浏览器直接创建,我们可以直接使用;

    —在全局作用域中,我们创建的变量都会作为window的属性保存;

    —在全局作用域中,我们创建的函数都会作为window的方法

    全局作用域中的变量都是全局变量,在页面中的任意部分都可以访问到;

    <script>
    	var a=10;
    //创建的变量可以作为全局对象window的属性进行读取
    console.log(window.a);
    //创建函数
    function fun(){
      console.log("My Name is Jack");
    }
    //可以通过访问全局对象的方法进行访问创建的函数
    window.fun();
    </script>
    

    变量的声明提前

    —使用var关键字声明的变量,会在所有代码执行前被声明好(不会赋值);但是如果声明变量时,不使用var关键字,则变量就不会声明提前;

    <script>
     //不会报错,b的返回值为undefined
    	console.log(b);
     //变量声明提前
     var b=10;
    
     //相当于以下写法
     var b;
     console.log(b);
     b=10;
    </script>
    

    函数的声明提前

    —使用函数声明创建的函数 function 函数名(){} 它会在所有代码执行前就被创建;所以可以在函数声明前调用函数

    —但是使用函数表达式创建的函数 var 函数名 = function(){} 不会被声明提前,所以不能在声明前调用函数

    <script>
    	 //函数声明提前,可以执行
     	fun1();
    	function fun1(){
         console.log("我是一个fun函数");
     }
     //使用变量表达式创建函数,无法声明提前,报错
     fun2();
     var fun2 = function(){
         console.log("我也是一个fun函数");
     };
    </script>
    
  6. 函数作用域

    调用函数时创建函数作用域,函数执行完毕后,函数作用域销毁;

    —每调用一次函数就会创建一个新的作用域,它们之间是相互独立的;

    —在函数作用域中可以访问到全局作用域中的变量

    —在全局作用域中无法访问到函数作用域的变量

    —当在函数作用域中操作一个变量,现在自身作用域中寻找,如果有就直接使用;如果没有就向上一级作用域(不一定是全局作用域,也有可能是函数)访问(就近原则),直到全局作用域,如果全局作用域没有,则报错ReferenceError

    —在函数作用域中如果想要访问全局作用域的变量,可以通过**window.变量名**的形式进行访问;

    —在函数作用域中也有声明提前的特性;使用var关键字声明的变量会在函数中会在所有代码执行之前被声明

    函数声明也会在函数中所有代码执行之前执行

    —在函数中,不使用var关键字声明的变量都会变成全局变量

    定义形参就相当于在函数作用域中声明了变量

    <script>
    	var a=33;
    	function fun(){
      //未使用var关键字定义变量,因此变成全局变量
      	a=10;//相当于window.a=10
    	}
    	//调用函数
    	fun();
    	console.log(a);//返回10
     	var e = 23;
     	function fun2(e){
         //定义形参相当于在函数作用域中声明了变量
         //var e
        	 alert(e);//返回undefined
     	}
    </script>
    
  7. this

    —解析器在调用函数时,每次都会向函数内部传递进一个隐含的参数,这个隐含的参数为this

    this指向的是一个对象,这个对象是函数执行的上下文对象

    —根据函数的调用方式不同,this指向不同的对象;

    1. 以函数的形式调用this,this指向的是Window;
    2. 以方法的形式调用this,this指向的是调用方法的对象;
    3. 当函数以构造函数创建时,this就指向构造函数新建的对象;
    4. 使用call和apply调用时,this是参数中指定的对象;
    5. 在事件的响应函数中,响应函数是给哪个对象绑定的,this就是哪个对象;
    <script>
    	function fun(){
            //以函数的形式调用,this指向window对象
            console.log(this)
        }
        fun();//返回window
    
        var obj = {
            name:"Tom",
            sayName:fun
        }
        //以方法的形式调用,this指向调用方法的对象obj
        obj.sayName();//返回Object
    </script>
    
    <script>
        //通过this可以访问不同的对象
    	function fun(){
            console.log(this.name);
        }
        var obj1 = {
            name:"Tom",
            sayName:fun
        };
        var obj2 = {
            name:"Jack",
            sayName:fun
        };
        obj1.sayName();//返回Tom
        obj2.sayName();//返回Jack
    </script>
    
  8. 构造函数

    构造函数就是一个普通函数,创建方式和普通函数无区别;

    —不同的是,构造函数的首字母习惯上为大写;

    —构造函数和普通函数调用方式不同:

    ​ 普通函数调用方式是直接调用

    ​ 构造函数需要使用new关键字进行调用,其返回对象类型;

    构造函数执行流程

    1. 调用构建函数时,立即创建一个新的对象;
    2. 将新建的对象设置为函数中的this,在构造函数中可以通过this来引入新建的对象;
    3. 逐行执行函数代码;
    4. 将新建的对象作为返回值返回;

    —使用同一个构造函数创建的对象,称为一类对象,也将一个构造函数称为一个类;使用构造函数创建的对象称为该类的实例

    instanceof可以检查一个对象是否是一个类的实例;如果是返回true,否则返回false;

    任何对象都是Object的实例,所以任何对象和Objectinstanceof都会返回true

    <script>
    	//创建构造函数
       function Person(name,age){
           //this指向构造函数中新建的对象
           this.name=name;
           this.age=age
           /*
           在构造函数内部创建方法,构造函数每执行一次都要创建一个sayName()方法,所有创建的实例都是唯一的sayName()方法;
           导致构造函数执行一次就会创建一个新的方法,占据较多的内存;具有一定的局限性;
           */
           //可以使所有对象共享同一个方法
           this.sayName=function(){
               alert(this.name);
           };
           this.sayName=fun;
       }
       //将sayName()方法在全局作用域中定义,避免重复创建
       function fun(){
           alert(this.name);
       }
        //将函数定义在全局作用域中,污染了全局作用域的命名空间,并且定义在全局作用域中不安全
        //因此可以通过原型对象进行创建方法
        Person.prototype.sayName=function(){
            alert(this.name);
        };
       //调用构造函数创建类的实例
       var per = ner Person("Tom",18);
       //检查是否实例属于类
       console.log(per instanceof Person);
    </script>
    
  9. toString()

    —当我们直接在页面中打印一个对象时,实际上是输出的对象的toString()方法的返回值(Object);

    —如果我们希望在输出对象时,不输出toString()方法的返回值,可以为对象添加一个toString()方法以修改其输出;

    <script>
    	function Person(name,age,gender){
         this.name=name;
         this.age=age;
         this.gender=gender;
     }
     //修改原型的toString()方法
     Person.prototype.toString=function(){
         return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]"
     };
     //创建Person的一个实例
     var per = new Person("Tom",18,"boy");
     console.log(pe);
    </script>
    
  10. 函数的方法

    call()apply()

    —这两个方法都是函数对象的方法,通过函数对象来调用;

    —当对函数调用两个方法,都会调用函数执行;

    —在使用以上两个方法时,可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this;(传递参数是谁,this指定的对象就是谁

    call()方法可以将实参在对象之后依次传递;apply()方法需要将实参封装到数组中统一传递;

    <script>
    	var obj1 = {
         name:"Tom",
         age:18,
         sayName:function(){
             alert(this.name);
         }
     };
     var obj2 = {
         name:"Jack"
     };
     obj1.sayName.apply(obj2);//返回Jack
    
     //call()和apply()的区别
     function fun(a,b){
         console.log("a="+a);
         console.log("b="+b);
     }
     var obj3 = {
         name:"Tom",
         sayName:function(){
             alert(this.name);
         }
     };
     //将实参在对象之后依次传递
     fun.call(obj3,1,2);
     //将实参封装到数组中统一传递
     fun.apply(obj3,[1,2]);
    </script>
    
  11. arguments

    在调用函数时,浏览器每次都会传递两个隐含的参数

    1. 函数的上下文对象this
    2. 封装实参的对象arguments

    arguments是一个类数组对象,伪数组

    —他可以通过索引来操作数据,以及arguments.length获取实参长度;

    —在调用函数时,我们所传递的实参都会封装到arguments,我们可以获取其长度和元素arguments[索引];即使不定义形参,也可以通过arguments来获取实参;

    argumentscallee属性,该属性对应函数对象,即指向当前正在执行的函数对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值