zoukankan      html  css  js  c++  java
  • JavaScript 的一些基础知识

    JavaScript基本语法

    调试

    打开 Chrome 开发工具

    • Win F12
    • Mac Command + Option + I

    输入代码、测试执行

    var str = 'evenyao'
    console.log(str)
    

    语句

    (以下内容参考自阮一峰js教程)

    JavaScript程序的执行单位为行(line),也就是一行一行地执行。一般情况下,每一行就是一个语句。

    语句(statement)是为了完成某种任务而进行的操作,比如下面就是一行赋值语句:

    var a = 1 + 3;
    

    这条语句先用var命令,声明了变量a,然后将1 + 3的运算结果赋值给变量a

    1 + 3叫做表达式(expression),指一个为了得到返回值的计算式。语句和表达式的区别在于,前者主要为了进行某种操作,一般情况下不需要返回值;后者则是为了得到返回值,一定会返回一个值。

    凡是JavaScript语言中预期为值的地方,都可以使用表达式。比如,赋值语句的等号右边,预期是一个值,因此可以放置各种表达式。一条语句可以包含多个表达式。

    语句以分号结尾,一个分号就表示一个语句结束。多个语句可以写在一行内。

    var a = 1 + 3 ; var b = 'abc';
    

    分号前面可以没有任何内容,JavaScript引擎将其视为空语句。

    ;;;
    

    上面的代码就表示3个空语句。(关于分号的更多介绍,请看后文《代码风格》一节。)

    表达式不需要分号结尾。一旦在表达式后面添加分号,则JavaScript引擎就将表达式视为语句,这样会产生一些没有任何意义的语句。

    1 + 3;
    'abc';
    

    上面两行语句有返回值,但是没有任何意义,因为只是返回一个单纯的值,没有任何其他操作。

    变量

    概念

    变量是对“值”的引用,使用变量等同于引用一个值。每一个变量都有一个变量名。

    var a = 1;
    

    上面的代码先声明变量a,然后在变量a与数值1之间建立引用关系,也称为将数值1“赋值”给变量a。以后,引用变量a就会得到数值1。最前面的var,是变量声明命令。它表示通知解释引擎,要创建一个变量a

    变量的声明和赋值,是分开的两个步骤,上面的代码将它们合在了一起,实际的步骤是下面这样。

    var a;
    a = 1;
    

    如果只是声明变量而没有赋值,则该变量的值是undefinedundefined是一个JavaScript关键字,表示“无定义”。

    var a;
    a // undefined
    

    如果变量赋值的时候,忘了写var命令,这条语句也是有效的。

    var a = 1;
    // 基本等同
    a = 1;
    

    但是,不写var的做法,不利于表达意图,而且容易不知不觉地创建全局变量,所以建议总是使用var命令声明变量。

    严格地说,var a = 1 与 a = 1,这两条语句的效果不完全一样,主要体现在delete命令无法删除前者。不过,绝大多数情况下,这种差异是可以忽略的。

    如果一个变量没有声明就直接使用,JavaScript会报错,告诉你变量未定义。

    x
    // ReferenceError: x is not defined
    

    上面代码直接使用变量x,系统就报错,告诉你变量x没有声明。

    可以在同一条var命令中声明多个变量。

    var a, b;
    

    JavaScript 是一种动态类型语言,也就是说,变量的类型没有限制,可以赋予各种类型的值。

    var a = 1;
    a = 'hello';
    

    上面代码中,变量a起先被赋值为一个数值,后来又被重新赋值为一个字符串。第二次赋值的时候,因为变量a已经存在,所以不需要使用var命令。

    如果使用var重新声明一个已经存在的变量,是无效的。

    var x = 1;
    var x;
    x // 1
    

    上面代码中,变量x声明了两次,第二次声明是无效的。

    但是,如果第二次声明的同时还赋值了,则会覆盖掉前面的值。

    var x = 1;
    var x = 2;
    
    // 等同于
    
    var x = 1;
    var x;
    x = 2;
    

    变量提升

    JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。

    console.log(a);
    var a = 1;
    

    上面代码首先使用console.log方法,在控制台(console)显示变量a的值。这时变量a还没有声明和赋值,所以这是一种错误的做法,但是实际上不会报错。因为存在变量提升,真正运行的是下面的代码。

    var a;
    console.log(a);
    a = 1;
    

    最后的结果是显示undefined,表示变量a已声明,但还未赋值。

    请注意,变量提升只对var命令声明的变量有效,如果一个变量不是用var命令声明的,就不会发生变量提升。

    console.log(b);
    b = 1;
    

    上面的语句将会报错,提示“ReferenceError: b is not defined”,即变量b未声明,这是因为b不是用var命令声明的,JavaScript引擎不会将其提升,而只是视为对顶层对象的b属性的赋值。

    标识符

    标识符(identifier)是用来识别具体对象的一个名称。最常见的标识符就是变量名,以及后面要提到的函数名。JavaScript语言的标识符对大小写敏感,所以aA是两个不同的标识符。

    标识符有一套命名规则,不符合规则的就是非法标识符。JavaScript引擎遇到非法标识符,就会报错。

    简单说,标识符命名规则如下:

    • 第一个字符,可以是任意Unicode字母(包括英文字母和其他语言的字母),以及美元符号($)和下划线(_)。
    • 第二个字符及后面的字符,除了Unicode字母、美元符号和下划线,还可以用数字0-9

    下面这些都是合法的标识符。

    arg0
    _tmp
    $elem
    π
    

    下面这些则是不合法的标识符。

    1a  // 第一个字符不能是数字
    23  // 同上
    ***  // 标识符不能包含星号
    a+b  // 标识符不能包含加号
    -d  // 标识符不能包含减号或连词线
    

    中文是合法的标识符,可以用作变量名。

    var 临时变量 = 1;
    

    JavaScript有一些保留字,不能用作标识符:arguments、break、case、catch、class、const、continue、debugger、default、delete、do、else、enum、eval、export、extends、false、finally、for、function、if、implements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、while、with、yield。

    另外,还有三个词虽然不是保留字,但是因为具有特别含义,也不应该用作标识符:InfinityNaNundefined

    注释

    源码中被JavaScript引擎忽略的部分就叫做注释,它的作用是对代码进行解释。Javascript提供两种注释:一种是单行注释,用//起头;另一种是多行注释,放在/* 和 */之间。

    // 这是单行注释
    
    /*
     这是
     多行
     注释
    */
    

    此外,由于历史上JavaScript兼容HTML代码的注释,所以<!---->也被视为单行注释。

    x = 1; <!-- x = 2;
    --> x = 3;
    

    上面代码中,只有x = 1会执行,其他的部分都被注释掉了。

    需要注意的是,-->只有在行首,才会被当成单行注释,否则就是一个运算符。

    function countdown(n) {
      while (n --> 0) console.log(n);
    }
    countdown(3)
    // 2
    // 1
    // 0
    

    上面代码中,n --> 0实际上会当作n-- > 0,因此输出2、1、0。

    区块

    JavaScript使用大括号,将多个相关的语句组合在一起,称为“区块”(block)。

    与大多数编程语言不一样,JavaScript的区块不构成单独的作用域(scope)。也就是说,区块中的变量与区块外的变量,属于同一个作用域。

    {
      var a = 1;
    }
    
    a // 1
    

    上面代码在区块内部,声明并赋值了变量a,然后在区块外部,变量a依然有效,这说明区块不构成单独的作用域,与不使用区块的情况没有任何区别。所以,单独使用的区块在JavaScript中意义不大,很少出现。区块往往用来构成其他更复杂的语法结构,比如forifwhilefunction等。

     

    JavaScript 数据类型

    概述

    JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有六种。(ES6 又新增了第七种 Symbol 类型的值)

    • 数值(number):整数和小数(比如1和3.14)
    • 字符串(string):字符组成的文本(比如"Hello World")
    • 布尔值(boolean):true(真)和false(假)两个特定值
    • undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值
    • null:表示无值,即此处的值就是“无”的状态。
    • 对象(object):各种值组成的集合

    通常,我们将数值、字符串、布尔值称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。而将对象称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefinednull,一般将它们看成两个特殊值。

    对象又可以分成三个子类型。

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

    typeof运算符

    JavaScript有三种方法,可以确定一个值到底是什么类型。

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

    instanceof运算符和Object.prototype.toString方法,将在后文相关章节介绍。这里着重介绍typeof运算符。

    typeof运算符可以返回一个值的数据类型,可能有以下结果。

    (1)原始类型

    数值、字符串、布尔值分别返回numberstringboolean

    typeof 123 // "number"
    typeof '123' // "string"
    typeof false // "boolean"
    

    (2)函数

    函数返回function

    function f() {}
    typeof f
    // "function"
    

    (3)undefined

    undefined返回undefined

    typeof undefined
    // "undefined"
    

    利用这一点,typeof可以用来检查一个没有声明的变量,而不报错。

    v
    // ReferenceError: v is not defined
    
    typeof v
    // "undefined"
    

    上面代码中,变量v没有用var命令声明,直接使用就会报错。但是,放在typeof后面,就不报错了,而是返回undefined

    实际编程中,这个特点通常用在判断语句。

    // 错误的写法
    if (v) {
      // ...
    }
    // ReferenceError: v is not defined
    
    // 正确的写法
    if (typeof v === "undefined") {
      // ...
    }
    

    (4)其他

    除此以外,其他情况都返回object

    typeof window // "object"
    typeof {} // "object"
    typeof [] // "object"
    typeof null // "object"
    

    从上面代码可以看到,空数组([])的类型也是object,这表示在JavaScript内部,数组本质上只是一种特殊的对象。

    既然typeof对数组(array)和对象(object)的显示结果都是object,那么怎么区分它们呢?instanceof运算符可以做到。

    var o = {};
    var a = [];
    
    o instanceof Array // false
    a instanceof Array // true
    

    instanceof 后续讲解。

    布尔值

    布尔值代表“真”和“假”两个状态。“真”用关键字true表示,“假”用关键字false表示。布尔值只有这两个值。

    下列运算符会返回布尔值:

    • 两元逻辑运算符: && (And),|| (Or)
    • 前置逻辑运算符: ! (Not)
    • 相等运算符:===!====!=
    • 比较运算符:>>=<<=

    如果JavaScript预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false,其他值都视为true

    • undefined
    • null
    • false
    • 0
    • NaN
    • ""''(空字符串)

    布尔值往往用于程序流程的控制,请看一个例子。

    if ('') {
      console.log(true);
    }
    // 没有任何输出
    

    上面代码的if命令后面的判断条件,预期应该是一个布尔值,所以JavaScript自动将空字符串,转为布尔值false,导致程序不会进入代码块,所以没有任何输出。

    需要特别注意的是,空数组([])和空对象({})对应的布尔值,都是true

    if ([]) {
      console.log(true);
    }
    // true
    
    if ({}) {
      console.log(true);
    }
    // true
    

    更多关于数据类型转换的介绍,参见《数据类型转换》一节。

    运算符

    JavaScript中运算符主要用于连接简单表达式,组成一个复杂的表达式。常见的有算数表达式、比较表达式、逻辑表达式、赋值表达式等,也有单目运算符,指操作原始表达式。大多数运算符都由标点符号组成(+、>=、!),也有关键字表示的运算符,如typeof、delete、instanceof等。

    一些运算符可以作用于任何数据类型(typeof),但大部分操作符希望操作数是特定的类型,而且大部分操作符会计算出(我们也常说返回)一个特定类型的值(typeof返回的全是string)。在JavaScript中运算符通常会根据需要对操作数进行类型转换,乘法操作符希望操作数是数字,但是 "3" * "5"也是合法的,JavaScript会自动将其转换为数字计算,返回Number 15。

    有些操作符对不同的数据类型有不同的含义,比如 +

    • 在两个操作数都是数字的时候,会做加法运算
    • 两个参数都是字符串或在有一个参数是字符串的情况下会把另外一个参数转换为字符串做字符串拼接
    • 在参数有对象的情况下会调用其valueOf或toString
    • 在只有一个字符串参数的时候会尝试将其转换为数字
    • 在只有一个数字参数的时候返回其正数值
    console.log(2+4);//6
    console.log("2"+"4");//"24"
    console.log(2+"4");//"24"
    console.log(2+new Date());//"2Mon Jan 20 2014 17:15:01 GMT+0800 (China Standard Time)"
    console.log(+"4");//4 
    

    远算符类型

    算数运算符

    • 加法运算符(Addition):x + y
    • 减法运算符(Subtraction): x - y
    • 乘法运算符(Multiplication): x * y
    • 除法运算符(Division):x / y
    • 余数运算符(Remainder):x % y
    • 自增运算符(Increment):++x 或者 x++
    • 自减运算符(Decrement):--x 或者 x--
    • 求负运算符(Negate):-x
    • 数值运算符(Convert to number): +x

    赋值运算符

    赋值运算符用于给变量赋值,最常见的赋值运算符,当然就是等号,表达式x=y表示将y赋值给x。除此之外,JavaScript还提供其他11个赋值运算符。

    x += y // 等同于 x = x + y
    x -= y // 等同于 x = x - y
    x *= y // 等同于 x = x * y
    x /= y // 等同于 x = x / y
    x %= y // 等同于 x = x % y
    x >>= y // 等同于 x = x >> y
    x <<= y // 等同于 x = x << y
    x >>>= y // 等同于 x = x >>> y
    x &= y // 等同于 x = x & y
    x |= y // 等同于 x = x | y
    x ^= y // 等同于 x = x ^ y
    

    比较运算符

    比较运算符比较两个值,然后返回一个布尔值,表示是否满足比较条件。JavaScript提供了8个比较运算符。

    • == 相等
    • === 严格相等
    • !=不相等
    • !== 严格不相等
    • < 小于
    • <= 小于或等于
    • > 大于
    • >= 大于或等于

    布尔运算符

    • ! 取反运算符
    • && 且运算符
    • || 或运算符
    • condition? true case : false case 三元条件运算符

    位运算符

    • 或运算(or):符号为|,表示两个二进制位中有一个为1,则结果为1,否则为0。
    • 与运算(and):符号为&,表示两个二进制位都为1,则结果为1,否则为0。
    • 否运算(not):符号为,表示将一个二进制位变成相反值。
    • 异或运算(xor):符号为ˆ,表示两个二进制位中有且仅有一个为1时,结果为1,否则为0。
    • 左移运算(left shift):符号为<<
    • 右移运算(right shift):符号为>>
    • 带符号位的右移运算(zero filled right shift):符号为>>>

    其它

    小括号

    在JavaScript中,圆括号是一种运算符,它有两种用法:如果把表达式放在圆括号之中,作用是求值;如果跟在函数的后面,作用是调用函数。

    把表达式放在圆括号之中,将返回表达式的值。

    void

    void运算符的作用是执行一个表达式,然后返回undefined。

    逗号运算符

    逗号运算符用于对两个表达式求值,并返回后一个表达式的值。

    运算符优先级与结合性

    优先级什么意思大家都清楚,结合性是指多个具有同样优先级的运算符表达式中的运算顺序。有的运算符是左结合的,即运算从左到右执行,下面两个运算是一样的

    w = x + y + z;
    w = (x + y) + z;
    

    有的运算符是右结合的

    w = x = y = z;
    w = (x = (y = z));
    w = a: b: c ? d : e? f : g;
    w = a? b : (c? d: (e? f : g));
    

    运算符的优先级《JavaScript权威指南》中有个表阐述的很好(我去掉了位运算部分),其中R/L代表结合性是右结合还是左结合,num->num表示操作符期望的数据类型和计算结果类型,lval指左值

    运算符操作结合性类型
    ++ 自增 R lval->num
    -- 自减 R lval->num
    - 求反 R num->num
    +(一个操作数) 转换为数字 R num->num
    ~ 按位求反 R int->int
    ! 逻辑非 R bool->bool
    delete 删除属性 R lval->bool
    typeof 检测数据类型 R any->str
    void 返回undefined R any->undefined

    *、/、% 乘、除、求余 L num,num->num

    +、- 加、减 L num,num->num
    + 字符串拼接 L str,str->str
    <、<=、>、>= 数字大小或字母表顺序 L num/str,num/str->bool
    instanceof 对象类型 L obj,function->bool
    in 测试属性是否存在 L str,obj->bool

    == 判断相等 L any,any->bool
    != 判断不等 L any,any->bool
    === 判断恒等 L any,any->bool
    !== 判断非恒等 L any,any->bool

    && 逻辑与 L any,any->any
    || 逻辑或 L any,any->any
    ?: 条件运算符 R bool,any,any->any
    =赋值 *=、/=、+=、-= 赋值 运算且赋值 R lval,any->any
    , 忽略第一个操作数,返回第二个操作数 L any,any->any

    MDN 参考

    有几个我们需要注意的地方

    1. typeof的优先级相当的高,比加减乘除神马的都高,所以虽然是操作符,在在复杂表达式的时候我们还是习惯加括号,看个例子

       typeof 2*3;//NaN
       typeof (2*3);//"number"
       typeof 2+3;// "number3"
      
    2. ++--是右结合的操作符(优先级最高的几个都是右结合),而且比加减乘除优先级高。同时自增、自减运算符的运算数得是左值(可以放在赋值符号左边的值),而不能是常数

       4++; //ReferenceError: Invalid left-hand side expression in postfix operation
       var a=0,b=0;
       a+++b;//0
       a;//1,++优先级比+高,所以相当于(a++)+b
       b;//0
      
    3. 赋值运算符的优先级相当的低

       a = b == c; //等同于a = (b==c)
      
    4. 逻辑非!也在优先级队列的前端,比加减乘除高,但逻辑与、逻辑或优先级很低,不如加减乘除

       !2*0; //0, 等价于(!2)*0
      
    5. 一个关于逻辑运算符的有意思地方是其“短路”功能,相信大家都有所了解,但有些题目不那么单纯,会结合表达式计算值来考察

       1 && 3;
       1 && "foo" || 0;
       1 || "foo" && 0
      

    了解了逻辑运算符的“短路”特点,在知道原始表达式的“返回值”就是本身,题目就很简单了

    相等

    我们知道可以使用=====判断两个值的相等性,其中区别相信大家清楚,===是严格意义的相等,只需注意NaN和NaN不等就行了。而使用==的时候,javascript会帮我们做类型转换,造成一些匪夷所思的结果,那么使用==的时候会在哪些情况下做类型转换,又会换成什么样子?

    • 如果两个值类型相同,则执行严格相等的运算
    • 如果两个值的类型不同
      1. 如果一个是null,一个是undefined,那么相等
      2. 如果一个是数字,一个是字符串,先将字符串转为数字,然后比较
      3. 如果一个值是true/false则将其转为1/0比较
      4. 如果一个值是对象,一个是数字或字符串,则尝试使用valueOf和toString转换后比较
      5. 其它就不相等了
    null==undefined;
    NaN==NaN
    "1"==true
  • 相关阅读:
    基于bootstrap的上传插件fileinput实现ajax异步上传功能(支持多文件上传预览拖拽)
    BootStrap fileinput.js文件上传组件实例代码
    Bootstrap fileinput.js,最好用的文件上传组件
    JS组件系列——Bootstrap文件上传组件:bootstrap fileinput
    JS文件上传神器bootstrap fileinput详解
    ***文件上传控件bootstrap-fileinput的使用和参数配置说明
    很清晰的解读i2c协议【转】
    高并发的socket的高性能设计【转】
    android dm-verity 功能【转】
    ARM的Jazelle技术【转】
  • 原文地址:https://www.cnblogs.com/evenyao/p/9323906.html
Copyright © 2011-2022 走看看