第22章 高级技巧
1、高级函数
(1)安全的类型检测
在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串。每个类在内部都有一个[[Class]]属性,这个属性中就指定了上述字符串中的构造函数名。
基于这一思路来测试某个值是不是原生函数或正则表达式,如:
function isFunction(value){
return object.prototype.toString.call(value) == “[object Function”];
}
(2)作用域安全的构造函数
作用域安全的构造函数在进行任何更改前,首先确认this对象是正确类型的实例。如果不是,那么会创建新的实例并返回。如:
function Person(name, age, job){
if(this instanceof Person){
this.name = name;
this.age = age;
this.job = job;
}else{
return new Person(name, age, job);
}
}
var person1 = Person(“Niecholas”,29,”Software Engineer”);
alert(window.names); //””
alert(person1.name); //” Niecholas”
var person2 = Person(“Shelby”,34,” Ergonmist”);
alert(person2.name); //” Shelby”
(3)惰性载入函数
惰性载入载入表示函数执行的分支仅会发生一次。有两种实现惰性载入的方式,第一种就是在函数被调用时再处理函数。第二种是在声明函数时就指定适当的函数。
(4)函数绑定
函数绑定要创建一个函数,可以在特定的this环境中以指定参数调用另一个函数。
创建多个闭包可能会令代码变得难以理解和调试。因此,很多JavaScript库实现了一个可以将函数绑定到指定环境的函数。这个函数一般都叫bind()。
(5)函数柯里化
用于创建已经设置好了一个或多个参数的函数。函数柯里化的基本方法和函数绑定是一样的:使用一个闭包返回一个函数。
柯里化函数通常由以下步骤动态创建;调用另一个函数并为它传入要柯里化的函数和必要参数。
函数柯里化还常常作为函数绑定的一部分包含在其中,构造出更为复杂的bind()函数。
2、防篡改对象
一旦把对象定义为防篡改,就无法撤销了。
(1)不可扩展对象
默认情况下,所有对象都是可以扩展的。
使用object.preventExtensions()方法可以改变这个行为,让你不能再给对象添加属性和方法。
虽然不能给对象添加新成员,但已有的成员则丝毫不受影响。你仍然还可以修改和删除已有的成员。另外,是一个object.istExtensible()方法还可以确定对象是否可以扩展。
(2)密封的对象
密封对象不可扩展。而且已有成员的[[Configurable]]特性将被设置为false。这意味着不能删除属性和方法。属性值是可以修改的。
使用object.isSealed()方法可以确定对象是否被密封了。
(3)冻结的对象
最严格的防篡改级别是冻结对象。冻结的对象既不可扩展,又是密封的,而且对象数据属性的[[Writable]]特性会被设置为false。
与密封与不允许扩展一样,对冻结的对象执行非法操作在非严格模式下会被忽略,而在严格模式下会抛出错误。
也有一个object.isFrozen()方法用于检测冻结对象。
3、高级定时器
关于定时器要记住的最重要的事情是,指定的时间间隔表示任何将定时器的代码添加到队列,而不是何时实际执行代码。
(1)重复的定时器
(2)Yeilding Processes
(3)函数节流
函数流背后的基本思想是指,某些代码不可以在没有间断的情况连续重复执行。
第一次调用函数创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。
第24章 最佳实践
1、可维护性
(1)代码约定
一种让代码变得可维护的简单途径是形成一套JavaScript代码的书写约定。
- 可读性
可读性的大部分内容都是和代码的缩进相关的。
可读性的另一方面是注释。
- 适当给变量和函数起名字对于增加代码可理解和可维护性是非常重要的。
- 变量类型透明
有3种表示变量数据类型的方式:
第一种方式是初始化。
缺点是它无法用于函数声明中的函数参数。
第二种方法是使用匈牙利标记法来指定变量类型。
JavaScript中最传统的匈牙利标记法是用单个字符表示类型:“o”代表对象,“s”代表字符串,“i”代表整数,“f”代表浮点数,“b”代表布尔型。
好处是函数参数一样可以使用;缺点是让代码某种程度上难以阅读,阻碍了没有用它时代码的直观性和句子式的特质。
最后一种指定变量类型的方式是使用类型注释。
缺点是你不能用多行注释一次注释大块的代码。
(2)松散耦合
HTML呈现应该尽可能与JavaScript保持分离。当JavaScript用于插入数据时,尽量不要直接插入标记。
显示问题的唯一来源应该是CSS,行为问题的唯一来源应该是JavaScript。在这些层次之间保持松散耦合可以让你的整个应用更加容易维护。
将应用逻辑和事件处理程序相分离。
(3)编程实践
避免全局量、避免与null进行比较、
2、性能
(1)注意作用域
访问全局变量总是要比访问局部变量慢。
- 避免全局查找
- 避免with语句。with语句会创建自己的作用域,因此会增加其中执行的代码的作用域的长度,因此会增加其中执行的代码的作用域链的长度。
(2)最小化语句数
创建很多语句时,变量声明只用一个var语句,之间由逗号隔开。
当使用迭代值(也就是在不同的位置进行增加或减少的值)的时候,尽可能合并语句。如:
var name = values[i];
i++;
组合为如下一个语句:
var name = values[i++];
只要有可能,尽量使用数组和对象的字面量表达式来消除不必要的语句。
(3)优化DOM交互
有两种在页面上创建DOM节点的方法:使用诸如createElement()和appendChild()之类的DOM方法,以及使用innerHTML。对于大的DOM修改,使用innerHTML要比使用标准DOM方法创建同样的DOM结构快的多。
大多数Web应用在用户交互上大量用到事件处理程序,最好使用事件代理。
任何时候要访问HTMLCollection,不管它是一个属性还是一个方法,都是在文档上进行一个查询,这个查询开销很昂贵。最小化访问HTMLCollection的次数可以极大地改进脚本的性能。
3、部署
你写的代码不应该原封不动地放入浏览器中,最好给JavaScript文件定义一个构建过程。
因为JavaScript并非编译为字节编码,而是按照源代码传送的,代码文件通常包含浏览器执行需要的额外的信息和格式。不过,我们可以使用压缩工具减少文件的大小。
第25章 新兴的API
1、request AnimationFrame()
在JavaScript中创建动画的典型方式,就是使用setInterval()方法来控制所有动画。
Firefox 4 最早为JavaScript动画添加了一个新API,即mozRequestAnimationFrame()。这个方法会告诉浏览器:有一个动画开始了。
基于mozRequestAnimationFrame(),Chrome和IE10+也都给出了自己的实现,分别叫webRequestAnimationFrame()和msRequestAnimationFrame()。
2、Page Visibility API
如果页面最小化了或者隐藏在了其他标签页后面,那么有些功能是可以停下来的。而Page Visibility API(页面可见性API)就是为了让开发人员知道页面是否对用户课件而推出的。
3、Geolocation API
地理定位是最令人兴奋,而且得到了广泛支持的一个新API。
Geolocation API在浏览器中的实现是navigator.geolocation对象。
4、File API
File API(文件API)的宗旨是为Web开发人员提供一种安全的方式,以便在客户端访问用户计算机中的文件,并更好地对这些文件执行操作。
5、Web计时
Web Timing API是用来度量页面性能指标的方式之一。让开发人员通过JavaScript就能使用浏览器内部的度量结果,通过直接读取这些信息可以做任何想做的分析。
8、Web Workers
长时间运行的JavaScript进程会导致浏览器冻结用户界面。Web Workers规范通过让JavaScript在后台运行解决了这个问题。