当前位置: 首页 > 科技观察

容易被忽视的JavaScript细节总结

时间:2023-03-16 00:18:30 科技观察

《JavaScript 权威指南》本书从第四版开始到第六版。每个版本我都一个字一个字的看了好几遍,但是每次看完的感受都是完全不一样的。上周一,我又打开了这本??犀牛书。这次带着批判的精神和研究的精神来到这里,所以也写下了一些看的时候的感受和笔记,这些都是容易被忽略的点,有些内容在犀牛书中不一定提到。之前在微博发过,整理了一下,放在这里方便阅读。语句/表达式从另一个角度理解语句(statemaents)和表达式(expressions):表达式不会改变程序的运行状态,但语句会。还有一种表达式语句,可以理解为表达式和语句的交集,比如({a:1})、"usestrict;"等,我觉得没必要拘泥于它,并没有多大意义。字符集ES3需要JS实现Unicode2.1及后续版本,而ES5只需要支持Unicode3及后续版本。Unicode字符在2005年超过100,000个字符,并且还在更新中。最新版本是8.0。分号如果你在写JS代码的时候不喜欢分号,想不通什么时候加分号,可以这样做:以“(”、“[”、“/”、“+”、“-”开头"在语句开始前加一个分号,如;(a+b).toString()。ES5严格模式禁止八进制。目前各个引擎对JS的实现存在差异,有的支持八进制,部分不支持,禁止八进制的原因:String和Number经常相互转换,而0开头的八进制数据特别容易混淆,容易混淆机器,比如09要不要转换成9还是直接报错?hex没有这个问题,比如0x98。更多信息看这里。PrecisionJS使用IEEE-754浮点数表示,是二进制表示。由于精度原因,JS不能表示所有的实数。它能显示的浮点数是有限的,比如不能准确表示ent三分之一的数字文字。这也导致了浮点数的计算出现错误,比如0.3-0.2!=0.2-0.1,因为在计算的过程中,出现了数据溢出,丢失了精度。null/undefined对系统级、意外或类似错误的值使用undefined,对程序级、正常或预期值使用null。在正常编程中给变量赋值时,不要使用undefined而是null。值得注意的是ES3中的undefined是可以重新赋值的,ES5修复了这个bug。通常我们使用void0来恢复/替换未定义的值。评估是一件很难掌握的事情。它更像是ES3中的Function,但更像是ES5中的运算符(严格模式下不允许使用别名,否则会报错,并作为保留字使用)。事实上,ES3不允许eval被别名化,但许多实现仍然允许它并将其作为全局代码执行。浏览器,尤其是IE,对其实现比较迷惑,无章可循。不过IE提供了一个execScript函数,类似于全局的eval,这个函数每次执行都会返回null。需要用到eval的场景不多,尽量少用。一般使用newFunction即可满足需求。参考删除属性的坑:a={n:{x:2}},b=a.n;删除一个;这段代码执行完后,b.x还是等于2,因为对象{x:2}被a和b同时删除了,删除指令只是删除了a对它的引用,b上的引用还在存在。这种问题有可能导致内存泄漏。ObjectExtendingObject的freeze方法限制太多;defineGetter/lookupGetter和相应的Setter是很好用的属性。toLocalString如图,大家可能不知道JavaScript的toLocaleString还可以这么玩。this语义this上下文只有两种语义,一种是作为方法调用,this指向调用它的对象;另一个作为函数调用,指向全局对象(在严格模式下未定义)。它没有范围限制。如下图所示,由于a作为函数被调用,指向window,所以返回false。JavaScript可以调用执行的类型是Function类型,但也有可调用的Object,比如低版本IE中的一些宿主对象:document.getElementById,alert等。在很多浏览器中typeofRegExp也是Object.这绝对是一个非标准的实现,浏览器应该尽可能少地依赖它们,直到它们被弃用/修复。IE8的getter/setterObject.defineProperty虽然是ES5的东西,早在IE8就已经支持了,但是支持的并不完善,比如writable,enumerable,configurable这些配置项设置都是无效的,IE8主要支持getter/setter。JSON.stringifyJSON.stringify接受三个参数。很多人都知道第三个参数可以设置空白字符来美化输出,但是你可能不知道第二个参数的作用。它是{Array|Function}类型的,如果是Array则用来过滤key,如果是Function则可以对value进行处理,如图。SymbolES6增加了一种新的数据类型Symbol,它是原始数据类型(图1),具有对象的特性(图2),可以指向同一个引用(图3),可以作为key对象的但不能枚举(图4)。内置的Symbol会影响程序的执行(图5)。Symbol.iterator是一个重要的符号,可以使元素具有迭代属性(图6)。有很多技巧。见附图:http://weibo.com/1812166904/DqMwR8O6z伪数组添加Symbol.iterator有几种方式:duck类型识别的iterator函数、yield函数和直接使用Array遍历符号。见附图:http://weibo.com/1812166904/DqMBYebPwSet/WeakSetSet/WeakSet这种数据结构不能说没有用,但确实用处不大。前者是一个不允许重复成员的数组。顺便说一句,有了ES6的一些特性,后者虽然可以在一定程度上防止内存泄漏,但是也容易出错。例如,如果一个引用已经被垃圾回收,如果再次使用它可能会返回null。都是ES6的配套产品。Map/WeakMap是两个非常好的设计。常规的Object结构是String-Val键值对,扩展为AllType-Val。任何类型都可以作为它的Key,无论是服务端编程还是客户端编程,这个属性都带来了极大的方便。正则表达式理解正则零宽的含义:正则化中所谓的零宽断言类似于锚字符,匹配指定位置但不匹配内容,比如^匹配开头,$匹配结尾,\b匹配单词边界;(?=p)匹配“下一个字符匹配p”的位置,(?!p)匹配“下一个字符不匹配p”的位置。\b字符匹配单词边界,实际上是\w和\W之间的位置(\w匹配[a-zA-Z0-9])。很少有人使用\B,它匹配非单词边界位置。简单理解就是\w&\w之间的位置或者\W&\W之间的位置。不断学习和分享……内容碎片化,分享。很多很复杂,我就不一一列举了。有兴趣的同学可以关注我的微博,我的想法和笔记会同步在上面。感觉在这之前大概看了六七遍犀牛书,很多内容已经深深地刻在脑海里了,但是时间久了就会忘掉,时不时巩固和温习一下。毕竟是前端最基础的部分。带着疑问去看书,收获是截然不同的。犀牛书不难读,难的是你对这些知识点的理解深度。