美文网首页
第3章 基本概念

第3章 基本概念

作者: meiqiuyang | 来源:发表于2018-04-19 22:49 被阅读0次

    本章内容

    • 语法
    • 数据类型
    • 流控制语句
    • 理解函数

    1 语法
    1.1 区分大小写
    ECMAScript中的一切(变量 、函数和操作符)都区分大小写。
    1.2 标识符
    标识符,就是指变量、函数、属性的名字,或者函数的参数。

    标识符的格式

    • 第一个字符必须是字母、下划线(_)或者一个美元的符号($)
    • 其他字符可以是字母、下划线、美元符号或数字

    标识符的格式采用驼峰大小写格式,也就是说第一个字母小写,剩下的每个有意义的单词的首字母大写,例如:

    firstSecond
    myCar
    doSomethingImportant

    注意,不能把关键字、保留字、true、false和null用作标识符

    1.3 注释
    ECMAScript使用C风格的注释,包括单行注释和块级注释。
    单行注释

    // 单行注释
    

    块级注释

    /*
     * 这是一行
     * [块级]注释
     */
    

    当然,目前IDE注释都很方便,了解即可。

    1.4 严格模式
    JavaScript 严格模式(strict mode)即在严格的条件下运行
    "use strict" 的目的是指定代码在严格条件下执行

    "use strict";
    x = 3.14;       // 报错 (x 未定义)
    
    "use strict";
    myFunction();
    
    function myFunction() {
        y = 3.14;   // 报错 (y 未定义)
    }
    
    x = 3.14;       // 不报错 
    myFunction();
    
    function myFunction() {
       "use strict";
        y = 3.14;   // 报错 (y 未定义)
    }
    

    为什么使用严格模式:

    • 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
    • 消除代码运行的一些不安全之处,保证代码运行的安全;
    • 提高编译器效率,增加运行速度;
    • 为未来新版本的Javascript做好铺垫。

    参考阮一峰的Javascript 严格模式详解

    1.5 语句
    ECMAScript中的语句以一个分号结尾;如果省略分号,则由解析器确定语句的结尾,如下图所示

    var sum = a + b      //即使没有分号,也是有效的语句
    var diff = a - b;    //有效语句
    

    这本书上说,建议任何时候都不要省略分号。因为加上这个分号可以避免很多错误,开发人员也可以放心地来压缩代码。
    另外,用分号一定程度上可以提高性能,因为解析器就不需要再花时间推测该在哪里插入分号了。

    还有,使用{}来将多条语句组合到一个代码块中。

    在控制语句中,使用代码块可以让编码意图更加清晰,而且也能降低修改代码时出错的几率。

    2 关键字和保留字
    abstract
    arguments
    boolean
    break
    byte
    case
    catch
    char
    class*
    const
    continue
    debugger
    default
    delete
    do
    double
    else
    enum*
    eval
    export*
    extends*
    false
    final
    finally
    float
    for
    function
    goto
    if
    implements
    import*
    in
    instanceof
    int
    interface
    let
    long
    native
    new
    null
    package
    private
    protected
    public
    return
    short
    static
    super*
    switch
    synchronized
    this
    throw
    throws
    transient
    true
    try
    typeof
    var
    void
    volatile
    while
    with
    yield

    反正,写代码的时候,如果用错标识符,IDE会提醒你的,了解就好,😱不需要背下来。

    3 变量
    ECMAScript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。

    4 数据类型
    ECMAScript中有5种简单数据类型(基本数据类型):Undefined、Null、Number和String。还有1种复杂数据类型——Object,它的本质上是由一组无序的键值对组成的。
    ECMAScript不支持任何床见自定义类型的机制,而所有值最终都是上述6种数据类型之一。由于ECMAScrip数据类型具有动态性,因此的确没有再定义其他数据类型的必要了。
    这里说的动态性,指的是数据类型可以扩展出任何类型,如object,可以动态添加属性与方法。
    4.1 typeof操作符
    鉴于ECMAScript是松散类型的,因此需要来检测给定的变量的数据类型,typeof就是负责提供这方面信息的操作符。对一个值使用typeof操作符可能返回下列某个字符串:

    • "undefined"——这个值未定义;
    • "boolean"——这个值是布尔值;
    • "string"——这个值是字符串;
    • "number"——这个值是数值;
    • "object"——这个值是对象或null;
    • "function"——这个值是函数。
      例子:
    var message = "some string";
    alert(typeof message);//"string"
    alert(typeof(message));//"string"
    alert(typeof 95);//"number"
    

    这几个例子说明,typeof操作符的操作数可以是变量(message),也可以是数值字面量。注意,typeof是一个操作符而不是函数,因此例子中的圆括号尽管可以使用,但不是必须的。
    4.2 Undefined类型
    Undefined类型只有一个值,即特殊的undefined。在使用var声明变量但未对其初始化时,这个变量的值就是undefined,例如:

    var message;
    alert(message == undefined);//true
    

    4.3 Null类型
    Null类是第二个只有一个值的数据类型,这个特殊的值是null。从逻辑角度来看,null值表示一个空对象指针,而这也正是使用typeof操作符检测null值时会返回"object"的原因。
    如果定义的变量准被在将来用于保存对象,那么最好将该变量初始化为null。这样一来,只要直接检查null值就可以知道相应的变量时候已经保存了一个对象的引用了。

    4.4 Boolean类型
    该类型只有两个字面值:true和false。这两个值与数字值不是同一回事,因此true不一定等于1,而false也不一定等于0。

    虽然Boolean类型的字面值只有两个,但ECMAScript中所有类型的值都有与这两个Boolean值等价的值,可以调用转类型函数Boolean()。
    下表给出了各种数据类型及其对应的转换规则。

    数据类型 转换为true值 转换为false的值
    Boolean true false
    String 任何非空字符串 空字符串("")
    Number 任何非零数字值(包括无穷大或无穷小) 0和NaN(不是数字)
    Object 任何对象 null
    Undefined 不适用 undefined

    这些转换规则在流控制语句(如if语句)有很重要的作用

    4.5 Number类型
    这种类型使用IEEE754格式来表示整数和浮点数值(浮点数值在某些语言中也被称为双精度数值)。
    最基本的数值字面量格式是十进制。
    除了以十进制表示外,整数还可以通过八进制(以8为基数)</span>或十六进制(以16进制)关于二进制,八进制,十进制和十六进制的说明
    其中,八进制字面值的第一位必须是0,然后是八进制数值序列(0~7)。如果字面值中的数值超出了范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析。例子:

    var octalNum1 = 070;//八进制的56
    var octalNum2 = 079;//无效的八进制数值——解析为79
    var octalNum3 = 08;//无效的八进制数值——解析为8
    

    八进制字面量在严格模式下是无效的,会导致支持的JavaScript引擎抛出错误。

    十六进制字面值的前两位必须是0x,后面跟任何十六进制数值(09及AF)。其中,字母A~F可以大写,也可以小写。例子:

    var hexNum1 = 0xA;//十六进制的10
    var hexNum2 = 0x1f;//十六进制的31
    

    在进行算数计算时,所有以八进制和十六进制表示的数值最终都将被转换成十进制数值。

    4.5.1 浮点数值
    所谓浮点数值,就是该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字。例子:

    var floatNum1 = 1.1;
    var floatNum2 = 0.1;
    var floatNum3 = .1;//有效,但不推荐
    

    由于保存浮点数值需要的内存空间是保存整数值的两倍,因此ECMAScript会不失时机地将浮点数值转换为整数值。例子:

    var floatNum1 = 1.;//小数点后面没有数字——解析为1
    var floatNum2 = 10.0;//整数——解析为10
    

    对于那些极大或者极小的数值,可以用e表示法(科学计数法)。用e表示法表示的数值等于e前面的数值乘以10的指数次幂。例子:

    var floatNum1 = 3.125e7;//等于31250000
    var floatNum2 = 3.125E7;//e不区分大小写
    var floatNum3 = 3e-7;//等于0.0000003
    

    浮点数值的最高精度是17位小数,但是在进行算术计算时其精确度远远不如整数。

    var a = 0.1;
    var b = 0.2;
    if (a + b == 0.3) {//不要做这样的测试,因为你不能成功的
        alert("You got 0.3");
    }
    console.log(a + b);//0.30000000000000004
    

    4.5.2 数值范围
    由于内存限制,ECMAScript不能保存世界上所有的数值。ECMAScript能够表示的最小数值保存在Number.MIN_VALUE中;能够表示的最大数值保存在Number.MAX_VALUE中。如果某次计算的寄过得到了一个超出ECMAScript数值范围的值,那么这个数值将被自动转换成特殊的Infinity值。具体来说,如果这个值是负数,则会转换成-Infinity(负无穷),反之,则会被转成Infinity(正无穷)。
    如上所述,如果某次计算返回了正或负的Infinity值,那么该值将无法参与下一次的计算。可以通过isFinite()来判断,例子:

    var result = Number.MAX_VALUE + Number.MAX_VALUE;
    console.log(isFinite(result));//false
    

    4.5.3 NaN
    这个就是Not a Number,翻译过来就是不是数值,在ECMAScript中,它是一个特殊的数值,表示本来应该返回数值的操作,结果么有返回数值,防止抛出异常。

    • NaN与任何值都不相等,包括它本身
    • 任何涉及到与NaN的操作,都会返回NaN。

    增对这两个特点,ECMAScript定义了isNaN()函数。这个函数可以帮我们确定参数是否“不是数值”。即,任何不能被转换为数值的参数都会导致这个函数返回true。例子:

    console.log(isNaN(NaN)); //true
    console.log(isNaN(10)); //false
    console.log(isNaN("10")); //false(可以被转换成数值10)
    console.log(isNaN("blue")); //true(不能被转换成数值)
    console.log(isNaN(true));//false(可以被转换成数值1)
    

    isNaN()也适用于对像。在基于对象调用isNaN()函数时,会首先调用对象的valueOf()方法,然后确定该方法返回的值是否可以转换为数值。如果不能,则基于这个返回值再调用toString()方法,再测试返回值。

    4.5.4 数值转换
    Number()、parseInt()和parseFloat()这三个函数可以把非数值转换为数值。

    Number(),即转型函数,它可以用于任何数据类型,它的转换规则如下:

    • 如果是Boolean值,true和false将分别转换为1和0.
    • 如果是数值,只是简单的输入和输出。
    • 如果是null值,返回0。
    • 如果是undefined,返回NaN。
    • 如果是字符串,遵循以下规则:
      1,如果字符串中只包含数字(包括前面带上加号或减号),则将其转换为十进制数值。
      2,如果字符串是有效的浮点格式,如“1.1”,则将其转换为对应的浮点数值。
      3,如果字符串中是有效的十六进制格式,例如“0xf”,则将其转换为对应的十进制数值。
      4,如果字符串是空的,则将其转换为0。
      5,如果字符串包含上述格式之外的字符,则将其转换为NaN。
      *如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再依照前面的规则转换返回的字符串的值。
      例子:
    console.log(Number(true));//1
    console.log(Number(false));//0
    console.log(Number(1));//1
    console.log(Number(null));//0
    console.log(Number(undefined));//NaN
    console.log(Number("1"));//1
    console.log(Number("00001"));//1
    console.log(Number("1.1"));//1.1
    console.log(Number("00001.1"));//1.1
    console.log(Number("0xf"));//15
    console.log(Number(""));//0
    console.log(Number("1abc1.1"));//NaN
    

    parseInt(),它在转字符串时,更多的时看其是否符合数值模式。他会忽略字符串前面的空格,只倒找到第一个非空格字符。如果第一个字符不是数字字符或者正负号,它就会返回NaN;也就是说parseInt()转换空字符串会返回NaN(Number()会返回0)。如果第一个字符是数字字符,parseInt()会继续解析第二个字符,直到解析完所有的后续字符或者遇到了一个非数字字符。例如,“123木头人”会被转换为123。类似的“123.5”会被转换为123,因为小数点不是有效的数字字符。
    另外,如果字符串以“0x”开头且后面跟数字字符,就会将其当成一个十六进制的整数;如果字符串以“0”开头且后面跟数字字符,就会将其当成一个八进制数来解析。
    例子:

    console.log(parseInt(""));//NaN
    console.log(parseInt("123木头人"));//123
    console.log(parseInt("123.5"));//123
    console.log(parseInt("0xA"));//10
    console.log(parseInt("070"));//70,有问题哦,请注意
    console.log(parseInt("080"));//80,如属于八进制
    console.log(parseInt("0xG"));//NaN,不属于十六进制
    

    这里就有一个问题了,如上文所说,如果是以0开头的且后面跟数字字符,就会当成一个八进制来解析,但是parseInt("070")在我的最新版chrome浏览器中被解析为70而不是56,为啥呢?其实是在ECMAScript 3 JavaScript引擎中,“070”是被当成八进制字面量,但是在ECMAScript 5 JavaScript引擎中,parseInt()已经不具有解析八进制的能力了,因此,前面的零会被认为无效。
    但是如果我硬要解析八进制咋整?parseInt()这个函数提供了第二个参数:转换时使用的基数(即多少进制)。例子:

    console.log(parseInt("0xAF",16));//175
    console.log(parseInt("AF",16));//175,因为明确知道了以十六进制进行解析,那么“0x”就不需要了
    console.log(parseInt("10",2));//2
    console.log(parseInt("10",8));//8
    console.log(parseInt("10",10));//10
    console.log(parseInt("10",16));//16
    

    parseFloat(),与parseInt()类似,它是从第一个字符开始解析每个字符,而且也是一直解析到字符串末尾,或者遇到一个无效的浮点数字字符为止。也就是说,字符串的第一个小数点是有效的,而第二个小数点就是无效的了。除了第一个小数点有效外,parseFloat()和parseInt()的第二个区别在于它始终都会忽略前导的零,只能解析十进制。注意点:如果字符串包含的是一个可解析为整数的数,它就会返回整数。例子:

    console.log(parseFloat("123木头人"));//123
    console.log(parseFloat("0xA"));//0
    console.log(parseFloat("22.5"));//22.5
    console.log(parseFloat("22.34.5"));//22.34
    console.log(parseFloat("0908.5"));//908.5
    console.log(parseFloat("2.125e7"));//31250000
    
    字面量 含义
    \n 换行
    \t 制表
    \b 退格
    \r 回车
    \f 进纸
    \ 斜杠
    \' 单引号('),在用单引号表示的字符串中使用。例如:'He said,\'hey.\''
    \" 双引号("),在用双引号表示的字符串中使用。例如:"He said,\"hey.\""
    \xnn 以十六进制代码表示的一个字符(其中n为0~F)。例如,\x41表示“A”
    \unnn 以十六进制代码nnn表示的一个Unicode字符(其中n为0~F)。例如,\u03a3表示希腊字符Σ

    4.6 String类型
    String类型用于表示由零或多个16为Unicode字符组成的字符序列,即字符串。字符串可以由双引号或者单引号表示。
    4.6.1 字符字面量
    String数据类型包含一些特殊的字符字面量,也叫转义序列,用于表示非打印字符,或者具有其他用途的字符。如下表:

    字面量 含义
    \n 换行
    \t 制表
    \b 退格
    \r 回车
    \f 进纸
    \ 斜杠
    \' 单引号('),在用单引号表示的字符串中使用。例如:'He said,\'hey.\''
    \" 双引号("),在用双引号表示的字符串中使用。例如:"He said,\"hey.\""
    \xnn 以十六进制代码表示的一个字符(其中n为0~F)。例如,\x41表示“A”
    \unnn 以十六进制代码nnn表示的一个Unicode字符(其中n为0~F)。例如,\u03a3表示希腊字符Σ

    这些字符字面量可以出现在字符串中的任意位置,而且也将被看作一个字符来解析,例子:

    var test ='This is the letter sigma: \u03a3.';
    console.log(test.length);
    

    这个例子中的变量text有28个字符,其中6个字符长的转义序列被作为1个字符。
    当然,如果字符串中包含双字节字符,那么length属性可能不会精确地返回字符串中的字符数目。

    4.6.2 字符串的特点
    ECMAScript中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变摸个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量。
    例子:

    var lang = 'Java';
    lang = lang + 'Script';
    

    实现这个操做过程如下:首先创建一个能容纳10个字符的新字符串,然后在这个字符串中填充“Java”和“Script”,最后一步是销毁元来的字符串“Java”和字符串“Script”,因为他们两个已经么有用了。这也就是很老旧的浏览器版本(例如版本低于1.0的FireFox、IE6等)拼接字符串会慢的原因。但是这些浏览器后来的版本已经解决了这个低效率的问题。

    4.6.3 转换为字符串
    把一个值转换成字符串有两种方式:

    • 方法一,toString(),数字、布尔值、对象和字符串都有toString()方法。但null和undefined值么有这个方法。
      调用toString()方法时,可以传递一个参数,即输出数值的基数。默认以十进制格式返回数值的字符串表示。它可以输出二进制、八进制、十六进制,乃至其他任意有效进制格式表示的字符串值。例子:
    var num = 10;
    console.log(num.toString());//"10"
    console.log(num.toString(2));//"1010"
    console.log(num.toString(8));//"12"
    console.log(num.toString(10));//"10"
    console.log(num.toString(16));//"a"
    
    • 方法二,String(),转型函数,如同Number(),能够将任何类型的数值转成字符串,转换规则:
      • 如果值有toString()方法,则调用该方法,并返回相应的结果;
      • 如果值是null,则返回“null”;
      • 如果值是undefined,则返回“undefined”。

    4.7 Object类型
    ECMAScript中的对象其实就是一组数据和功能的集合。Object类型是所有它的实例的基础。换句话说,Object类型所具有的任何属性和方法也同样存在与更具体的对象中。
    Object的每个实例都具有下列属性和方法。

    • constructor:保存着用于创建当前对象的函数。构造函数(constructor)就是Object()。
    • hasOwnProperty(propertyName):用于检查给定的属性再当前对象实例中(而不是再实例的原型中)是否存在。
    • isPrototypeOf(object):用于检查传入的对象是否是当前对象的原型。(后面会讨论到原型)
    • propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。
    • toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。
    • toString():返回对象的字符串表示。
    • valueOf():返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同。

    5 操作符
    ECMA-262描述了一组用户操做数据只的操作符,包括算术操作符、位操作符、关系操作符和相等操作符。他们能够适用于很多值,例如字符串、数字值、布尔值,甚至于对象。不过,再应用于对象时,相应的操作符通常都会调用对象的valueOf()和(或)toString()方法,以便取得可以操做的值。
    5.1 一元操作符
    只能操做一个值的操作符叫做一元操作符
    1 递增和递减操作符
    递增和递减借鉴与C,而且各有两个版本:前置型和后置型。
    前置型:

    var age= 28;
    ++age;
    age = age + 1;
    --age;
    age = age - 1;
    
    var age = 28;
    var anotherAge = --age + 2;
    
    console.log(age);//27
    console.log(anotherAge);//29
    

    后置型:

    var age = 28;
    age++;
    age--;
    
    var num1 = 2;
    var num2 = 20;
    
    var num3 = num1-- + num2;//22
    var num4 = num1 + num2;//21
    

    上面的例子,应该明白了前置和后置的区别。

    所有这4个操作符对任何值都适用,也就是说它们不仅仅适用于整数,还可以用于字符串、布尔值、浮点数值和对象。在应用于不同的值时,递增和递减操作符遵循下列规则。

    • 在应用于一个包含有效数字字符的字符串时,先将其转换为数字值,再执行加减1的操作。字符串变量变成数值变量。
    • 在应用于一个不包含有效数字字符的字符串时,将变量的值设置为NaN。字符串变量变成数值变量。
    • 在应用于布尔值false时,先将其转换为0再执行加减1的操作。布尔值变量变成数值变量。
    • 在应用于布尔值true时,先将其转换为1再执行加减1的操作。布尔值变量变成数值变量。
    • 在应用于浮点数值时,执行加减1的操作。
    • 在应用于对象时,先调用对象的valueOf()方法以取得一个可供操作的值,然后对该值进行前述规则。如果是时NaN,则再调用toString()方法后再应用前述规则。对象变量变成数值变量。
      例子:
    
    var s1 = "2";
    var s2 = "A";
    var b1 = false;
    var b2 = true;
    var f = 1.1;
    var o = {
        valueOf: function () {
            return -2;
        }
    };
    console.log(++s1);//3
    console.log(++s2);//NaN
    console.log(++b1);//1
    console.log(++b2);//0
    console.log(--f);//0.10000000000000009(由于浮点舍入错误所致)
    console.log(--o);//-2
    
    var s3 = "2";
    var s4 = "A";
    var b3 = false;
    var b4 = true;
    var f1 = 1.1;
    var o1 = {
        valueOf: function () {
            return -2;
        }
    };
    
    console.log(s3++);//2
    console.log(s4++);//NaN
    console.log(b3++);//0
    console.log(b4++);//1
    console.log(f1--);//1.1
    console.log(o1--);//-1
    

    2 一元加和减操作符
    简单说,一元加操作符(+)放在数值前面,对数值不会产生任何影响。一元减操作符主要用于表示负数。
    例子:

    var s1 = "1";
    var s2 = "1.1";
    var s3 = "a";
    var b = false;
    var f = 1.1;
    var o = {
        valueOf: function () {
            return -1;
        }
    };
    
    console.log(+s1);//1
    console.log(+s2);//1.1
    console.log(+s3);//NaN
    console.log(+b);//0
    console.log(+f);//1.1
    console.log(+o);//-1
    
    console.log(-s1);//-1
    console.log(-s2);//1.1
    console.log(-s3);//NaN
    console.log(-b);//-0
    console.log(-f);//-1.1
    console.log(-o);//1
    

    相关文章

      网友评论

          本文标题:第3章 基本概念

          本文链接:https://www.haomeiwen.com/subject/pduqkftx.html