JavaScript红宝书学习1——语法基础

《JavaScript红宝书第四版》学习记录1

2. HTML中的JavaScript

执行脚本,可以设置defer,async属性

  1. defer:不确保多个defer脚本的执行顺序,最好只使用一个defer
<script defer src=""> </script>  //告诉浏览器立即下载,但是延迟执行
  1. async: 不保证顺序,完全异步
<script async src=""> </script> //立即下载,异步执行

3. 语法基础

3.4 数据类型

3.4.5 Number

  1. 关于float类型的计算精度:

    let a = 0.1, b=0.2
    a+b //0.30000000000000004
    a+b==0.3  //false
    
    let c = 0.15, d=0.25
    c+d //0.4
    c+d==0.4 //true
    

    【特别】永远不要测试某个特定的浮点值

  2. isNaN用法

    isNaN(10)  //false
    isNaN(true) //false
    isNaN("sdf") //true,无法转换为数值
    isNaN("12546")  //false,可以转换为数值
    isNaN("undefined")  //true
    isNaN(+0)  //false
    isNaN(Infinity)  //false
    
  3. 数值转换

    1)Number()转换

    Number("undefined") //NaN 
    Number(0) //0 
    Number(true) //1 
    Number(null) //0 
    Number("12345") //12345 
    Number(" 12345 ") //12345 
    Number(0xA34) //2612 
    Number("") //0 
    Number(2.345) //2.345
    

    2)parseInt()

    console.log(parseInt("undefined")) //NaN
    console.log(parseInt(0)) //0
    console.log(parseInt(true)) //NaN,有区别
    console.log(parseInt(null)) //NaN,有区别
    console.log(parseInt("12345")) //12345
    console.log(parseInt(" 12345 ")) //12345
    console.log(parseInt(0xA34)) //2612
    console.log(parseInt("")) //NaN,有区别,Number("")返回0
    console.log(parseInt(2.345)) //2,有区别
    

    3)二者对比:

    【注意】Number()再字符串转换时比较复杂而且反常规,如果想要得到整数,推荐优先使用parseInt, 尤其是对于空串的处理,parseInt返回NaN,Number返回0

    Number("1234blue")  //NaN
    parseInt("1234blue")  //1234
    
    Number("")  //0
    parseInt("")  //NaN
    

    二者对于指定转换底数:

    parseInt('0x12', 16) //18 
    parseInt('0x12', 10) //0 
    Number('0x12', 16) //18 
    Number('0x12') //18 
    Number('AF',16) //NaN 
    parseInt('AF',16) //175 
    parseInt('AF') //NaN
    
    1. parseFloat()

    用法类似于parseInt(), 不同之处是会忽略所有的开头的0

3.4.6 String类型

  1. 特点:

    具有【不可变性】,一旦创建,不再改变。改变的过程是把原来的销毁,继而创建新string的过程

  2. 字符串转换

    • 几乎所有类型都可以直接使用toString()

    • 也可以使用+“” 这样的方式来转换

      let sss = 198
      undefined
      sss+""
      "198"
      
    • 在进行数字转换时,可以接收参数指定底数

      let str = 18
      undefined
      str.toString()
      "18"
      str.toString(16)
      "12"
      str.toString(2)
      "10010"
      str.toString(8)
      "22"
      
  3. 模板字符串

    • 特点是以反引号``开头和结尾,适用于代码等,保留反引号之间的空格

    • 可以用于【字符串插值】,举例

      let printVal = "testPrint"
      undefined
      console.log(`Console.log to print template value, e.g. ${printVal}`)
      VM561:1 Console.log to print template value, e.g. testPrint
      undefined
      console.log("Console.log to print template value, e.g. ${printVal}")
      VM574:1 Console.log to print template value, e.g. ${printVal}
      undefined
      

      之前看到有这种用法,而自己尝试时一直不成功,原因就是没有使用反引号

  4. 【暂不关注】模板字面量标签函数

    这部分内容看书没看懂,查了一下是ES6引入的,主要用于HTML标签过滤防止恶意篡改内容;以及表达式等参数的个数不确定时用于字面量的拼接;或者多语言的切换(‘欢迎您xxx,您是xxxx位访问者)等,目前没有用到。

  5. 【暂不关注】String.raw(), 返回的是原始字符串,也就是包含了所有转义字符的,比如\n等,日后可尝试使用

3.4.7 Symbol

  1. 基本特点,初始化
let sym = Symbol()
typeof sym  "symbol"
let sym1 = new Symbol()  //【注意】,不能对Symbol使用new关键字, 报错
VM758:1 Uncaught TypeError: Symbol is not a constructor
    at new Symbol (<anonymous>)
    at <anonymous>:1:12
(anonymous) @ VM758:1
let sym = Symbol('foo') 
sym//Symbol(foo)
  1. symbol的典型应用场景总结:
  • 对于原始方法的重写,根据自身需求进行Symbol.iterator,Symbol.match,Symbol.replace,Symbol.search等诸多方法的重写,很多勇于正则表达式

  • 作为对象的属性名:可以理解为私有属性,使用for循环遍历key的时候访问不到,只有通过Object[]的方式访问。

    const testName = Symbol('testName')
    const obj={
        [testName]:'Jim'
    }
    obj // {Symbol(testName): "Jim"}Symbol(testName): "Jim"__proto__: Object
    obj.testName  // undefined
    obj[testName]  //"Jim"
    
  • 【可使用】消除魔法变量

    if(tag === 'status') {xxxx}
    else if (tag === 'router') {xxxx}
    else if (tag === 'rule') {xxxx}
    
    //使用Symbol
    const tagTypes = {
    	status: Symbol(),
    	router: Symbol(),
    	rule: Symbol(),
    }
    if(tag === tagTypes.status) {xxxx}
    else if (tag === tagTypes.router) {xxxx}
    else if (tag === tagTypes.rule) {xxxx}
    
  • 有些场景,相当于uuid,比如多个库都有id这个属性,那么可能造成id的重复引用导致混乱,而使用Symbol类型作为key则问题解决

  • 目前Symbol在我们的项目中未找到合适的应用场景,还需要多学习,作为一个积累

3.4.8 Object

  1. 每个Object都有如下固有属性:

    constructor//构造函数
    hasOwnProperty(propertyName) //判断对象实例上是否存在xxx属性
    isPropertyOf(Object)  //判断是否是另一个对象xxxx的原型
    propertyIsEnumerable(propertyName) //判断某属性是否可枚举,用for-in语句枚举
    toLocaleString() //返回字符串表示,反应对象的本地执行化环境
    toString() //返回字符串表示
    valueOf()  //返回对象对应的字符串、数值或布尔值表示,通常与toString()相同
    
  2. propertyIsEnumerable理解

    本来理解为某个属性xxx对于它所在的object是否是可枚举的,也就是是否用key可访问到,后来尝试后发现理解错误。

    比如我定义了obj的Symbol类型的key,这个key应该是使用for in遍历不到的,本以为是propertyIsEnumerable为false的,但实际上这个propertyIsEnumerable是针对属性值本身而言的,也就是说你的属性值本身是string,那么不能for…in…,如果是一个数值或者其他类型就可以for…in…

  3. toLocaleString

    这个属性是比较冷门的格式转换方法,可以用于

    • 数字格式转换,比如3500,转换为3,500;或者转换为百分比,保留xxx位数等
    • 货币格式转换
    • 日期格式转换,Date.toLocaleString()

    详细应用可以参照帖子 https://blog.csdn.net/weixin_39749820/article/details/82869537

3.5 操作符

3.5.2 位操作

​ 位操作很多老师讲课时说一般在职业生涯中很难遇到,不过我们开发过程中遇到了,需要前端进行多个int值的拼接,js中进行有符号值与无符号值的转换,用到>>>0这一操作。

3.5.3 布尔操作符

  1. 逻辑非

    !!操作符,相当于调用Boolean(), 可以把任意表达式转为布尔值,比较方便使用

    if(!!xxx)  //用于判断这个xxx变量是否合法
    //对于null, NaN, undefined都会返回false
    
  2. 逻辑与,逻辑或

    主要是在应用中需要注意,二者均有**【短路特性】**,只是取决于第一个或者第二个操作数的结果

  3. 指数操作符 **(相当于Math.pow())

    3**2  //9
    16 ** 0.5  //4
    
    let squ = 3
    squ **= 2  //9, 复合赋值,类似于+=,-=用法;只是语法简单,不会提升性能
    
  4. 关系操作符

    • 对于'23'<'3' //true这类似的比较,比较的是ASCII码,'2’的编码是50,'3’编码51
    • NaN跟谁比,都是false,无论是大于还是小于
上一篇:关于parseInt函数的一切


下一篇:JS、javascript计算两个时间差