当前位置: 首页 > Web前端 > HTML

JavaScript类型详解!

时间:2023-04-02 22:49:02 HTML

1.关于类型什么是类型?简单的说,类型就是给内存中的一个二进制序列赋予一定的意义。例如二进制序列0100000001110000000101010100101111000110101001111110111110011110被认为是64位无符号整数类型,则为4643234631018606494精度,根据IEEEfloating-4规则,double-4精度表示点数(参见二进制1)对于浮点类型,它是257.331。变量类型大多数计算机语言都使用变量来存储和表示数据。有些语言会为变量指定一个类型,这个类型在整个程序中是不能改变的(无论是在编译时还是运行时)。相比之下,JavaScript和其他一些语言中的变量可以存储任何类型,并且它们使用无类型变量。变量类型是否存在与语法无关。比如C#也提供了var类型的变量,但是下面的语句在C#中会报错:vara=1;a="string";原因是C#的varkey这个词只是省略了变量类型声明,根据初始化表达式自动推断出变量类型,所以C#的var变量还是有类型的。在JavaScript中,您可以随时为特定变量分配任何值,因此JavaScript变量是无类型的。强类型和弱类型根据计算机语言的类型系统的设计方法,可以分为强类型和弱类型。两者的区别在于是否可以在计算时为用户透明隐式地进行不同类型之间的转换。从使用者的角度来看,如果一种语言可以隐式转换它所有的类型,那么当它的变量和表达式参与运算时,即使类型不正确,也可以通过隐式转换得到正确的类型。对于用户来说,似乎所有的类型都可以进行所有的操作,所以这样的语言被称为弱类型。相比之下,强类型语言中的类型之间不一定存在隐式转换(比如C++是强类型语言,但在C++中double和int可以相互转换,但是double和任何类型的指针之间必须becast)为什么有类型?类型可以帮助程序员写出正确的程序,在实际写程序的过程中体现为一种约束。一般规律是约束越强越不容易出错,但写程序的时候越麻烦。具有可变变量的强类型语言具有最强的约束,通常以C++为代表,而具有无类型变量的弱类型语言具有最弱的约束,通常以JavaScript为代表。在JavaScript中,因为约束很弱,所以很容易出现这样的错误:vara=200;变量b="1";变量c=a+b;你可能认为c是201,但实际上它是"2001",这个错误永远不会发生在强类型语言中。但是,正是因为JavaScript没有这些约束,所以可以很容易地拼接数字和字符串类型。因此,约束和灵活性始终是语言设计者需要平衡的一组特性。静态类型和动态类型类型是一种约束,通过类型检查来实现。在不同的语言中,类型检查工作在不同的阶段,可以分为编译时检查和运行时检查。对于JavaScript这样的解释型语言,也有类似编译过程的阶段,即词法分析和语法分析。如果解释型语言的类型检查是在语法分析或前面的阶段完成的,也可以认为类似于编译时检查。所以说静态类型检查和动态类型检查比较合理。有趣的是,虽然很多语言在编译时检查类型,但在运行时仍然可以获取到它的类型信息。例如,元数据用于在C#中存储类型信息。在运行时,用户可以通过反射获取和使用类型信息。信息。灵活性在JavaScript设计的各个方面都是优先考虑的,因此它使用动态类型检查,而JavaScript除了极少数特定操作外,不会主动检查类型。您可以在运行时获取任何变量或表达式的类型信息,并通过程序逻辑检查其正确性。2、JavaScript标准规定的类型JavaScript标准规定了9种类型:UndefinedNullBooleanStringNumberObjectReferenceListCompletion其中3种ReferenceListCompletion只被语言分析运行时使用,不能从程序中直接访问.这里暂不介绍。下面我们可以理解这六种类型:Undefined类型Undefined类型只有一个值undefined,就是变量没有赋值时的值。在JS中,全局对象有一个undefined属性表示未定义。事实上,undefined不是JavaScript关键字。您可以为全局未定义属性赋值以更改其值。Null类型Null类型也只有一个值null,但是JavaScript为它提供了一个关键字null来表示这个唯一值。Null类型的语义是“空对象引用”。Boolean类型Boolean有两个值true和falseString类型String类型的官方解释是16位无符号整数类型的序列,实际用于表示以UTF-16编码的文本信息。Number类型JavaScriptNumber一共有18437736874454810627(即264-253+3)个值。JavaScript的Number以双精度浮点型存储,除了9007199254740990代表NaN,它符合IEEE754(见附录1),占用64位和8个字节。对象类型JavaScript中最复杂的类型是对象,它是一系列属性的无序集合。函数是一个实现了私有属性[[call]]的对象。JavaScript的宿主还可以提供一些特殊的对象。3.JavaScript用户眼中的类型:前面提到了JS标准规定的类型,但是一个不可忽视的问题是JS标准是为JS实现者编写的。对于JS用户来说,类型不一定要按照Standard来定义,比如JS在执行操作的时候会自动将非Object类型转换成它对应的对象,所以"str".length其实等价于(newString("str")).length是的,从这点来看,认为两者属于同一类型也不无道理。我们利用JS中的一些语言特性在运行时进行类型区分,但是这些方法的结果是不同的,你需要决定哪个更好或者哪个更差。typeof——看起来很官方typeof是JS语言中的一个运算符,从它的字面来看,显然是用来获取类型的,按照JavaScript标准,typeof获取的是变量类型名的字符串表示,他有6种可能的结果:string、bool、number、undefined、object、function,JavaScript标准允许实现者自定义一些对象的typeof值。JS标准中有这样一个描述列表:下面这个例子来自51js的Rimifon,展示了IE中typeof的结果产生“date”和“unknown”:varxml=document.createElement("xml");varrs=xml.记录集;rs.Fields.Append("日期",7,1);rs.Fields.Append("bin",205,1);rs.打开();rs.AddNew();rs。Fields.Item("日期").Value=0;rs.Fields.Item("bin").Value=21704;rs.更新();vardate=rs.Fields.Item("date").Value;varbin=rs.Fields.Item("bin").Value;rs.关闭();警报(日期);警报(箱);alert([日期类型,bin类型]);try{alert(date.getDate())}catch(err){alert(err.message)}这种最接近“类型”语义的判断方式其实也有不少非议,其中之一就是它不能区分不同的对象,newString("abc")和newNumber(123)不能用typeof来区分,因为在JS编程中,经常会用到大量的对象,typeof只能给出一个模糊的结果"object”对于所有对象,这使得它的实用性大大降低。instanceof-原型还是类型?instanceof的意思翻译成中文是“aninstanceof...”。从字面上理解为基于类的面向对象编程的术语,而JS实际上并没有在语言层面提供对基于类的编程的支持。JavaScript标准虽然只字未提,但实际上一些内置对象的设计和算子的设置都暗示了一种“官方”的类实现方式,即从函数作为类,当new算子作用于functions,函数的prototype属性设置为新构造对象的原型,函数本身作为构造函数。因此,由同一函数的new操作构造的对象被认为是一个类的实例。这些对象的共同点是:1.具有相同的原型2.由相同的构造函数处理。而instanceof是结合这种实现类的方式来检查“一个实例是否属于一个类”的操作符。通过猜测也可以知道,检查一个对象是否经过构造函数处理是极其困难的,但是检查它的原型是什么就容易多了,所以从原型的角度来理解instanceof的实现,就是检查[[prototype]]属性是否与具体函数的原型一致。注意这里的[[prototype]]是私有属性,在SpiderMonkey(Firefox的JS引擎)中可以通过__proto__来访问。Prototype只对标准描述的Object类型有意义,所以instanceof对所有非Object对象都会getfalse,instanceof只能判断是否属于某个类型,而不能获取类型,但是instanceof的优点是同样显而易见的是,它可以区分自己是由定义的“类”构造的对象。instanceof实际上是可以被欺骗的。它使用的对象私有属性[[prototype]]不能改变,但是函数的原型是一个公共属性。下面的代码展示了如何欺骗instanceoffunctionClassA(){};functionClassB(){};varo=newClassA();//构造一个类A的对象ClassB.prototype=ClassA.prototype;//ClassB.prototypereplacesalert(oinstanceofClassB)//真作弊成功--!Object.prototype.toString——是个好方法吗?Object.prototype.toString本来就很难调用。所有JavaScript内置类都会覆盖toString方法。对于非内置类构造的对象,Object.prototype.toString只能得到无意义的[objectObject]结果。所以在相当长的一段时间里,这个功能的妙用并没有被发现。在标准中,Object.prototype.toString的描述只有3句1.获取这个对象的[[class]]属性2.通过三个字符串"[object",result(1),and"]拼接计算一个"字符串3。返回结果(2)。很明显,Object.prototype.toString其实只是为了获取对象的[[class]]属性,不知道是不是故意的。所有JS内置函数对象StringNumberArrayRegExp...用于构造新对象时,都会设置[[class]]属性,所以[[class]]属性可以很好的作为判断对象的依据类型。因为Object.prototype.toString取了这个对象的属性,所以只需要使用Object.prototype.toString.call或Object.prototype.toString.apply指定这个对象,然后获取类型即可。Object.prototype.toString虽然巧妙,但是无法获取到自定义函数构造的对象的类型,因为自定义函数没有设置[[class]],在程序中是访问不到这个私有属性的。Object.prototype.toString最大的好处就是可以让1和newNumber(1)成为同一类型的对象,而且大部分时候两者的使用方式是一样的。不过值得注意的是,newBoolean(false)参与bool运算时,false的结果正好相反。如果此时将两者视为同一类型,则很容易产生难以检查的错误。总结:为了对以上三种判断方法进行比较,我做了一个表格,方便大家对几种方法有一个整体的比较。为了方便对比,我把几种判断方式得到的结果统一起来:其实很难说以上哪种方式更合理,即使标准中有规定,也只是体现了JS的运行时机制而不是最佳实践。我个人的意见是淡化“类型”这个概念,多关注“我要如何使用这个对象”的约束。在需要的地方使用typeof和instanceof来检查完全可以达到和强类型语言一样的效果。附件1IEEE754规定的双精度浮点数表示法(来自中文维基百科):符号位(symbol):用于表示符号指数(exponent):用于表示幂数尾数(mantissa):用于表示accuracy最后:在学习web前端的过程中,难免会遇到很多问题。这些问题可能会困扰你很长时间。为此,我建了一个web开发学习交流群(545667817),里面全是四部小伙伴,我们整理了最全的前端学习资料,从最基础的HTML+CSS+JS到实际的移动HTML5项目学习资料。任何想学习的人都可以申请加入。大家互相学习,互相交流,共同进步。每日分享不一样的学习资料!