<你不知道的Javascript>笔记
2017-12-10 21:44
337 查看
前言
Javascript本身是一门非常灵活的语言,如果是先有写过编译型语言的再来看看它,简直是灵活到你可以接近”瞎写”的程度还不会出错.然而凡事皆有双面性,它的灵活性背后是无数的坑.Javascript设计的时候,估计也没有考虑到会发展成今天这个规模,更是没有想到它居然可以用在后端.
很多在前端设计中无所谓的坑,放在后端就是灾难.这本书非常详细的介绍了那些Javascript中看似古怪的设计及其背后的深层次原因,值得一读.
这份笔记里将记录一些我认为比较有实践意义的东西.对于那些实际代码中应该抛弃的奇怪写法,不做深究.
类型转换
js本身规定了六个基本类型,在必要的时候,会发生类型转换.let a = 42; let b = a + ""; let c = String(a);
第二和第三个赋值操作时,都发生了类型转换,前者是隐式,将a强制转换为string类型,后者是显式.
转为string
基础类型转化规则定义如下:* null: “null”
* undefined: “undefined”
* boolean: “true”/”false”
* number: 通常和常规数学表达一致.有个特殊情况,在数字很小或很大的时候,将会转换出指数形式的结果,比如”1.07e21”
JSON.stringify()
所有JSON安全的值都可以用这个方法转为字符串.以下情形不属于JSON安全的对象:undefined, function, symbol以及循环引用.遇到前三者时会自动忽略,而循环引用会报错.
以下代码可以创建一个具有循环引用的JSON对象:
let a = {"prop0": "safe"}; a.prop1 = a;
JSON.stringify()还具有一个可选的参数,叫做
replacer.这个参数可以传两种类型的值进去,数组和函数.
* 传入数组的时候,这个数组里元素必须是字符串.它指出了JSON对象中要处理的键.未在该数组中列出的键会被忽略.如:
let a = { "b": 0, "c": 1, "d": 2 }; JSON.stringify(a, ["c", "d"]);
传入函数的时候,对象的每个键会调用一次,同时对象本身也会调用一次.
转为number
true转换为1,false转换为0(反过来好像也是这样).undefined转换为NaN,null转换为0.转为boolean
ES5中定义了转换为boolean类型时的规则.转换结果为false的如下:*
undefined
*
null
*
false
*
+0 -0 NaN
*
""
除此以外,其它所有的东西,转换结果都是true.包括空对象,空数组这些.
显式转换
string & number
字符串转数字,如果要用类型转换的方式来做,如下:let c = "3.14"; let d = 5+ +c;
这其实是一种可读性很差的写法,我个人并不推荐这么写.书里还举了一个疯狂的例子:
1 + - + + + - + 1; // What the fuck?
还可以调用构造函数
Number()进行转换.
另外,用的比较多的
parseInt()也是一个办法,不过它的准确定义应该是解析字符串,而非类型转换.
parseInt()函数还有第二个参数,指定了转换数字的目标进制.比如要字符串是十六进制表示,如下:
let a = "100"; parseInt(a, 16);
注意,这里是将100作为一个十六进制数来看待,而并不是将100作为一个十进制数看待,返回转十六进制的结果.
与之相反的,是
toString()方法,它也可以附带一个参数,将
Number类型的数据转成字符串并以指定的进制输出.一个有趣的应用是产生随机字符串:
(Math.random()*100000000000).toString(36).replace('.', "");
这段代码的原理就是36进制的表示恰好是0-9和a-z的完整集合,转成字符串之后,字符串里只会包含数字和小写字母.
| 和 ~运算符
~运算符会对一个32位有符号整数执行按位取反操作,包括符号位.如果目标参数不是整数,则先强制转换为整数,再执行取反.|会对一个32位有符号整数执行按位或操作.如果参数不是整数,同样转换为整数再运算.
如下两个应用会实现取整的效果:
let a = 1.123; let b = 0 | a;
由于0和任何数按位或都是另一个数本身,因此这里返回的就是a取整的结果.
let a = 1.1415926; let b = ~~a;
第一个~首先将a取整后取反.a取整的结果是
0x00000001,按位取反后是
0xfffffffe,即-2的补码表示.第二个~对
0xfffffffe进行按位取反,就得到了取整的结果
0x00000001.
这种写法看似简洁,并且使用了位运算.一个通常的说法是使用位运算效率会高很多.对于编译型语言,结论成立.对于解释型语言,打问号.看如下的代码:
let a = []; for (let i = 0; i < 100000; i ++) { a.push(Math.random() * 1000000) } let ts = Date.now(); for (let i = 0; i < 100000; i ++) { ~~a[i]; } console.log(Date.now() - ts); ts = Date.now(); for (let i = 0; i < 100000; i ++) { Math.floor(a[i]); } console.log(Date.now() - ts);
在我的机器上跑下来的结果是,前者26ms,后者3ms.当然,这个结果会随着不同的node版本会有差异,但已经足够证明一点:不要迷信那些在传统编译型语言中惯用的优化手段.
4000
相关文章推荐
- java 从零开始,学习笔记之基础入门<javascript>(三十)
- <<JavaScript编程全解>>阅读笔记之变量与对象
- javascript-学习笔记-<script> </script> 代码执行的和上一个博客相对应的
- 概念笔记之[javascript<-2->]闭包和封装
- <<JavaScript编程全解>>阅读笔记之函数与闭包
- <javascript学习笔记>javascript 实现隔行变色
- javascript特效<一>--学习笔记
- 【javascript笔记】关于函数的构造函数和prototype<四>
- javaScript学习笔记——如何让<canvas>动起来
- javascript学习笔记——如何修改<a href="#">url name</a>
- JavaScript 笔记 - <script>标签 defer属性 (延迟脚本)
- <高性能JavaScript>笔记 [1~3]
- JavaScript 笔记 - <noscript> 元素
- <高性能JavaScript>笔记 [4~6]
- javascript面向对象编程笔记第一章<基本类型>
- <javascript学习笔记> 设置和获取dom的css样式 、获取url参数
- 学习笔记--javascript 的<script></script>放在body和<head></head>的区别
- 【javascript笔记】js基本数据类型<零>
- 我的JavaScript学习笔记<续>
- <<JavaScript编程全解>>阅读笔记之javascript数据类型