《JavaScript红宝书第四版》学习记录1
2. HTML中的JavaScript
执行脚本,可以设置defer,async属性
- defer:不确保多个defer脚本的执行顺序,最好只使用一个defer
<script defer src=""> </script> //告诉浏览器立即下载,但是延迟执行
- async: 不保证顺序,完全异步
<script async src=""> </script> //立即下载,异步执行
3. 语法基础
3.4 数据类型
3.4.5 Number
-
关于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
【特别】永远不要测试某个特定的浮点值
-
isNaN用法
isNaN(10) //false isNaN(true) //false isNaN("sdf") //true,无法转换为数值 isNaN("12546") //false,可以转换为数值 isNaN("undefined") //true isNaN(+0) //false isNaN(Infinity) //false
-
数值转换
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
- parseFloat()
用法类似于parseInt(), 不同之处是会忽略所有的开头的0
3.4.6 String类型
-
特点:
具有【不可变性】,一旦创建,不再改变。改变的过程是把原来的销毁,继而创建新string的过程
-
字符串转换
-
几乎所有类型都可以直接使用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"
-
-
模板字符串
-
特点是以反引号``开头和结尾,适用于代码等,保留反引号之间的空格
-
可以用于【字符串插值】,举例
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
之前看到有这种用法,而自己尝试时一直不成功,原因就是没有使用反引号
-
-
【暂不关注】模板字面量标签函数
这部分内容看书没看懂,查了一下是ES6引入的,主要用于HTML标签过滤防止恶意篡改内容;以及表达式等参数的个数不确定时用于字面量的拼接;或者多语言的切换(‘欢迎您xxx,您是xxxx位访问者)等,目前没有用到。
-
【暂不关注】String.raw(), 返回的是原始字符串,也就是包含了所有转义字符的,比如\n等,日后可尝试使用
3.4.7 Symbol
- 基本特点,初始化
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)
- 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
-
每个Object都有如下固有属性:
constructor//构造函数 hasOwnProperty(propertyName) //判断对象实例上是否存在xxx属性 isPropertyOf(Object) //判断是否是另一个对象xxxx的原型 propertyIsEnumerable(propertyName) //判断某属性是否可枚举,用for-in语句枚举 toLocaleString() //返回字符串表示,反应对象的本地执行化环境 toString() //返回字符串表示 valueOf() //返回对象对应的字符串、数值或布尔值表示,通常与toString()相同
-
propertyIsEnumerable理解
本来理解为某个属性xxx对于它所在的object是否是可枚举的,也就是是否用key可访问到,后来尝试后发现理解错误。
比如我定义了obj的Symbol类型的key,这个key应该是使用for in遍历不到的,本以为是propertyIsEnumerable为false的,但实际上这个propertyIsEnumerable是针对属性值本身而言的,也就是说你的属性值本身是string,那么不能for…in…,如果是一个数值或者其他类型就可以for…in…
-
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 布尔操作符
-
逻辑非
!!
操作符,相当于调用Boolean(), 可以把任意表达式转为布尔值,比较方便使用if(!!xxx) //用于判断这个xxx变量是否合法 //对于null, NaN, undefined都会返回false
-
逻辑与,逻辑或
主要是在应用中需要注意,二者均有**【短路特性】**,只是取决于第一个或者第二个操作数的结果
-
指数操作符 **(相当于Math.pow())
3**2 //9 16 ** 0.5 //4 let squ = 3 squ **= 2 //9, 复合赋值,类似于+=,-=用法;只是语法简单,不会提升性能
-
关系操作符
- 对于
'23'<'3' //true
这类似的比较,比较的是ASCII码,'2’的编码是50,'3’编码51 - NaN跟谁比,都是false,无论是大于还是小于
- 对于