[Javascript]:JS数据类型、类型判断、函数function与Function的使用

      因为之前学过Java,在学习JS时,对JS的数据类型、function和Function的使用概念容易搞混淆,理解不怎么深刻。遂将这些知识点和概念梳理一遍,以便自己和他人理解。如有错误,敬请谅解。

      知识点会涉及到:JS数据类型、JS的类型判断方式、函数创建方式、function与Function的区别、匿名函数的使用、函数特点以及函数重载问题。

Javascript数据类型

  • 基本类型:undefined(未定义)、null(空)、number(数字)、string、boolean、symbol(新增的,没用过)
  • 引用类型:object function
  • 基本类型即值类型,引用类型即对象类型,和Java概念差不多。

在许多JS学习资料中,都会看见数据类型是以Undefined、Null、String...这种形式,而不是我上面的那种小写形式。关于这个问题,会进行解释。

  • 这是因为在JS中,一切基于对象,所有事物都可以看作对象。这意味着在JS中使用的一切都是对象。给一个简单实例:给一个变量赋值,这个过程没用到new操作符创建相应对象,但却可以使用它的包装对象方法。如下:
  <!-- 以字面量形式创建 -->
    <script>
       var a = 15;
       var b = "abcde";
       var len  = b.length;
       var c = b.charAt(0);
       document.write("长度:" + len + ", b索引字符:" + c);
       //结果:长度:5, b:a
    </script>
    <!--以对象形式来创建 -->
    <script>
       var a = new Number(15);
       var b = new String("abcde");
       document.write(a.length + " , " + b.charAt(0)); //结果和上面一样,两者使用方式相同
    </script> 

        上面的实例验证了:在JS中,直接使用值类型给变量赋值,JS也会把基本类型包装成相应对象,这时变量就是一个对象,所以才能直接使用方法。和Java相比,Java只有在需要值类型和包装类需要转换时才会自动进行装箱拆箱,否则严格按照本身定义的类型来使用,不会全部转成对象。所以搞明白JS中的一切都是对象这个概念后,包括变量、函数什么的都可以看作是对象。

       这时再来理解为什么数据类型都是大写而不是小写就很简单了。关于上面的基本类型,因为JS一切为对象的原则,所以undefined、null、object等就没有实际使用意义,上面写出来也只是为了搞明白它们之间的区别和相关概念。这些原始类型的作用仅仅是在使用 typeof 和 instanceof  用来判断具体类型,或是作为返回的字符串,用来表明该类型是什么,是基本类型还是引用类型,其他地方就用不到了~


所以,数据类型用对象类型来会更符合JS的定义:

Undefined、Null、Number、String、Boolean、Symbol、Object、 Function

  • Undefined表示的是一个变量被声明但是没有初始化,即没有赋值。值为undefined。
  • Null则和Java中概念差不多,唯一值是null,表示对象的引用地址为空。
  • 关于Object和Function后面会说到,至于其他没什么可说的。
       

typeof 和 instanceof 的用法

typeof和instanceof都是运算符,它们都可以用来判断变量类型,但是它们各自的用法和操作对象又有所不同。


 typeof用法 

typeof 的返回值 和用于判断的值都是JS的原始类型,就是最上面写的那些类型。

typeof(var):获取指定变量的具体类型。

  <!-- 使用typeof()来得到变量的原始类型,也可以直接 typeof var -->
    <script>
       var a = 15;
       var b = "abcde";
       var c = false;
       var d = function(){} //这是一个函数
       var e = new Function(); //这是一个函数对象
       var f; //没赋值
      document.write("a:" + typeof(a) + "<br>");
      document.write("b:" + typeof(b) + "<br>");
      document.write("c:" + typeof(c) + "<br>");
      document.write("d:" + typeof(d) + "<br>");
      document.write("e:" + typeof(e) + "<br>");
      document.write("f:" + typeof f +",undef:"+typeof(undef)+ "<br>");
    </script>
    <!--结果
        a:number
        b:string
        c:boolean
        d:function
        e:function
        f:undefined,undef:undefined -->


typeof var === 'type' 对变量类型进行判断。

 var a = 150;
        var b = "abcde";
        var c = false;
        alert(typeof a === 'number');    //true
        alert(typeof b === 'number');    //fasle
        alert(typeof c === 'boolean');   //true
        alert(typeof d === 'undefined'); //true      

使用typeof判断对象类型变量时,都是返回object。

 <script>
        //定义两个构造函数
        function cons1(){}
        function cons2(){}
        var a = new cons1();
        var b = new cons2();
        alert(typeof a === cons1);//false
        alert(typeof b === cons2);//false
        alert(typeof a);//object
        alert(typeof b);//object
 </script>

正因为typeof对于判断对象类型具有局限性,所以判断对象类型应使用insatanceof运算符。



 instanceof用法 

object instanceof Object2,instanceof运算符会判断指定对象类型的prototype

 //定义两个构造函数
        function cons1(){}
        function cons2(){}
        var a = new cons1();
        var b = new cons2();
        var aa = new Function(); //这是一个函数对象
        var arr = []; //字面量创建数组
        var arr2 = new Array();//数组对象创建数组
        var obj = {name:"傲天", age:19}; //使用字面量创建对象
        alert(a instanceof cons1); //返回true
        alert(b instanceof cons2); //返回true
        alert(aa instanceof Function); //返回true
        alert(arr instanceof Object); //返回true
        alert(arr instanceof Array); //返回true
        alert(obj instanceof Object); //返回true
两者区别:

typeof用于判断基本类型,instanceof 用于判断对象类型。



function和Function区别,创建函数、函数特点


Function与function的区别:      

  • Function是一个功能完整的对象,作为JS的内置对象之一。而function只是一个关键字,用来创建一个普通函数或对象的构造函数。JS的普通函数都是Function对象的实例,所以函数本身也是一个对象,就像var一样,只不过这个对象具有可调用特征而已。


function创建对象和普通函数的区别:

  • 如果用function创建构造函数,例如:var a = new function{}() 或者  var b = new Person();  则a、b就不是普通函数,而是作为一个真正对象,是Object类型。虽然普通函数也是对象,但一个是Function,作为函数;一个是Object,作为对象。 关于这个问题,可以使用instanceof运算符去验证。
  • 本篇不会涉及使用function创建对象的相关知识,这里仅作了解。

注意:关键字function和原始类型的function名称是相同的,但就像object和Object一样,两者没半毛钱关系。一个是作为创建函数的关键字,一个是用来判断一个对象(函数)是不是Funtion类型。别搞混了。  



 创建函数的方式 

        //  函数声明:使用function声明一个函数,再为其指定一个函数名。
        function first(){
            alert("函数声明方式");
        }
        //  函数表达式:使用function声明一个函数,但没有函数名,而是将这个函数赋给一个变量。也叫作匿名函数
        var second = function(arg1, arg2){
            alert(arg1+"|" + arg2+"\n匿名函数方式")
        }
        //  使用Function对象构造函数创建函数
        var third = new Function(
            "a1", "a2", "alert('函数对象,' + a1 + '|' + a2)"
        );

调用函数方式可以有如下几种:

        //  1.直接执行方式或采用事件来执行函数
        first();
        second("ABC", "XYZ");
        third("火", "土");

        //  2.函数也是对象,所以像变量一样.把函数名赋给另一个变量,那个变量就指向该函数地址
        //  相当于再进行一次封装。动态添加对象方法时会用到。
        var a = first;
        var b = second; 
        a();
        b("ABC", "XYZ");

        //注意!这种方式是直接执行third()函数,而不是赋值函数名。
        var c = third("火", "土");

三者的不同和优缺点:

  • 函数声明在使用之前,就会被加载到作用域中,随时等待调用。而函数表达式(匿名函数)则是在代码执行到那一行才被定义,提前使用则会出错。
        first(); //可以执行
        function first(){
            alert("函数声明方式");
        }
        second(15,25); //执行出错
        var second = function(arg1, arg2){
            alert(arg1+"|" + arg2+"\n匿名函数方式")
        }
  • 匿名函数(函数表达式)与Function()构造函数用法很相似,它们的不同点:匿名函数在使用时只被解析一次。而作为字符串传递给Function()构造函数的JS代码在每次调用构造函数时都要被解析和编译一次。Function对象的就是通过构造函数动态地创建和编译一个函数,但最好不要过多使用,因为用Function对象构造函数定义函数比其他两种慢多了。


 匿名函数 

  • 匿名函数就是上面提到的函数表达式。匿名函数从字面意义来讲,就是没名字的函数,但它需要有一个依附体,要让匿名函数能被找到,不然的话没有意义。匿名函数看起来像Java的匿名内部类,但两者的使用方式差别巨大。但可以去了解一下,对于使用匿名函数或许有不一样的理解。
  • 匿名函数除了可以赋值给一个var,用变量来调用匿名函数;还能把匿名函数赋给一个事件,作为事件处理程序,但别的函数方式也能达到这种效果。但匿名函数最特殊的地方是它的调用方式,下面会一一列举。
实例

        // 定义一个匿名函数,依附于一个变量
        var first = function(a1, a2){
            alert(a1 + "|" + a2 + "\n变量名调用匿名函数")
        }
        //通过var名调用
        first(111, 222);

        //依附一个事件,随着事件触发而执行
        window.onload = function () {
            alert("页面加载完成后触发事件!");
        }


上述匿名函数需要触发相关事件,或是主动执行。有没有匿名函数自动执行的方式呢?如下:

立即执行的匿名函数

 //在匿名函数体后面加上(),表示立即执行该函数
        var second = function(){
            alert("代码执行到此处,立即执行。无需var()");
        }(); //加分号表示执行完成,可加可不加。

        //匿名函数有参,则往里面传参数
        var second = function(a1, a2){
            alert(a1 + "|" + a2 + "\n用括号给匿名函数传入参数,立即执行");
        }(555,666);

因为函数本身也是对象,所以能赋给变量、事件,自然也能赋给一个对象。

//匿名函数赋给anyobj对象,然后anyobj再赋给second变量。这种方式没啥意义,了解原理即可。
        var second = {
            anyobj:function(msg){
                alert(msg);
            }("依附一个对象的匿名函数")
        }

观察上述调用方式,它们都需要一个依附体(变量、事件等),然后这些对象会通过()调用匿名函数,这就是立即执行的匿名函数。但能不能换成别的依附体呢?让匿名函数看起来更像是匿名函数。如下:

  //匿名函数放在括号体内
        (
            function(msg){
                alert(msg + "\n匿名函数放在括号内,作为函数表达式");
            }("传入参数")
        );

这种调用方式是:外面括号包含匿名函数,然后调用()来立即执行函数。这种方式为什么能调用呢?这就要说到小括号的作用,外面的小括号相当于运算符,而此时匿名函数放在里面就形成了函数表达式,然后通过()就能调用该匿名函数。


从这个角度来看,我们还能使用其他运算符来执行匿名函数。

 //使用一元运算符和匿名函数形成函数表达式
        +function(msg){
            alert(msg);
        }("+")
        -function(msg){
            alert(msg);
        }("-")
        !function(msg){
            alert(msg);
        }("!")
        ~function(msg){
            alert(msg);
        }("~")
        *function(msg){
            alert(msg);
        }("*")

      

      关于匿名函数的调用方式就说到这里,当然还有许多细节没说到,这里也仅仅是作为参考,至于还有没有其他运算符来执行匿名函数就不过多了解,最常用的也就是以上几种。最后想说,了解基本概念后,一定要多写,写得多自然也就理解了。


 JS函数的特点 

  1. 因为JS的弱类型特性,函数形参无法指定具体类型,返回类型自然也没有,return可以返回任何类型。
  2. JS函数不限制传递的参数数量。这表明就算函数的参数列表已确定,照样可以传入多个参数。
  3. JS函数没有重载,如果有同名函数,后一个会覆盖前一个。
实例
  <script>
        // 定义函数,返回传入的参数值
        function getVal(val){
            return val;
        }
        var a = getVal("传入val值", 200); //传入2个参数
        //只定义了两个参数a,b 可以是任何类型
       function method1(arg1, arg2){
            console.log("method1函数值:" + arg1 + "," + arg2);
            console.log("a值:" + a);
       }
    </script>
    <!-- 往method1函数中传入4个参数 -->
    <button οnclick="method1(1, 'abc', 100, true)">点击</button>
    <!-- 控制台输出
        method1函数值:1,abc
        a值:传入val值 
    -->
     通过上面,可以看到尽管定义函数时参数数量已确定,但依然可以往里面传入多个参数,JS不会对其进行检查。看起来无参函数和有参函数似乎没啥区别,反正参数可以随便传。但只有定义了形参,函数内部才能方便地使用定义好的形参。如果函数没有定义形参,你传入一堆参数给无参函数,函数内部无法直接拿到传入的参数值。这时候就只能通过函数内部的arguments对象来获取实参。

关于参数传入数量的问题:
  • 如果传递的参数数量少于函数本身定义的形参数量时,之后的参数值都是undefined,因为没对其传值,就和定义了变量却没赋值一样。
  • 如果是在强类型语言中,这种问题是没有的,所以要注意JS的特性。

 关于arguments对象 

  • arguments是每个函数内部都有的内部对象。函数所有接收的实参都由它来存储管理。取值方式和数组差不多。
 <script>
        //返回所有传入的参数
        function getArgs(){
            var all = "";
            for(var i = 0; i < arguments.length; i++){
                all += arguments[i] + " ";
            }
            return all;
        }
        function show(){
            var allArgs = getArgs("我", 150, new Date(), "ABC", 555);
            console.log(allArgs);
            // 我 150 Wed Sep 13 2017 21:19:53 GMT+0800 (中国标准时间) ABC 555 
        }       
 </script>
 <button οnclick="show()">点击</button>
      通过上面实例,可以看到arguments对象能拿到函数实参,无参函数通过arguments[0] 、argument[1]就能拿到传入的第一个实参和第二个实参。但这种获取实参方式不能乱用。如果规定了形参就使用形参,并且不要多传无用参数。而无参函数就别传入参数,一是无用,二是容易误导,代码写规范点总是没错的。

 JS函数为什么没重载 

  • 首先,先了解重载需要具备的条件:方法名相同,但只要形参类型不相同或者形参数量不相同,都会导致方法重载。至于有无返回值则和重载条件无关。这样就会出现同名但方法不同。
  • 在JS中,函数参数数量没法确定,而且参数类型可以是任意的,如果函数同名,后面的会覆盖前面的。所以JS函数没法实现重载。反过来想,如果JS函数可以重载,那就需要确定参数类型或者参数个数,那这样JS的动态类型就没实际意义了。但可以通过arguments得到参数长度来实现另类重载。

  


  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值