JavaScript基础入门(仅仅列举与其他语言的差别)

JavaScript Notes

基础语法

  1. 标签label:通常与break和continue搭配使用

    // 与break:跳出双层循环
    top:
      for (var i = 0; i < 3; i++){
        for (var j = 0; j < 3; j++){
          if (i === 1 && j === 1) break top;
          console.log('i=' + i + ', j=' + j);
        }
      }
    // i=0, j=0
    // i=0, j=1
    // i=0, j=2
    // i=1, j=0
    
    // 与break:跳出代码块
    foo: {
      console.log(1);
      break foo;
      console.log('本行不会输出');
    }
    console.log(2);
    // 1
    // 2
    
    // 与continue:会跳过当前循环,直接进入下一轮外层循环
    top:
      for (var i = 0; i < 3; i++){
        for (var j = 0; j < 3; j++){
          if (i === 1 && j === 1) continue top;
          console.log('i=' + i + ', j=' + j);
        }
      }
    

数据类型

  1. 七种:数值、字符串、布尔值、nullundefinedobjectSymbol

  2. typeof运算符:

    typeof 123 // "number"
    typeof '123' // "string"
    typeof false // "boolean"
    typeof undefined // "undefined"
    typeof null // "object"
    
    function f() {}
    typeof f // "function"
    
    typeof window // "object"
    typeof {} // "object"
    typeof [] // "object"
    
    

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

    // 错误的写法
    if (v) {
      // ...
    }
    // ReferenceError: v is not defined
    
    // 正确的写法
    if (typeof v === "undefined") {
      // ...
    }
    
  3. nullundefined都可以表示“没有”,含义非常相似:

    if (!undefined) {
      console.log('undefined is false');
    }
    // undefined is false
    
    if (!null) {
      console.log('null is false');
    }
    // null is false
    
    undefined == null  // true
    

    区别是这样的:null是一个表示“空”的对象,转为数值时为0undefined是一个表示"此处无定义"的原始值,转为数值时为NaN

    Number(null) // 0
    5 + null // 5
    
    Number(undefined) // NaN
    5 + undefined // NaN
    
  4. 布尔值转换规则是除了下面六个值被转为false,其他值都视为true注意:空数组([])和空对象({})对应的布尔值,都是true

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

数值

  1. JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,11.0是相同的,是同一个数。

    1 === 1.0 // true
    

    某些运算只有整数才能完成,此时 JavaScript 会自动把64位浮点数,转成32位整数,然后再进行运算。

    浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即 -2^53 到 2^53,都可以精确表示。

  2. JavaScript 能够表示的数值范围为2^1024 到 2^-1023(开区间)。超出范围发溢出,但是不同于c语言,正向溢出返回Infinity,负向溢出返回0。

    Math.pow(2, 1024) // Infinity
    Math.pow(2, -1023) // 0
    
  3. 八进制:有前缀0o00的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。通常来说,有前导0的数值会被视为八进制,但是如果前导0后面有数字89,则该数值被视为十进制。

    0888 // 888
    0777 // 511
    
  4. 特殊值:

    • +0-0:唯一有区别的场合是,+0-0当作分母,返回的值是不相等的。

    • NaN:不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于Number。

      5 - 'x' // NaN
      Math.acos(2) // NaN
      Math.log(-1) // NaN
      Math.sqrt(-1) // NaN
      0 / 0 // NaN
      
      • NaN不等于任何值,包括它本身。

      • NaN在布尔运算时被当作false

      • NaN与任何数(包括它自己)的运算,得到的都是NaN

    • Infinity:表示“无穷”,用来表示两种场景。一种是一个正的数值太大,或一个负的数值太小,无法表示;另一种是非0数值除以0,得到Infinity

      // 场景一
      Math.pow(2, 1024) // Infinity
      
      // 场景二
      0 / 0 // NaN
      1 / 0 // Infinity
      
      • Infinity有正负之分,Infinity表示正的无穷,-Infinity表示负的无穷。

        Infinity === -Infinity // false
        
        1 / -0 // -Infinity
        -1 / -0 // Infinity
        
      • InfinityNaN比较,总是返回false

      • Infinity的四则运算,符合无穷的数学计算规则。

        5 * Infinity // Infinity
        5 - Infinity // -Infinity
        Infinity / 5 // Infinity
        5 / Infinity // 0
        

        0乘以Infinity,返回NaN;0除以Infinity,返回0Infinity除以0,返回Infinity

        0 * Infinity // NaN
        0 / Infinity // 0
        Infinity / 0 // Infinity
        

        Infinity加上或乘以Infinity,返回的还是Infinity

        Infinity减去或除以Infinity,得到NaN

        Infinitynull计算时,null会转成0,等同于与0的计算。

        Infinityundefined计算,返回的都是NaN

  5. 与数值相关的全局方法:

    • parseInt():用于将字符串转为整数。

      字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符(特殊地,头部的空格是直接去除),就不再进行下去,返回已经转好的部分。

      parseInt('123') // 123
      // 字符串头部有空格,空格会被自动去除
      parseInt('   81') // 81
      // 参数不是字符串,则会先转为字符串再转换
      parseInt(1.23) // 1
      
      parseInt('12.34') // 12
      parseInt('15e2') // 15
      
      // 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN。
      parseInt('abc') // NaN
      parseInt('.3') // NaN
      parseInt('+1') // 1
      parseInt('-2') // -2
      
      // 如果字符串以0x或0X开头,parseInt会将其按照十六进制数解析。
      parseInt('0x10') // 16
      
      // 对于那些会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果。
      parseInt(1000000000000000000000.5) // 1
      // 等同于
      parseInt('1e+21') // 1
      
      parseInt(0.0000008) // 8
      // 等同于
      parseInt('8e-7') // 8
      

      parseInt方法还可以接受第二个参数(2到36之间),表示被解析的值的进制,返回该值对应的十进制数。

      parseInt('1000', 2) // 8
      parseInt('1000', 6) // 216
      parseInt('1000', 8) // 512
      
      parseInt('10', 37) // NaN
      parseInt('10', 1) // NaN
      // 如果第二个参数是0、undefined和null,则直接忽略。
      parseInt('10', 0) // 10
      parseInt('10', null) // 10
      parseInt('10', undefined) // 10
      
      // 如果字符串包含对于指定进制无意义的字符,则从最高位开始,只返回可以转换的数值。
      // 如果最高位无法转换,则直接返回NaN。
      parseInt('1546', 2) // 1
      parseInt('546', 2) // NaN
      
      // 如果parseInt的第一个参数不是字符串,会被先转为字符串。这会导致一些令人意外的结果。
      parseInt(0x11, 36) // 43
      parseInt(0x11, 2) // 1
      // 等同于
      parseInt('17', 36)
      parseInt('17', 2)
      
    • parseFloat:用于将一个字符串转为浮点数。

      // 如果字符串符合科学计数法,则会进行相应的转换。
      parseFloat('314e-2') // 3.14
      parseFloat('0.0314E+2') // 3.14
      
      // 如果字符串包含不能转为浮点数的字符,则不再进行往后转换,返回已经转好的部分。
      parseFloat('3.14more non-digit characters') // 3.14
      
      // parseFloat方法会自动过滤字符串前导的空格。
      parseFloat('\t\v\r12.34\n ') // 12.34
      
      // 如果参数不是字符串,则会先转为字符串再转换。
      parseFloat([1.23]) // 1.23
      
      // 如果字符串的第一个字符不能转化为浮点数,则返回NaN。
      parseFloat([]) // NaN
      parseFloat('FF2') // NaN
      parseFloat('') // NaN
      
    • isNaN:用来判断一个值是否为NaN。但是,isNaN只对数值有效,如果传入其他值,会被先转成数值(Number函数)。比如,传入字符串的时候,字符串会被先转成NaN,所以最后返回true,这一点要特别引起注意。也就是说,isNaNtrue的值,有可能不是NaN,而是一个字符串。

      isNaN(NaN) // true
      isNaN(123) // false
      
      isNaN('Hello') // true
      // 相当于
      isNaN(Number('Hello')) // true
      isNaN(['xzy']) // true
      // 等同于
      isNaN(Number(['xzy'])) // true
      
      // 对于空数组和只有一个数值成员的数组,isNaN返回false,原因是这些数组能被Number函数转成数值。
      isNaN([]) // false
      isNaN([123]) // false
      isNaN(['123']) // false
      
      // 因此,使用isNaN之前,最好判断一下数据类型。
      function myIsNaN(value) {
        return typeof value === 'number' && isNaN(value);
      }
      

      判断NaN更可靠的方法是,利用NaN为唯一不等于自身的值的这个特点,进行判断。

      function myIsNaN(value) {
        return value !== value;
      }
      
    • isFinite:返回一个布尔值,表示某个值是否为正常的数值。

      isFinite(Infinity) // false
      isFinite(-Infinity) // false
      isFinite(NaN) // false
      isFinite(undefined) // false
      isFinite(null) // true
      isFinite(-1) // true
      

      除了Infinity-InfinityNaNundefined这几个值会返回falseisFinite对于其他的数值都会返回true

字符串

  1. 由于 HTML 语言的属性值使用双引号,所以很多项目约定 JavaScript 语言的字符串只使用单引号。

  2. 字符串分成多行书写:采用\或者+

  3. 如果想输出多行字符串,有一种利用多行注释的变通方法。

    (function () { /*
    line 1
    line 2
    line 3
    */}).toString().split('\n').slice(1, -1).join('\n')
    // "line 1
    // line 2
    // line 3"
    
  4. 反斜杠还有三种特殊用法。

    (1)\HHH:反斜杠后面紧跟三个八进制数(000377),代表一个字符。

    (2)\xHH\x后面紧跟两个十六进制数(00FF),代表一个字符。

    (3)\uXXXX\u后面紧跟四个十六进制数(0000FFFF),代表一个字符。

  5. 字符串可以被视为字符数组。如果方括号中的数字超过字符串的长度,或者方括号中根本不是数字,则返回undefined

    字符串内部的单个字符无法改变和增删。length属性返回字符串的长度,该属性也是无法改变的。

  6. Base64 是一种编码方法,可以将任意值转成 0~9、A~Z、a-z、+/这64个字符组成的可打印字符。使用它的主要目的,不是为了加密,而是为了不出现特殊字符,简化程序的处理。

    JavaScript 原生提供两个 Base64 相关的方法。

    • btoa():任意值转为 Base64 编码
    • atob():Base64 编码转为原来的值
    var string = 'Hello World!';
    btoa(string) // "SGVsbG8gV29ybGQh"
    atob('SGVsbG8gV29ybGQh') // "Hello World!"
    
    // 注意,这两个方法不适合非 ASCII 码的字符,会报错。
    btoa('你好') // 报错
    
    // 要将非 ASCII 码字符转为 Base64 编码,必须中间插入一个转码环节,再使用这两个方法。
    function b64Encode(str) {
      return btoa(encodeURIComponent(str));
    }
    
    function b64Decode(str) {
      return decodeURIComponent(atob(str));
    }
    
    b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
    b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
    

对象

  1. 对象的生成:

    var obj = {
        'a': 100,
        "f": function (x) {
            return x*x;
        },
    };
    
  2. 对象的引用和Java类似。

  3. 如果要解释为对象,最好在大括号前加上圆括号。因为圆括号的里面,只能是表达式,所以确保大括号只能解释为对象。

    ({ foo: 123 }) // 正确
    ({ console.log(123) }) // 报错
    

    这种差异在eval语句(作用是对字符串求值)中反映得最明显。

    eval('{foo: 123}') // 123
    eval('({foo: 123})') // {foo: 123}
    
  4. 属性的操作

    • 属性的读取:数值键名不能使用点运算符(因为会被当成小数点),只能使用方括号运算符。

    • 属性的产看:Object.keys(obj);

    • 属性的删除:delete命令用于删除对象的属性,删除成功后返回true需要注意的是,delete命令只能删除对象本身的属性,无法删除继承的属性(如toString)。

      delete obj.p // true
      
      // 删除一个不存在的属性,delete不报错,而且返回true。
      var obj = {};
      delete obj.p // true
      
      //只有一种情况,delete命令会返回false,那就是该属性存在,且不得删除。
      Object.defineProperty
      
    • 属性是否存在:in运算符用于检查对象是否包含某个属性(检查的是键名),如果包含就返回true,否则返回false。它的左边是一个字符串,表示属性名,右边是一个对象。

      var obj = { p: 1 };
      'p' in obj // true
      'toString' in obj // true
      

      in运算符的一个问题是,它不能识别哪些属性是对象自身的,哪些属性是继承的。就像上面代码中,对象obj本身并没有toString属性,但是in运算符会返回true,因为这个属性是继承的。

      这时,可以使用对象的hasOwnProperty方法判断一下,是否为对象自身的属性。

      var obj = {};
      if ('toString' in obj) {
        console.log(obj.hasOwnProperty('toString')) // false
      }
      
    • 属性的遍历:for...in循环用来遍历一个对象的全部属性。

      for...in循环有两个使用注意点:

      • 它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性(如toString属性)。
      • 它不仅遍历对象自身的属性,还遍历继承的属性。

      一般情况下,都是只想遍历对象自身的属性,所以使用for...in的时候,应该结合使用hasOwnProperty方法,在循环内部判断一下,某个属性是否为对象自身的属性。

      var person = { name: '老张' };
      
      for (var key in person) {
        if (person.hasOwnProperty(key)) {
          console.log(key);
        }
      }
      
  5. with语句,它的作用是操作同一个对象的多个属性时,提供一些书写的方便。

    var obj = {
      p1: 1,
      p2: 2,
    };
    with (obj) {
      p1 = 4;
      p2 = 5;
    }
    // 等同于
    obj.p1 = 4;
    obj.p2 = 5;
    

函数

  1. 函数的声明:

    function f(...) {}
    
    var f = function(...) {};
    // 下面这种形式可以在函数体内部调用自身,也方便除错
    var f = function f() {};
    
    // Function 构造函数基本无人使用
    
  2. 如果同一个函数被多次声明,后面的声明就会覆盖前面的声明。

    function f() {
      console.log(1);
    }
    f() // 2  此处调用的是后文的f函数
    
    function f() {
      console.log(2);
    }
    f() // 2
    

    由于函数名的提升,前一次声明在任何时候都是无效的,这一点要特别注意。

    JavaScript 引擎将函数名视同变量名,所以采用function命令声明函数时,整个函数会像变量声明一样,被提升到代码头部。所以,下面的代码不会报错。

    f();
    
    function f() {}
    

    表面上,上面代码好像在声明之前就调用了函数f。但是实际上,由于“变量提升”,函数f被提升到了代码头部,也就是在调用之前已经声明了。但是,如果采用赋值语句定义函数,JavaScript 就会报错。

    f();
    var f = function (){};
    // TypeError: undefined is not a function
    

    上面的代码等同于下面的形式。

    var f;
    f();
    f = function () {};
    

    上面代码第二行,调用f的时候,f只是被声明了,还没有被赋值,等于undefined,所以会报错。

    注意,如果像下面例子那样,采用function命令和var赋值语句声明同一个函数,由于存在函数提升,最后会采用var赋值语句的定义。

    var f = function () {
      console.log('1');
    }
    
    function f() {
      console.log('2');
    }
    
    f() // 1
    

    上面例子中,表面上后面声明的函数f,应该覆盖前面的var赋值语句,但是由于存在函数提升,实际上正好反过来。

参考:网道

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值