《JavaScript语言精粹》学习笔记
按章节来记录的,都是看这本书时的学习笔记,有些地方真的是,不看根本不知道原来是这个样子。
知其所以然的学习过程
2. 语法
- 注释
在JavaScript中,/ *
可能出现在正则表达式字面量里,所以块注释对于被注释的代码块来说是<u>不安全的</u>。
推荐使用
//
来做注释
5. 继承
5.2 原型
在一个纯粹的原型模式中,我们将摒弃类,转而关注对象。基于原型的继承相比于基于类的继承在概念上更为简单:<u>一个新对象可以继承一个旧对象的属性。</u>
6. 数组
数组是一段线性分配的内存,它通过整数计算偏移并访问其中的元素。数组是一种性能出色的数据结构。不幸的是,JavaScript没有想此类数组一样的数据结构。
作为替代,JavaScript提供了一种拥有一些类数组特性的对象。它把数组的下标转变成字符串,用其作为属性。
- JavaScript允许数组包含任意混合类型的值。
var misc = ['string', 889, true, false, null, undefined, ['nested', 'array'], {object: true}, NaN];
- 每个数组都有一个length属性。和大多数其他语言不同,JavaScript的数组的length是没有上界的。
- !!! 数组的length属性不一定等于数组的长度。
array只有一个属性,就是length,length表示的是数组所占内存空间的数目,而不仅仅是数组中元素的个数.
> test[1000] = '4';
< "4"
> test.length
< 1001
array-length.png
-
删除
由于JavaScript的数组其实是一个对象,所以可以使用delete test[1]
来移除元素。但是遮掩会留下一个空洞,我们希望的是后面的元素依次移动位置,所以我, 可以使用splice(index, num, [])
来进行移除。 -
typeof运算符报告数组的类型是
object
。JavaScript没有一个好的机制来区别数组和对象。
// 有一个不错方法去判断一个对象是否为数组:
Object.prototype.toString.apply(misc) === '[object Array]'
7. 正则表达式
- 可处理正则表达式的方法有:
regexp.exec
、regexp.test
、string.match
、string.replace
、string.search
、string.split
。
附录A - 毒瘤
JavaScript中一些不可避免的问题特征,你必须知道这些问题并准备好应对的措施。
-
伪数组
-
<u>JavaScript没有真正的数组。</u>
-
typeof
运算符不能辨别数组和对象。
要辨别一个值是否是数组,需要检查它的constructor
属性。
var array = [1,2,3,4,5]; // 可以检测是否是数组 typeof array === 'object' && array.constructor === Array // 同样可以检测是否是数组 Object.prototype.toString.apply(array) === '[object Array]'
-
arguments
数组不是一个数组,它只是一个有着length
成员属性的对象。
-
-
假值
JavaScript拥有一组数量庞大的假值。
值 | 类型 |
---|---|
0 | Number |
NaN(非数字) | Number |
' '(空字符串) | String |
false | Boolean |
null | Object |
undefined | Undefined |
<u>这些值全部都等同于假,但是他们是不可互换的。</u>
undefined和null是全局变量。
- hasOwnProperty
只是一个方法,而不是一个运算符,所以在任何对象中,他可能会被一个不同的函数甚至一个非函数的值所替换。
another_stooge. hasOwnProperty = null;
- 对象
JavaScript的对象永远不会是真的空对象,因为它们可以从原型链中取的成员属性。这样,就会带来一些麻烦。
下面是一段程序去极端一算文本中每个单词出现的次数。
var counts = {};
var word;
var words = ['sad', 'wasdaf', 'erae', 'wafc'];
for(i = 0; i < words.length; i ++) {
word = words[i];
if(counts[word]) {
counts[word]++;
} else {
counts[word] = 1;
}
}
这里的if(counts[word])
是不严谨的,应该if(typeof counts[word] === 'number)
附录B - 糟粕
在本附录中,将会展示JavaScript的一些有问题的特性,但是我们很容易就能避免它们。
- ==
JavaScript有梁旭相等运算符: ===和!==,以及它们的邪恶的孪生兄弟==和!=。
如果两个运算数类型一致且拥有相同的值,则===返回true,否则!==返回false。
==和!= 则会在只有两个运算数类型一致的时候才会做出正确的判断。当类型不一致的时候,它们会试图强制转换值的类型,转换的规则复杂且难以记忆。下面有些例子:
表达式 | 值 |
---|---|
'' == '0' | false |
0 == '' | true |
0 == '0' | true |
false =='false' | false |
false ==0 | true |
false == undefined | false |
false == null | false |
null == undefined | true |
'\t\r\n' == 0 | true |
建议:
永远不要使用==
、!=
。
- with语句
with语句在这门语言里存在,本身就严重应县了JavaScript处理器的速度,因为它组算了变量名的此法作用域绑定。
建议:
永远不要使用with语句。
- eval
eval减弱了你的应用程序的安全性,因为它给被求值的文本授予了太大的权利。它也降低了语言的性能。
建议:
-
避免使用eval。
-
Function的构造器是eval的另一种形式,也应该避免使用它。
-
浏览器提供的setTimeout和setInterval函数,它们能接受自渡船参数或者函数参数,当传递的是字符串参数时,setTimeout和setInterval函数会像eval那样去处理,所以应该避免使用字符串参数形式。
- 缺少块的语句
避免if
、while
、do
、for
这样的语句可以接受一个括在花括号中的代码块,也可以接受单行语句。单行语句虽然可以节约2个字节,但是它模糊了程序的结构,会给以后带来隐患,所以不建议使用。
- ++ --
++ --会使得程序变得拥挤、复杂和隐晦,所以不建议使用。
JavaScript中只有双精度浮点整数。
- 位运算符
位运算符接近硬件处理,所以非常快,但是JavaScript的执行环境一般接触不到硬件,所以非常慢,JavaScript不建议呗用来执行未操作。
写在后面
GitHub上集大家之力搞了一个前端面试题的项目,里面都是大家面试时所遇到的题以及一些学习资料,有兴趣的话可以关注一下。如果你也有兴趣加入我们的话,请在项目中留言。项目同时也可以在gitbook上查看。