美文网首页
JavaScript语法

JavaScript语法

作者: Viaphlyn | 来源:发表于2017-09-09 22:49 被阅读19次

    一、基本语法

    1. 语句

    • 1.1 每一行是一个语句,语句不需返回值,表达式有返回值。

    2. 变量

    • 2.1 严格地说,var a = 1 与 a = 1是不完全一样,delete命令无法删除前者。不用var声明的语句不利于表达意图,且容易创建全局变量。
    • 2.2 用var声明同一个变量并赋值有覆盖性。
    • 2.3 用var命令声明的变量存在变量提升,声明语句都会被提升到代码的头部。

    3. 标识符

    • 3.1 变量名首个不能是数字,不能包含 * 和运算符,不能用保留字,大小写是不同的,中文可做变量名。

    4. 注释

    • 4.1 也可用html的单行注释(在行首,否则为运算符)。

    5、区块

    • 5.1 JavaScript的区块不构成单独的作用域。

    6、语句点

    • 6.1 else代码块总是跟随离自己最近的那个if语句。
    • 6.2 switch、case语句都可以使用表达式,在比较运行结果时,采用的是===,而不是==,比较时不会发生类型转换。

    二、数据类型

    1. 对象

    • 狭义的对象(object)
    • 数组(array)
    • 函数(function)

    2. 类型

    • number、string、boolean、function、undefined、object(空数组和null也是)

    3. 三种确定类型方法

    • typeof运算符
    • instanceof运算符
    • Object.prototype.toString方法

    4. 布尔值

    • false: undefined、null、false、0、NaN、 " "或' '(空字符串)
    • ture :特别注意空数组([])和空对象({})

    三、数值

    1. 数值范围

    1.1 所有数字都是以64位浮点数形式储存
    1.2 JavaScript 浮点数的64个二进制位,从最左边开始:
    第1位:符号位,0表示正数,1表示负数
    第2位到第12位:指数部分
    第13位到第64位:小数部分(即有效数字)
    1.3 能表示的数值范围为2^1024 到2^-1023(开区间)(否则返回Infinity)

    2. 数值精度

    2.1 从-(2^53-1) 到(2^53-1),都可以精确表示
    2.2 若只有整数才能完成的运算,会自动把64位浮点数转成32位整数
    2.3 浮点数不是精确的值(小数的比较,如0.1+0.2===0.3 //false
    2.4 小数点前的数字多于21位和其后的零多于5个会自动转为科学计数法

    3. 数值进制

    3.1 十进制:没有前导0的数值。
    3.2 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。
    3.3 十六进制:有前缀0x或0X的数值。
    3.4 二进制:有前缀0b或0B的数值。

    4.特殊数值

    • +0===-0
      (1 / +0) === (1 / -0) // false +Infinity!=-Infinity
      NaN === NaN // false
      Infinity > (<) NaN // false
    • isNaN为true的值,有可能不是NaN,而是一个字符串、对象和数组。

    5. 全局方法

    5.1 parselnt

    • parseInt:将字符串转为整数,只返回字符串头部可以转为数字,第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN。
      parseInt('+') // NaN
      parseInt('+1') // 1
    • parseInt会将科学计数法的表示方法视为字符串
    • 进制转换(2到36之间)
      parseInt('1000', 2) // 2进制-8
      parseInt('1000', 8) // 8进制512
      parseInt('10', 37) // NaN
      parseInt('10', 1) // NaN
      parseInt('10', 0) // 10
      parseInt('10', null) // 10
      parseInt('10', undefined) // 10
      5.2 parseFloat:将一个字符串转为浮点数(会将空字符串转为NaN)
      (用法与parseInt类似)

    四、字符串

    1. 转义符

    转义符 表达 码值
    \0 null (\u0000)
    \b 后退键 (\u0008)
    \f 换页符 (\u000C)
    \n 换行符 (\u000A)
    \r 回车键 (\u000D)
    \t 制表符 (\u0009)
    \v 垂直制表符 (\u000B)
    ' 单引号 (\u0027)
    " 双引号 (\u0022)
    \ 反斜杠 (\u005C)
    • 在非特殊字符前面使用反斜杠,则反斜杠会被省略
    • charCodeAt:返回每个字节对应的十进制值
    • 在JavaScript引擎内部,所有字符都用Unicode表示

    五、对象

    1. 新建对象

    var o1 = {};
    var o2 = new Object();
    var o3 = Object.create(Object.prototype); //用在需要对象继承的场合
    

    2. 注意事项

    2.1 如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),也不是数字,则必须加上引号,保留字可以不加引号当作键名
    2.2 行首是大括号为语句(即代码块)。在大括号前加上圆括号为表达式(即对象)。

    3. 属性

    • 3.1 读取对象的属性:点运算符(数值键名不能使用(被当成小数点)
      方括号运算符(键名必须放在引号里面,否则会被当作变量处理。但数字键不加引号,因为会被当作字符串处理)
    o.p // "Hello World"
    o['p'] // "Hello World"
    
    • 3.2 用Object.keys方法查看一个对象本身的所有属性。
    • 3.3 delete命令用于删除对象的属性,删除成功后返回true,属性就会返回undefined。
      • 删除一个不存在的属性,delete不报错,而且返回true。
      • 属性存在,且不得删除,delete命令会返回false。
      • delete命令不能删除var命令声明的变量,只能用来删除属性。

    4. in

    • 用于检查对象是否包含某个属性(检查的是键名,不是键值),包含(true),否则(false)。(但不能识别对象继承的属性)

    5.for...in循环

    • 5.1 用来遍历一个对象的全部属性。
    • 5.2 遍历的是对象所有可遍历的属性,跳过不可遍历的属性,遍历继承的属性。
    • 5.3 用hasOwnProperty只遍历对象本身的属性

    6. with

    • 6.1 操作同一个对象的多个属性时,提供一些书写的方便
    with (o) {
      p1 = 1;
      p2 = 2;
    }
    // 等同于
    o.p1 = 1;
    o.p2 = 2;
    
    • 6.2 with区块内部的变量,必须是当前对象已经存在的属性,否则会创造一个当前作用域的全局变量,因为with区块没有改变作用域,它的内部依然是当前作用域。

    六、数组

    1.本质

    数组属于一种特殊的对象。typeof运算符会返回数组的类型是object。

    2. 类似数组的对象

    • 2.1 类似数组的对象是函数的arguments对象,以及大多数DOM元素集,还有字符串。
    • 2.2 数组的slice方法将类似数组的对象,变成真正的数组。
      var arr = Array.prototype.slice.call(arrayLike);
    • 2.3 length属性不过滤空位空位,空位与某个位置是undefined,是不一样的。使用数组的forEach方法、for...in结构、以及Object.keys方法进行遍历,空位都会被跳过。
    • 2.4 遍历类似数组的对象,可以采用for循环,也可以采用数组的forEach方法。

    七、函数

    1. 函数声明

    • 1.1 function命令声明的代码区块,就是一个函数
      -用function命令声明函数
    function print(s) {
      console.log(s);
    }
    
    • 1.2 采用变量赋值的写法
    var print = function(s) {
      console.log(s);
    };
    
    • 1.3 Function构造函数
    var foo = new Function(
      'return "hello world"'
    );
    
    // 等同于
    
    function foo() {
      return 'hello world';
    }
    
    • Function构造函数可以不使用new命令,返回结果完全一样,但不直观,一般不用这种方法。

    2. 函数重复声明

    • 后面的声明就会覆盖前面的声明

    3.不能在条件语句中声明函数

    • 函数的toString方法返回函数的源码,内部的注释也可以返回
    • 变量在函数内部定义,是一个局部变量,函数之外无法读取。
    • 函数内部定义的变量,会在该作用域内覆盖同名全局变量。

    4.arguments 对象

    • arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数。这个对象只有在函数体内部,才可以使用。
    • 还可以为参数赋值(严格模式不允许这种用法)
    • 判断函数调用时到底带几个参数
    function f() {
      return arguments.length;
    }
    

    5. 闭包(定义在一个函数内部的函数)

    • 5.1 JavaScript有两种作用域:全局作用域和函数作用域。函数内部可以直接读取全局变量。
    • 在函数外部无法读取函数内部声明的变量,闭包就是将函数内部和函数外部连接起来的一座桥梁。
    • 可以看作是函数内部作用域的一个接口。
    • 是封装对象的私有属性和私有方法。
    • 链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
    • 在函数的内部,再定义一个函数得到函数内的局部变量
    function f1() {
      var n = 999;
      function f2() {
        console.log(n);
      }
      return f2;
    }
    
    var result = f1();
    result(); // 999
    //函数f1的返回值就是函数f2,由于f2可以读取f1的内部变量,所以就可以在外部获得f1的内部变量了。
    
    • 上述代码闭包就是函数f2,即能够读取其他函数内部变量的函数。
    • 注意:外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。

    6. 调用

    // 语句
    function f() {}
    // 表达式
    var f = function f() {}
    
    • 行首是function关键字之后,认为这一段都是函数的定义,不应该以圆括号结尾,所以就报错了。
    • 不要让function出现在行首,让引擎将其理解成一个表达式。最简单的处理,就是将其放在一个圆括号里面。
    (function(){ /* code */ }());
    // 或者
    (function(){ /* code */ })();
    //最后的分号都是必须的
    

    7. eval

    • 将有独自存在的意义字符串当作语句执行
    • 没有自己的作用域,都在当前作用域内执行,因此可能会修改当前作用域的变量的值,造成安全问题。
    • eval有安全风险。为了防止这种风险规定,如果使用严格模式,eval内部声明的变量,不会影响到外部作用域。

    八、运算符

    1. 加法运算符

    // 加法
    1 + 1 // 2
    1 + true // 2
    
    // 字符串连接
    '1.1' + '1.1' // "1.11.1"
    '1' + 1 // "11"
    '1' + true // "1true"
    //只要有一个运算子是字符串,则两个运算子都转为字符串,执行字符串连接运算。
    
    • 运算子为对象,先自动转成原始类型的值(即先执行该对象的valueOf方法,如果结果还不是原始类型的值,再执行toString方法;如果对象是Date实例,则先执行toString方法)

    2. 其他算术运算符(比如减法、除法和乘法)

    • 都不会发生重载。它们的规则是:所有运算子一律转为数值,再进行相应的数学运算。
    1 - '2' // -1
    1 * '2' // 2
    1 / '2' // 0.5
    

    3. 余数运算符(%)

    • 需要注意的是,运算结果的正负号由第一个运算子的正负号决定。
    • 为了得到正确的负数的余数值,需要先使用绝对值函数.

    4.对象间的比较

    [2] > [11] // true
    // 等同于 [2].valueOf().toString() > [11].valueOf().toString()
    // 即 '2' > '11'
    

    5. 严格相等运算符

    • 5.1 如果两个值的类型不同,直接返回false。
      -5.2 类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false。
    • 5.3 同一类的复合类型值
      • 两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个对象。
      • 对于两个对象的比较,严格相等运算符比较的是地址,而大于或小于运算符比较的是值。
    • 5.4 undefined和null与自身严格相等。

    6.相等运算符

    • 6.1 原始类型的值
      • 原始类型的数据会转换成数值类型再进行比较。
    • 6.2 对象与原始类型值比较
      • 对象(这里指广义的对象,包括数组和函数)与原始类型的值比较时,对象转化成原始类型的值,再进行比较。

    7. 取反运算符

    • 形式上是一个感叹号,用于将布尔值变为相反值对于非布尔值的数据,取反运算符会自动将其转为布尔值。
    !!x
    // 等同于
    Boolean(x)
    //两次取反就是将一个值转为布尔值的简便写法。
    

    8. 位运算符

    • 8.1 位运算符只对整数起作用,如果一个运算子不是整数,会自动转为整数后再执行。虽然在JavaScript内部,数值都是以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数。
    i = i | 0;
    //将i(不管是整数或小数)转为32位整数。
    //利用这个特性,可以写出一个函数,将任意数值转为32位整数。
    
    • 8.2 否运算
      ~ 3 // -4
    • 一个数与自身的取反值相加,等于-1。
    • 对一个整数连续两次“否运算”,得到它自身。
    ~~2.9 // 2
    ~~47.11 // 47
    ~~1.9999 // 1
    //使用否运算取整,是所有取整方法中最快的一种。
    
    • 8.3 异或
    • “异或运算”有一个特殊运用,连续对两个数a和b进行三次异或运算,可以互换它们的值(详见维基百科)。这意味着,使用“异或运算”可以在不引入临时变量的前提下,互换两个变量的值。
    var a = 10;
    var b = 99;
    
    a ^= b, b ^= a, a ^= b;
    
    a // 99
    b // 10
    
    • 异或运算也可以用来取整。
      12.9 ^ 0 // 12
    • 8.4 左移运算
    • 如果左移0位,就相当于将该数值转为32位整数,等同于取整,对于正数和负数都有效。
    13.5 << 0
    // 13
    
    • 8.5 开关作用
    var mask = FLAG_A | FLAG_B | FLAG_D;
    // 0001 | 0010 | 1000 => 1011
    //对ABD三个变量进行“或运算”,得到掩码值为二进制的1011。
    
    
    flags = flags | mask;
    //有了掩码,“或运算”可以确保打开指定的开关。
    
    flags = flags & mask;
    //“与运算”可以将当前设置中凡是与开关设置不一样的项,全部关闭。
    
    flags = flags ^ mask;
    //“异或运算”可以切换(toggle)当前设置
    //即第一次执行可以得到当前设置的相反值,再执行一次又得到原来的值。
    
    
    flags = ~flags;
    //“否运算”可以翻转当前设置,即原设置为0,运算后变为1;原设置为1,运算后变为0。
    

    9. 逗号运算符

    'a', 'b' // "b"
    //返回后一个表达式的值。
    

    10.优先级

    • 从高到低依次为:小于等于(<=)、严格相等(===)、或(||)、三元(?:)、等号(=)。
    • 圆括号(())可以用来提高运算的优先级,优先级是最高的(圆括号不是运算符,而是一种语法结构。两种用法:一是把表达式放在圆括号之中,提升运算的优先级;二是跟在函数的后面,作用是调用函数。)

    九、数据类型转换

    1.强制转换

    • 1.1 Number()
      • 比parseInt函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN。
        valueOf->若原始类型的值->Number
        valueOf->若对象->toString->若原始类型的值->Number
        valueOf->若对象->toString->若对象->错误
    • Number方法的参数是对象时,将返回NaN,除非是包含单个数值的数组
    • 1.2 String()
      • 数值:转为相应的字符串。
      • 字符串:转换后还是原来的值。
      • 布尔值:true转为"true",false转为"false"。
      • undefined:转为"undefined"。
      • null:转为"null"
      • 对象
        toString->若原始类型的值->String
        toString->若对象->valueOf->若原始类型的值->String
        toString->若对象->valueOf->若对象->报错
    • 1.3 Boolean()
      • undefined、null、-0、 0或+0、 NaN、' '(空字符串)
        转换结果为false,其他的值全部为true。
      • 注意,所有对象(包括空对象)的转换结果都是true,甚至连false对应的布尔对象new Boolean(false)也是true。

    2. 自动转换

    • 预期什么类型的值,就调用该类型的转换函数。比如,某个位置预期为字符串,就调用String函数进行转换。如果该位置即可以是字符串,也可能是数值,那么默认转为数值。
    • 由于自动转换具有不确定性,而且不易除错,建议在预期为布尔值、数值、字符串的地方,全部使用Boolean、Number和String函数进行显式转换。
    // 写法一
    expression ? true : false
    
    // 写法二
    !! expression
    有时也用于将一个表达式转为布尔值。它们内部调用的也是Boolean函数。
    
    • 字符串的自动转换,主要发生在加法运算时。当一个值为字符串,另一个值为非字符串,则后者转为字符串。

    十、错误处理机制

    1. Error对象

    • 代码解析或运行时发生错误,JavaScript引擎就会自动产生、并抛出一个Error对象的实例,然后整个程序就中断在发生错误的地方,不再往下执行。
      • message:错误提示信息
      • name:错误名称(非标准属性)
      • stack:错误的堆栈(非标准属性)
    if (error.name){
      console.log(error.name + ": " + error.message);
    }
    

    2. JavaScript的原生错误类型

    • 2.1 SyntaxError:是解析代码时发生的语法错误。
    • 2.2ReferenceError:是引用一个不存在的变量时发生的错误。
      另一种是,将一个值分配给无法分配的对象,比如对函数的运行结果或者this赋值。
    console.log() = 1
    // ReferenceError: Invalid left-hand side in assignment
    
    this = 1
    // ReferenceError: Invalid left-hand side in assignment
    
    • 2.3 RangeError是当一个值超出有效范围时发生的错误。
      • 数组长度为负数
      • Number对象的方法参数超出范围,以及函数堆栈超过最大值。
    • 2.4 TypeError是变量或参数不是预期类型时发生的错误。如对字符串、布尔值、数值等原始类型的值使用new命令,就会抛出这种错误,因为new命令的参数应该是一个构造函数。
    • 2.5 URIError是URI相关函数的参数不正确时抛出的错误,主要涉及
      • encodeURI()
      • decodeURI()
      • encodeURIComponent()
      • decodeURIComponent()
      • escape()
      • unescape()
    • 2.6 eval函数没有被正确执行时,会抛出EvalError错误。该错误类型已经不再在ES5中出现了,只是为了保证与以前代码兼容,才继续保留。

    3. 自定义错误

    4. throw语句

    • throw语句的作用是中断程序执行,抛出一个意外或错误。它接受一个表达式作为参数,可以抛出各种值。
    • throw可以接受各种值作为参数。JavaScript引擎一旦遇到throw语句,就会停止执行后面的语句,并将throw语句的参数值,返回给用户。

    5. try…catch结构

    • 为了对错误进行处理,需要使用try...catch结构。
    • catch代码块捕获错误之后,程序不会中断,会按照正常流程继续执行下去。还可以再抛出错误,甚至使用嵌套的try...catch结构
    • catch捕获错误之后,会判断错误类型(EvalError还是RangeError),进行不同的处理。
    • try...catch结构允许在最后添加一个finally代码块,表示不管是否出现错误,都必需在最后运行的语句。

    6. finally

    • 执行finally代码块以后,程序就中断在错误抛出的地方。
    • 即使有return语句在前,finally代码块依然会得到执行,且在其执行完毕后,才会显示return语句的值。return语句的执行是排在finally代码之前,只是等finally代码执行完毕后才返回。

    相关文章

      网友评论

          本文标题:JavaScript语法

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