js01为什么我是js?js基本语法、变量和类型转换详解!

什么是javascript?

  • JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。怎么理解?

    • 直译式脚本语言:

      JavaScript是一种解释型的脚本语言,C、C++等语言先编译后执行,而JavaScript是在程序的运行过程中逐行进行解释。

    • 动态类型:

      JavaScript是一种采用事件驱动的脚本语言,它不需要经过Web服务器就可以对用户的输入做出响应。在访问一个网页时,鼠标在网页中进行鼠标点击或上下移、窗口移动等操作JavaScript都可直接对这些事件给出相应的响应。

    • 弱类型

      JavaScript语言中采用的是弱类型的变量类型,对使用的数据类型未做出严格的要求,是基于Java基本语句和控制的脚本语言,其设计简单紧凑。

    • 基于对象

      JavaScript是一种基于对象的脚本语言,它不仅可以创建对象,也能使用现有的对象。

    • 基于原型

      为什么js的介绍会把基于原型提到介绍里,放在这么重要的位置呢?在js里,基于原型是指原型对象这个东西,我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以特定类型的所有实例共享的属性和方法。如果按照字面意思来理解,那么prototype就是通过调用构造函数而创建的那个对象实例的原型对象。

      无论什么时候,只要创建了一个函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认的情况下,所有原型对象都会自动获得一个constructior(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针。

      看不明白?没关系,原型我也不明白!不过我给它标记在了一个位置,它在《JavaScript高级程序设计》第三版的第六章第6节,对象创建小节,147页!

基本语法

  • ECMAscript的语法大量的借鉴了C及类C语言的语法规则,但是语法规则却更加宽松自然,熟悉上述语言的人使用js的时候可定会有一种如鱼得水的感觉!但是我非常不提倡过于依赖这个宽松的语法规则,可能会对其他语言书写时带来一些麻烦!

  • 宽松的变量定义

    为什么我说宽松的语法规则会带来一些麻烦呢?

    var exaBBB="Hello world!";//定义一个字符串变量
    exaBBB=100; //给变量赋值一个数值,而这时exaBBB已经变成一个数值类型的变量,期间会有隐士类型转换!
    
    exaAAA="bad ass";//甚至你不声明也可以随意给个变量赋值,反正引擎会自动声明!!!

    还不仅仅是如此,js对于分号的要求也是不严格的,上面的语句你都不加分号它依然能正常执行在浏览器上!但是其他语言呢!所以,非常不建议依赖这种方式,而且,在后期代码压缩去掉空格和换行之后,不加分号会引起世界末日式的错误!

数值类型

  • typeof操作符

    使用typeof (变量名)typeof 变量名并将其打印出来就可以看出变量的具体类型。

  • 类型
    1. ”undefined”–值未定义;
    2. “boolean”–布尔类型;
    3. “string”–字符串;
    4. “number”–数值型(数字);
    5. “object”–对象或者null;
    6. “function”–函数;
  • undefined类型

    • 怎样会使类型成为undefined?

      1. 声明了变量没有赋值var example;
      2. 为声明了的变量赋值undefinedvar example = undefined;
      3. 以为未声明、未赋值的变量被使用
        var example;
        
        //var message;
        
        alert(example);//example声明了未赋值,为undefined。
        alert(message);//message在注释里没有声明,报错!
        alert(typeof message);//调用delete会使其不会报错,但是在严格模式下依然会报错
        //至于为什么使用typeof后就不会了,后面有个详细的讲解。
        console.log(typeof example);//打印出undefined
        console.log(typeof(message));//打印出undefined
  • null类型

    通过var car=null给一个变量赋null类型,在逻辑上来看,null是一个空对象的指针,所以typeof操作符检测null时会返回一个object。如下:

    var car=null;
    alert(typeof car);//object

    而实际上,undefined是从null派生出来的值,所以在做一个比较的时候,ECMA-262规定了它们是相等的:

    alert(null==undefined);//true
  • Boolean 类型

    Boolean在js可以说用的非常多的值了,但是它非常简单,只有true和false两个值!这与其他语言,尤其是c语言不一样,大家一定要分别清楚!在c语言中,定义的真假不仅仅包括布尔值,还有0,1等等,信奉非0即真,但是js中严格的要求了真假的值,所以大家一定要分清楚!

    虽然js里面的布尔值只有true和false两个值,但是其他的类型的值都有与Boolean值等价的,可以通过Boolean()函数转型:

    var message="hello world!";
    var messageBoolean=Boolean(message);

    其他类型数值转换表:

    数据类型 转换为true的条件 转换为false的条件
    Boolean true false
    String 任何非空字符串 “”空字符串
    Number 任何非零数值(包括无穷大) 0和NaN
    Object 任何对象 null
    Undefined no application undefined

    实际上很多时候都是在类型转换的时候用到布尔值,因此上面的这个表非常有用。而且很多时候都会用到隐式的布尔类型转换,如if判断的时候都会自动执行Boolean()的转换!

  • Number类型

    Number类型也是js中最常用的最受关注的类型了,但是js中宽松的变量定义并没有给变量定义数值类型,所以,如何在解析的时候能准确的辨析数值类型就非常重要。
    虽然js中没有定义变量类型,但是我们需要知道变量基本的类型:
    整型(int)、浮点型(float,有些语言也有双精度浮点型的说法)、字符(char)、字符串(string)等。如在c语言的这一类语言中,定义具体的变量类型是为了给变量相应的内存空间、字节大小等,而js可谓相当智能,所以不用考虑的这么复杂,就不需要再声明变量的时候给予明确的类型,而且js也会自动的根据你给的值给变量定义准确的变量类型!

    特殊的数值定义:

    var intNum=55;//int型,整型
    
    var octalNum1=070; //八进制的56,以八进制的规则成对赋值可以给变量赋八进制数的值
    var octalNum2=079;//无效的八进制数,解析为79,自动去除前面的0。
    var octalNum3=08;//无效的八进制数,解析为8
    
    var hexNum1=0xA;//十六进制的10
    var hexNum2=0xA;//十六进制的31

    在定义的时候虽然都可以这样赋值,但是计算的时候依然会按照十进制数值进行计算。

    在js中还可以保存”+0”和”-0”两个值,并且认为它们是相等的!

  • 浮点数值

    1. 浮点类型赋值:

      var floatNum1=1.1;
      var floatNum2=0.1;
      var floatNum3=.1;//有效,但是不规范,不推荐
    2. 浮点类型解析

      var floatNum1=1.;//小数点后没有数字解析为整数--1
      var floatNum2=10.0;//小数点后面为0解析为整数--10
      var floatNum3=3.125e7;//科学计数,等于3.125x10^7,值为31250000
    3. 怪异的浮点计算

    浮点的最高精度是小数点后的第17位小数,但是计算精度却非常的奇怪,比如0.1+0.2不等于0.3而是0.300000000000004。这是个小小的舍入误差,但是却对浮点值的引用造成了非常大影响!因此,将浮点数作为if的判断条件时一定要慎重考虑!或者干脆不要用浮点作为判断条件!

    if(a+b==0.3){ //不要这样,雅蠛蝶!
        alert("you got 0.3!");
    }
  • String类型

    String类型用于表示由零或者多个16个Unicode字符组成的字符序列,即字符串。字符串可以由引号(“”)单引号(”)表示,但是两种引号必须成对出现。

    var examString="Hello world!';//错误
    
    var examString="Hello world!";
    var examString='Hello world!';
    • 字符字面量

      String数据类型好汉一些特殊的字符字面量,也成为转义序列,用于表示非打印字符,用于表示其他用途的字符。如:’\n”\t’等,另外还有一些字符实体用于表示特殊字符等等,详细请查看我 上一期的笔记的最后面一部分内容!

    • 字符串特点

      在ECMAscript中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变,要改变某个变量保存的字符串,就必须销毁原来的字符串,然后再用另一个新的字符串值填充该变量:

      var lang="Java";
      lang=lang+"script";

      如上,整个代码过程操作:首先,创建一个能容纳10个字符的新字符串,然后在这个字符串中填充”java”和”script”,最后一步是销毁原来的字符串”java”和字符串”script”,因为这两个字符串已经没有用了。

  • Object类型

    Object(对象),在ECMAscript中的对象就是一组数据和功能的集合。

    • 创建一个对象

      var objExam=new Object();//当然,如果不需要向构造函数传递参数,则可以不加括号,但只是不推荐的!
      var objExam=new Object;//这是不推荐的
    • Object的每个实例都具有下列属性和方法:

      • constructor:保存着用于创建当前对象的函数。对于前面的例子而言,构造函数(constructor)就是Object();
      • hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例的原型中–>原型模式暂不仔细了解以后的笔记再做仔细解释)是否存在。参数properttyName必须是个字符串;
      • isPrototypeOf(Object):用于检查传入的对象是否当前对象的原型。
      • propertyIsEnumerable(propertyName):拥有检查给定的属性是否能用于for-in语句来枚举。与hasOwnProperty()一样,参数需为字符串;
      • toLocaleString():返回对象的额字符串表示,该字符串与执行环境的地区对应。
      • toString():返回对象以字符串表示;
      • valueOf():返回对象的字符串、数值或布尔值表示。
  • 数值范围

    每一门语言的使用都是基于内存空间的,即使js非常智能也不能摆脱内存空间的限制,在大多数浏览器中,ECMAscript能够表示的最小值保存在Number.MIN_VALUE中,这个值为5e-324(5x10^-324);当然,最大的值保存在了Number.MAX_VALUE中,这个值为1.7976931348623157e+308;如果某次计算的值超过上述的范围,则会自动的被赋值为Infinity和-infinity然后中断一切接下来的运算。

  • NaN(Not a Number)

    • 基本概念

      NaN,即非数值,是一个特殊的存在,这个用于表示一个本来要返回数值的操作数却离奇的失踪而没有返回数值的情况(这个我认为反而是个亮点,为什么呢?当一个程序自上而下执行的时候,当本该有返回值的地方没有返回值,在其他语言必定会报错或者trycatch抛出异常,但是js非常完美的返回了一个非数值,这样就可以不影响程序的继续执行,保证文档的其他内容不会受到影响!)

    • 特点

      1.任何涉及NaN的操作(如:NaN/10)都会返回NaN;

      2.NaN与任何数值都不相等,包括它(NaN)本身!

      alert(NaN==NaN);//false
    • isNaN()函数

      既然NaN连本身都不相等,那么怎么判断呢?js给出了个用于判断返回值是不是NaN的函数,就是isNaN()函数:

      alert(isNaN(NaN));//true
      alert(isNaN(10));//false
      alert(isNaN("10"));//false
      alert(isNaN("blue"));//true
      alert(isNaN(true));//false

      是不是有那么一丝的不可思议?那是因为isNaN()是基于对象的,而基于对象的调用isNaN()的时候,会首先调用对象的valueof()方法,然后调用数值转换方法确定是不是数值,如果还不能,则调用toString()方法转换为字符串再进行返回值测试。相应的转换规则我也会在后面详细解释。

    在ECMAScript中,Object是所有对象的基础,因此所有对象都具有这些基本的属性和方法。

类型转换和他们的”潜规则”

  • 数值类型转换

    在所有的编程语言中,数字类型是最为广泛的类型,尤其是在js这门弱类型定义的语言中,数值转换就变得尤为重要,所以,js的标准中,为大家定义了三个可以用于进行数值转换的基本函数: Number()、parseInt()和parseFloat()。接下来让我们一个一个了解他们!

Number()函数

Number()函数适用于所有的数据,可以将所有的东西塞进他的参数里!

  • 如果是Boolean值,true和false分别转换为1和0,但是这个1,0本身的真假关系无关!!!!!
  • 如果是数字值,只是简单的传入和返回;
  • 如果是null值,返回0;
  • 如果是字符串,则遵循以下规则:
    • 如果字符串中包含数字(包括前面带的正负号),则将其转换为十进制数,如:”1”会变成1,”123”会变成123,而”011”会变成11,前缀的0会被自动忽略;
    • 如果字符串中包含有效的浮点格式,如”1.1”,则将其转换为对应的浮点数值(同样会忽略前缀0);
    • 如果字符串是空的,则返回0;
    • 如果字符串包含以上格式之外的字符,返回NaN;
      +如果转换的是对象,则先调用valueOf()方法,依照前面的规则返回值。如果转化的结果为NaN则会按照NaN的规则调用toString()方法,在依次按照前面的规则进行转换。
var num1= Number("Hello world!"); //NaN
var num1= Number(""); //0
var num1= Number("00000011");//11
var num1= Number("true");//1

但是对于Number()是可以用一个东西替代的,那就是一元操作符 “+/-“,我会在下一个笔记里仔细讲解。

parseInt()函数和parseFloat()函数

  • parseInt()函数

    与Number()不同的是,parseInt()函数和parseFloat()都是专门针对字符串进行转换的,为的是更高的精度!

    parseInt()的规则很简单,对于字符串而言,只有数字打头和非数字打头两种。这就变得十分简单了,如果是以数字打头的字符串,函数会从第一数字字符开始解读,一直遇到第一个非数字字符或者全部解析完为止;如果是以非数字字符打头,则函数返回NaN。而parseInt也可以将二进制,八进制,十六进制进行解析:

    var num=parseInt("12345blue");//12345
    var num=parseInt("22.5");//22,小数点也是非数字字符
    var num=parseInt("0xA");//10(十六进制数)
    var num=parseInt("070");//56(八进制数)
    var num=parseInt("70");//70(十进制数)
    var num=parseInt("0xf");//15(十六进制数)
    var num=parseInt("");//NaN

    而parseInt()还有个更高明的地方,看到上面的例子,是不是觉得八进制十进制和十六进制之间如果哦都是符合要求的数字时到底如何转换呢?js标准给parseInt()增加了一个实用的参数–数值基数:

    var num=parseInt("0xAF",16);//175
    var num=parseInt("AF",16);//175
    var num=parseInt("AF");//NaN
    
    //如果还不够明显
    var num=parseInt("10",2);//2
    var num=parseInt("10",8);//8
    var num=parseInt("10",10);//10
    var num=parseInt("10",16);//16

因此,为了避免解析错误,得到更精确的值,我坚决推荐在使用parseInt()的时候加上数值基数!

  • parseFloat()函数

    parseFloat()和parseInt()主要有两个区别:

    • 第一个小数点有效,如果字符串里只有第一个小数点是有效的,如果后面遇到的第一个非数值字符和第二个小数点,则解析结束!
    • 如果字符串包含的是一个可解析为整数的数(没有小数点或小数点后面都是0),parseFloat()会返回一个整数。
      var num=parseFloat("12345blue");//12345
      var num=parseFloat("22.5");//22.5
      var num=parseFloat("22.34.5");//22.34
      var num=parseFloat("0xA");//0
      var num=parseFloat("3.125e7");//等值于3.125^7,为31250000

    仔细对比两个函数的区别和例子,是不是很清晰了?仔细思考你就会发现,他们直接包含着变量定义赋值的”潜规则”!

字符串类型转换

转换为字符串也有两个不一样的函数toString()和String(),他们的主要区别也是在于传递参考基数。

toString()函数

  • toString()的基数

    和parseInt()一样,toString()函数也可以传递一个基数作为guide进行解析,我们直接来看显然的例子:

    var num=10;
    alert(num.toString());//"10" 默认以10进制解析
    alert(num.toString(2));//"1010"
    alert(num.toString(8));//"12"
    alert(num.toString(10));//"10"
    alert(num.toString(16));//"a"

    对于toString()而言,基本每一个数值、布尔值、对象等都有它的toString()函数,但是可怜的null和undefined却不包括在内!

  • String()函数

    String()函数真说不清楚算是个小弟还是大哥,因为它非常的取巧,因为:

    • 如果值有toString()函数,则调用该方法的默认函数(没有基数);
    • 如果值是null,则返回”null”;
    • 如果值是undefined,则返回”undefined”;
    var value1=10;
    var value2=true;
    var value3=null;
    var value4;
    
    alert(String(value1));//"10"
    alert(String(value2));//"true"
    alert(String(value3));//"null"
    alert(String(value4));//"undefined"

    同样,对于字符串的转换也被一元操作符”+/-“恐怖的支配!

下节笔记预告:操作符、作用域和基本函数

猜你喜欢

转载自blog.csdn.net/qq_32842925/article/details/80355205