zoukankan      html  css  js  c++  java
  • JavaScript 的基本概念( ES5 )

    语法

    • 区分大小写
    • 标识符
      第一个字符必须是一个字母,下划线或者一个美元符( $ )。其他规则无论,最好按照通用的驼峰大小写。
    • 注释
    // 单行注释
    /*
        多行注释
    */
    
    • 严格模式
      在顶部添加如下代码
    "use strict"
    
    • 语句
      语句以一个分号结尾,也可省略分号,则由解析器确定语句的结尾,具体分号写与不写自行决定。

    关键字和保留字

    具有特殊用途的关键字和保留字,不能用作标识符。

    变量

    // 声明全局变量
    var message = 'hi'
    message = 100
    console.log(message) // 100
    
    // 函数内声明是为局部变量
    function test(){
        console.log(message) // undefined  使用 var 声明变量会产生变量提升,但尚未赋值所以是 undefined
        var message = 'hi' // 局部变量
    }
    test()
    alert(message) // 报错
    
    // 一条语句定义多个变量,用度号隔开
    var message = 'hi',
        found = false,
        age = 18;
    

    数据类型

    • 5 种简单数据类型和 1 种复杂数据类型
      ES5 中有 5 种简单数据类型( 基本数据类型 ) Undefined, Null, Boolean, Number, String。还有 1 种复杂数据类型 Object。
    • typeof 操作符
      使用 typeof 操作符返回下列某个字符串:
      "undefined" —— 如果这个值未定义
      "boolean" —— 如果这个值是布尔值
      "string" —— 如果这个值是字符串
      "number" —— 如果这个值是数值
      "object" —— 如果这个值是对象或 null
      "function" —— 如果这个值是函数
    var message = "some string"
    console.log(typeof message)  // "string"
    console.log(typeof(message)) // "string"
    console.log(typeof 99) // "number"
    
    • Undefined 类型
      只有一个值为 undefined,使用 var 声明变量但未初始化时,这个变量的值为 undefined
    // var 声明变量但未初始化
    var message
    console.log(message == undefined) // true
    
    // var 声明变量初始化为 undefined
    var message = undefined // 一般不会赋值 undefined 会默认如上例
    console.log(message == undefined) // true
    
    // 变量声明后默认获得 undefined 但变量没声明会产生错误
    var message 
    console.log(message) // "undefined"
    console.log(age) // 产生错误,因 age 尚未声明
    
    // typeof 操作符对未赋值和未声明的变量都返回 undefined
    var message 
    console.log(typeof message)
    console.log(typeof age)
    
    • Null 类型
      仅有一个值的类型, 该值为 null。从逻辑上看,null 值表示一个空对象指针, 因此 typeof 操作符检测 null 值返回 "object"。
    var car = null
    console.log(typeof car)
    
    // undefined 值是派生自 null 值,检测它们相等性测试返回 true
    console.log(null == undefined) // true
    
    // 声明保存对象的变量还没有真正保存对象,就应该让改变量保存 null 值
    var bar 
    var foo = bar + 2 + 3
    console.log(foo) // NaN 由于 bar 无赋值因此操作会出错
    
    var faz = null
    var baz = faz + 4 + 5
    console.log(baz) // 9 因 faz 被 null 赋值操作正确
    
    • Boolean 类型
      该类型只有两个字面值:true 和 false。对任何数据类型调用 Boolean() 函数,都会返回一个 Boolean 值。

    • Number 类型
      一:浮点数值,永远不要测试某个特定浮点数值

    console.log(0.3 == 0.2 + 0.1) // false 
    

    二:数值范围
    由于内存限制,浏览器中这个边界是最小值是 5e - 324,最大值 1.7976931348623157e + 308, 超出则为 Infinity 分正负。
    三:NaN
    非数值是一个特殊的数值,这个值用于表示本来要返回一个数值的操作但未返回数值的情况( 这样就不会抛出错误 )。

    1. 任何涉及 NaN 的操作都会返回 NaN, 2. NaN 与任何值都不相等,包括 NaN 本身。
    console.log(NaN == NaN) // false
    

    isNaN() 函数接受一个参数,该参数可以是任何类型,而函数会帮我们确定这个参数是不是"不是值"。isNaN() 接受到一个值后,后尝试将这个值转换为数值。
    不能被换行成数值的值都会导致这个行数返回 true

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

    四:数值转换
    有 3 个函数可以把非数值转换为数值: Number()、parseInt() 和 parseFloat()。Number() 转型函数可以用于任何数据类型,而另外两个只能用于把字符串转成数值。

    1. Number() 函数的规则如下:
    • 如果是 Boolean 值,true 和 false 将分别被转换成 1 和 0。
    • 如果是数字值, 只是简单的传入和返回。
    • 如果是 null 值,返回 0。
    • 如果是 undefined,返回 NaN。
    • 如果是字符串规则如:
    1. 如果字符串中只包行数字,则将其转换为十进制数值,即 "1" 转换 1,"123" 转换成 123,"011" 转行成 11。(前导的零被忽略)
    2. 如果字符串包含有效浮点数格式转行成对应的浮点数,(前导的零被忽略)
    3. 如果字符串包含有效十六进制格式,被转行成大小相同的十进制整数值。
    4. 如果字符串是空的,则将被转行成 0。
    5. 其余都被转行成 NaN。
    • 如果是对象,则先调用 valueOf() 方法,然后依照前面的规则返回值。如果转换的结果为 NaN,则调用对象的 toString() 方法,然后依照前面的规则转换返回的字符串的值。
    var num1 = Number("Hello world")
    console.log(num1) // NaN
    var num2 = Number(" ")
    console.log(num2) // 0
    var num3 = Number("000011")
    console.log(num3) // 11
    var num4 = Number(true)
    console.log(num4) // 1
    
    1. parseInt() 函数在转换字符串时,更多的是看其是否符合数值模式。它会忽略字符串前面的空格,直至找到第一个非空字符,如果第一个字符不是数字字符或者负号,parseInt() 就会返回 NaN。parseInt()能识别各种整数格式( 十进制、八进制、十六进制 )。使用 parseInt() 函数可以为这个函数提供第二个参数: 转换是使用的基数(即多少进制)
    console.log(parseInt("")) // NaN
    console.log(parseInt("1234blue")) // 1234
    console.log(parseInt("22.5")) // 222
    console.log(parseInt("0xA")) // 10    十六进制
    console.log(parseInt("070")) // 56    八进制
    console.log(parseInt("70")) // 70    十进制
    console.log(parseInt("0xf")) // 15    十六进制
    
    console.log(parseInt("0xAF", 16))     // 175
    console.log(parseInt("AF", 16))    // 175
    console.log(parseInt("AF"))    // NaN
    
    console.log(parseInt("10", 2))    // 2    按二进制解析
    console.log(parseInt("10", 8))    // 8    按八进制解析
    console.log(parseInt("10", 10))     // 10     按十进制解析
    
    1. parseFloat() 从第一个字符( 位置 0 ) 开始解析每个字符, 一直到字符末尾,或者解析到一个无效浮点数字字符为止。parseFloat() 只解析十进制值,因此无第二个参数。
    console.log(parseFloat("22.34.5"))    // 22.34 
    console.log(parseFloat("1234blue"))    // 1234
    console.log(parseFloat("0xA"))    // 0
    console.log(parseFloat("22.5"))    // 22.5
    console.log(parseFloat("0908.5"))    // 908.5
    console.log(parseFloat("3.124e7"))   // 31250000
    
    • String 类型
      String 类型用于表示由零或多个 16 位 Unicode 字符组成的字符序列,即字符串。字符串可有双引号或单引号表示(必须左右引号匹配)。
      1)字符字面量
      String 数据类型包含一些特殊的字符字面量,也叫转义序列。
      换行
      制表
       空格
      回车
      f 进纸
      斜杠
      ' 单引号
      " 双引号
      xnn 十六进制
      unnnn 十六进制
      2)字符串的特点
      字符串是不可变的,字符串一旦创建,它们的值不能改变,要改变某个变量保存的字符串,首先销毁原来的字符串,然后再用一个包含新值的字符串填充该变量。
    var lang = "Java"
    lang = lang + "Script"
    

    以上代码的过程是,变量 lang 开始时包行字符串 "Java"。第二代码把 lang 值重新定义为 "Java" 与 "Script" 的组合,即 "JavaScript"。先创建一个能容纳 10 个字符的新字符串,然后在这个字符串中填充 "Java" 和 "Script",最后一步是销毁原来的字符串 "Java" 和字符串 "Script",因为这两个字符串已经没用了,这个过程是在后台发生,旧版浏览器字符拼接速度慢的原因所在,新版浏览器已经解决改问题。
    3)转换为字符串
    把一个值转换为一个字符串有两种方法,第一种是使用几个每个值都有的 toString() 方法,这个方法的作用就是返回相应值的字符串表现。

    var age = 1
    console.log(typeof age)    // number
    var getAsString = age.toString()
    console.log(typeof getAsString) // string
    
    var found = true
    console.log(typeof found)    // boolean
    var foundAsString = found.toString()
    console.log(typeof foundAsString) // string
    

    其中 null 和 undefined 值没有 toString 方法。
    调用数值的 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"
    

    在不知道转换的值是不是 null 或 undefined 时,还可以用转行函数 String(), 这个函数能够将任何类型的值转换为字符串。
    String() 函数遵循下列转换规则:

    • 如果值有 toString() 方法,则调用该方法( 无参数 ) 并返回相应的结果。
    • 如果值是 null,则返回 "null"。
    • 如果值是 undefined, 则返回 "undefined"。
    var value1 = 10
    var value2 = true
    var value3 = null
    var value4
    
    console.log(String(value1))    // "10"
    console.log(String(value2))    // "true"
    console.log(String(value3))    // "null"
    console.log(String(value4))    // "undefined"
    
    • Object 类型
      对象可以执行 new 操作符后根要创建的对象类型的名称来创建。而创建 Object 类型的实例并且为其添加属性和方法,就可以自定义对象,
    var o = new Object()
    

    每个 Object 实例都具有下列属性和方法

    • Constructor: 保存着用于创建当前对象的函数。对于前面的例子而言,构造函数 (constructor) 就是 Object()。

    • hasOwnProperty(propertyName): 用于检查给定的属性在当前实例中( 而不是在实例的原型中 )是否存在。其中,作为参数的属性名(propertyName)必须以字符串的形式指定。

    • isPrototypeOf(object): 用于检查传入的对象是否是另一个对象的原型。

    • propertyIsEnumerable(propertyName): 用于检查给定的属性是否能够使用 for-in 语句来枚举。参数属性名必须以字符串的形式指定。

    • toLocalesString():返回对象的字符串表示, 改字符串与执行环境地区对应。

    • toString(): 返回对象的字符串表示。

    • valueOf():返回对象的字符串、数值或者布尔值表示,通常与 toString() 方法的返回值相同。

    • 操作符
      描述一组用于操作数值的操作符,包括算术操作符、位操作符、关系操作符合相等操作符。
      1)一元操作符
      1.1)递增和递减操作符

    // 递增操作符
    var age = 29
    ++age
    console.log(age)    // 30
    
    // 常规加法操作
    var age = 29
    age = age + 1
    console.log(age)    // 30
    
    // 递减操作符
    var age = 29
    --age
    console.log(age)    // 28
    

    执行前置递增和递减操作时,变量的值都是在语句被求值以前改变的。(这是副作用)

    var age = 29
    var anotherAge = --age + 2
    
    console.log(age)    // 28
    console.log(anotherAge)    // 30
    

    前置递增和递减操作与执行语句的优先级相等,因此整个语句会从左自右被求值。

    var num1 = 2
    var num2 = 20
    var num3 = --num1 + num2
    var num4 = num1 + num2
    
    console.log(num3)
    console.log(num4) 
    

    后置型递增和递减操作符的语法不变,后置与前置的区别,后置在语句被求值之后才执行。

    var age = 29
    age ++
    console.log(age)    // 30
    
    var num1 = 2
    var num2 = 20
    var num3 = num1-- + num2
    var num4 = num1 + num2
    console.log(num3)    // 22
    console.log(num4)    // 21
    

    递增或递减操作符遵循下列规则:

    • 在用于一个包含有效数字字符串时,先将其转换为数字值,再执行加减 1 的操作。字符串变量变成数值变量。
    • 在用于一个不包含有效数字字符串时,将变量的值设置为 NaN。字符变量变成数值变量。
    • 在应用于布尔值 false 时,先将其转换成 0 再执行加减 1 的操作。布尔值变量变成数值变量。
    • 在应用于布尔值 true 时,先将其转换成 1 再执行加减 1 的操作。 布尔值变量变成数值变量。
    • 在应用于浮点数值时,执行加减 1 的操作。
    • 在应用于对象时,先调用对象的 valueOf() 方法以取得一个可供操作的值。然后对该值应用前述规则,如果结果是 NaN,则再调用 toString() 方法后再应用前述规则,对象变量变成数值变量。
    var s1 = "2"
    var s2 = "z"
    var b = false
    var f = 1.1
    var o = {
        valueOf: function() {
                return -1
            }
        }
    
    s1++   // 3
    s2++   // NaN
    b++    // 1
    f++    // 0.10000000009 (浮点数计算不精准)
    o++    // -2
    

    2)一元加和减操作符

    var num = 25
    num = +num    // 25
    

    在对非数值应用一元加操作符时,该操作符会象 Number() 转型函数一样对这个值执行转换。

    var s1 = "01"
    var s2 = "1.1"
    var s3 = "z"
    var b = false 
    var f = 1.1
    var o = {
        valueOf: function() {
                return -1
        }
    }
    
    s1 = +s1    // 1
    s2 = +s2    // 1.1
    s3 = +s3    // NaN
    b = +b    // 0
    f = +f    // 1.1
    o = +o    // -1
    

    一元操作符主要用于表示负数,例如将 1 转换成 -1。

    var num = 25
    num = -25    // -25
    

    在将一元操作符应用于数值时,该值会变成负数,而当应用于非数值时,医院减操作符遵循与一元加操作符相同的规则,最后再将得到的数值转换为负数。

    var s1 = "01"
    var s2 = "1.1"
    var s3 = "z"
    var b = false
    var f = 1.1
    var o = {
        valueOf: function() {
                return -1
        }
    }
    
    s1 = -s1    // 转换成数值 -1
    s2 = -s2    // 转换成数值 -1.1
    s3 = -s3    // 转换成 NaN
    b = -b    // 转换成数值 0
    f = -f    // 转换成 -1.1
    o = -o    // 转行成数值 1
    

    3)位操作符
    非常高级的知识,一般情况用不到,暂时搁置。
    4)布尔操作符
    在一门编程语言中,布尔操作符的重要性堪比相等操作符。布尔操作符共有 3 个:与(AND)、或(OR)和非(NOT)。
    4.1)逻辑非
    逻辑非操作符由一个感叹号(!)表示,无论这个值是什么类型,这个操作都会返回一个布尔值。逻辑非操作首先将它的操作数转换为一个布尔值,然后再对其取反。逻辑非的规则:

    • 如果操作数是一个对象,返回 false
    • 如果操作数是一个空字符串,返回 true
    • 如果操作数是一个非空字符串,返回 false
    • 如果操作数是数值 0,返回 true
    • 如果操作数是任意非 0 数值(包含 Infinity),返回 false
    • 如果操作数是 null, 返回 true
    • 如果操作数是 NaN,返回 true
    • 如果操作数是 undefined,返回 true
    console.log(!false)    // true
    console.log(!"blue")    // false
    console.log(!0)    // true
    console.log(!NaN)    // true
    console.log(!"")    // true
    console.log(!12345)    // false
    
    console.log(!!"blue")    // true
    console.log(!!0)    // false
    console.log(!!NaN)    // false
    console.log(!!"")    // false
    console.log(!!12345)    // true
    

    4.2)逻辑与
    逻辑与操作符有两个和号(&&)表示。
    规则如下:

    • 如果第一个操作数是对象,则返回第二操作数;
    • 如果第二个操作数是对象,则只有第一个操作数的求值结果为 true 的情况下才会返回改对象;
    • 如果两个操作数都是对象,则返回第二操作数;
    • 如果有一个操作数是 null,则返回 null;
    • 如果有一个操作数是 NaN,则返回 NaN;
    • 如果有一个操作数是 undefined,则返回 undefined。
      如果第一个操作数能够决定结果,那么就不会再对第二个操作数求值。如果第一个操作数是 false,则无论第二个操作数是什么值,结果不可能是 true。
      4.3)逻辑或
      逻辑或操作符有两个竖线符号(||)表示。
      规则如下:
    • 如果第一个操作数是对象,则返回第一个操作数;
    • 如果第一个操作数的求值结果为 false,则返回第二个操作数;
    • 如果两个操作数都数对象,则返回第一个操作数;
    • 如果两个操作数都是 null,返回 null;
    • 如果两个操作数都是 NaN,返回 NaN;
    • 如果两个操作数都是 undefined,则返回 undefined。
      第一个操作数的求值结果为 true,就不会对第二个操作数求值。

    5)乘性操作符
    乘性操作符有 3 个:乘法、除法和求模。在操作数为非数值的情况下会执行自动的类型转换。若参与乘法计算的某个操作数不是数值,后台会先使用 Number() 转换函数将其转换为数值。
    5.1)乘法
    乘法操作符有一个星号(*)表示。
    如果一个操作数不是数值,则在后台调用 Number() 将其转行为数值,利用 Number() 的规则转换后,再相乘。
    5.2)除法
    除法操作符有一个斜线符号(/)表示。
    如果一个操作数不是数值,则在后台调用 Number() 将其转行为数值,利用 Number() 的规则转换后,再相除。
    5.3)求模
    求模(取余)操作符有一个百分号(%)表示。

    var result = 26 % 5    // 等于 1
    
    • 如果操作数都是数值,执行常规的除法计算,返回除的余数;
    • 如果被除数是无穷大值而除数是有限大的数值,则结果是 NaN;
    • 如果被除数是有限大的数值儿除数是零,则结果是 NaN;
    • 如果是 Infinity 被 Infinity 除,则结果是 NaN;
    • 如果被除数是有限大的数值儿除数是无穷大的数值,则结果是被除数;
    • 如果被除数是零,则结果是零;
    • 如果有一个操作数不是数值,则在后台调用 Number() 将其转行为数值,然后再应用以上规则。
      6)加性操作符
      加法和减法这两个加性操作符应该说是编程语言中最简单的算术操作符,但是在 ECMAScript 中,这两个操作符却有一系列的特殊行为。
      6.1)加法
    var result = 1 + 2
    console.log(result)    // 3
    
    • 如果一个操作数是 NaN,则结果是 NaN;
    • 如果是 Infinity 加 Infinity, 则结果是 Infinity;
    • 如果是 -Infinity 加 -Infinity, 则结果是 -Infinity;
    • 如果是 Infinity 加 -Infinity, 则结果是 NaN;
    • 如果是 +0 加 +0,则结果是 +0;
    • 如果是 -0 加 -0,则结果是 -0;
    • 如果是 +0 加 -0,则结果是 +0;
      不过,如果有一个操作数是字符串,那么就有应用如下规则:
    • 如果两个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来;
    • 如果只有一个操作数是字符串,则将另外一个操作数转行为字符串,然后再将两个字符串拼接起来。
      如果有一个操作数是对象、数字或者布尔值,则调用他们的 toString() 方法去的相应的字符串值,
      然后应用前面关于字符串的规则。对于 undefined 和 null,则分别调用 String() 函数并取得字符串 'undefined' 和 'null'。
    var result1 = 5 + 5
    console.log(result1)    // 10
    
    var result2 = 5 + '5'
    console.log(result2)    // 55 
    

    6.2) 减法

    • 如果两个操作数都是数值,执行常规算术减法操作并返回结果;
    • 如果有一个操作数是 NaN,则结果是 NaN;
    • 如果是 Infinity 减 Infinity,则结果是 NaN;
    • 如果是 -Infinity 减 Infinity,则结果是 NaN;
    • 如果是 Infinity 减 -Infinity,则结果是 Infinity;
    • 如果是 -Infinity 减 Infinity,则结果是 -Infinity;
    • 如果是 +0 减 +0,则结果是 +0;
    • 如果是 +0 减 -0,则结果是 -0;
    • 如果是 -0 减 -0,则结果是 +0;
    • 如果有一个操作数是字符串、布尔值、null 或 undefined,则先再后台调用 Number() 函数将其转行为数值,然后根据前面的规则执行减法计算,如果转换的结果是 NaN,则减法的结果是 NaN;
    • 如果有一个操作数是对象,则调用对象的 valueOf() 方式以去的表示该对象的数值,如果得到的值是 NaN,则减法的结果就是 NaN。如果对象没有 valueOf() 方法,则调用其 toString() 方式并将得到的字符串转行为数值.
    var result1 = 5 - true // 4
    var result2 = NaN - 1    // NaN
    var result3 = 5 -3    // 2
    var result4 = 5 - ''    // 5
    var result5 = 5 - '2'    // 3
    var result5 = 5 - null    // 5
    

    6.3) 关系操符
    小于(<)、大于(>)、小于等于(<=)和大于等于(>=)

    • 如果两个操作数都是数值,则执行数值比较。
    • 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值。
    • 如果一个操作数是数值,将另一个操作数转换为一个数值,然后执行数值比较。
    • 如果一个操作数是对象,则调用这个对象的 valueOf() 方法,用得到的结构按照前面的规则执行比较。如果没有 valueOf() 方法,则调用 toString() 方法,并用得到的结果根据前面的规则执行比较。
    • 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。
    • 任何操作数与 NaN 进行关系比较,结果都是 flase。

    6.4) 相等操作符
    相等(==)与不相等(!=) 都会先转行操作数(通常称为 强制类型转换)

    • 如果操作数是布尔值,则在比较相等性之前将其转换为数值——false 转行为 0,而 true 转换为 1;
    • 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值;
    • 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf() 方法,用得到的基本类型值按前面的规则进行比较;
      这两个操作符进行比较时则要遵循下列规则。
    • null 和 undefined 是相等的。
    • 要比较相等性之前,不能将 null 和 undefined 转换成其他任何值。
    • 如果有一个操作数是 NaN,则相等操作符返回 flase,而不相等操作符返回 true,重要提示:即使两个操作数都是 NaN,相等操作符返回 flase;因为按照规则,NaN 不等于 NaN。
    • 如果两个操作数都是对象,则比较它们是不是同一个对象,如果两个操作数指向同一个对象,则相等操作符返回 true,否则,返回 flase。
      全等(=)和不全等(!)
    • 不会发生强制类型转换

    6.5) 条件操作符 (三元操作符)
    6.6) 赋值操作符(=)

    • 乘/赋值 (*=)
    • 除/赋值 (/=)
    • 加/赋值 (+=)
    • 件/赋值 (-=)
    • 取模/赋值 (%=)
      6.7)逗号操作符
      用于声明多个变量

    语句

    1. if 语句
    2. do-while 语句 (循环体内代码至少执行一次)
    3. while 语句 (前测循环语句)
    4. for 语句 (前测循环语句)
    5. for-in 语句 (精准的迭代语句,可以用来枚举对象的属性)
    6. break 和 continue 语句
      break 语句会立即退出循环,强制继续执行循环后面的语句。而 continue 语句虽然也是立即退出循环,但是退出循环后会从循环顶部执行。
      7)switch 语句 (default)

    函数

    函数对任何语言来说都是一个核心的概念,通过函数可以封装任意多条语句,而且可以在任何地方、任何时候调用执行。
    函数参数不介意传递多少个参数,也不在意传进来参数是什么类型。arguments 类数组的功能。
    1) 没有重载,后面定义的同名函数会覆盖前面的的函数。

  • 相关阅读:
    福利 | 简历模板大放送
    如何脱颖而出?成为优秀的人
    未来最重要的三个能力
    如何提升你的阅读能力?
    2016 Top 10 Android Library
    如何提升你的面试机会?
    推荐一些非常有用的学习网站
    谈谈学习方法
    你为什么还不够优秀?
    vue
  • 原文地址:https://www.cnblogs.com/zhourongcode/p/10885535.html
Copyright © 2011-2022 走看看