1、带有 src 属性的<script>元素不应该在其<script>和</script>标签之间再包含额外的 JavaScript 代码。如果包含了嵌入的代码,则只会下载并执行外部脚本文件,嵌入的代码会被忽略。一般都把全部 JavaScript 引用放在<body>元素中页面内容的后面。

2、循环引用:对象 A 中包含一个指向对象 B 的指针,而对象 B 中也包含一个指向对象 A 的引用:

var element = document.getElementById("some_element");
var myObject = new Object();
myObject.element = element;
element.someObject = myObject;

IE8及以前版本中有一部分对象并不是原生 JavaScript 对象,而是使用 C++以 COM(Component Object Model,组件对象模型)对象的形式实现的的,而 COM 对象的垃圾收集机制由于采用了引用计数策略,所以会有循环引用的问题,而循环引用会导致即使将例子中的 DOM 从页面中移除,它也永远不会被回收,因此会导致内存泄露。所以一旦数据不再有用,最好通过将其值设置为 null 来释放其引用:

myObject.element = null;
element.someObject = null;

3、未初始化的变量会自动被赋予 undefined 值,但显式地初始化变量依然是明智的选择,当 typeof 操作符返回"undefined"值时,我们就知道被检测的变量还没有被声明,而不是尚未初始化。

4、创建对象推荐组合使用构造函数模式和原型模式:

function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true

组合使用构造函数模式和原型模式中构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。

其他模式的缺点:

工厂模式:虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型);

构造函数模式:每个方法都要在每个实例上重新创建一遍;

原型模式:原型中所有属性是被很多实例共享的,这种共享对于函数非常合适,然而对于包含引用类型值的属性来说问题比较大。

5、JavaScript中的继承可以使用组合继承(也叫伪经典继承):

function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
//继承属性
SuperType.call(this, name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //

组合继承使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承,从而避免了原型链和借用构造函数的缺陷。但是组合继承也有不足,即无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候(new SuperType()),另一次是在子类型构造函数内部(SuperType.call(this, name)),寄生组合式继承克服了这个缺点,基本模式如下:

function object(o){
function F(){}
F.prototype = o;
return new F();
} function inheritPrototype(subType, superType){
var prototype = object(superType.prototype); //创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
}

所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。我们就可以用调用 inheritPrototype()函数的语句,去替换前面例子中为子类型原型赋值的语句,例如:

function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
alert(this.age);
};

6、由于耦合的问题,在编写递归调用时,使用 arguments.callee 总比使用函数名更保险:

function factorial(num){
if (num <= 1){
return 1;
} else {
return num * arguments.callee(num-1); //不要使用return num * factorial(num-1);
}
}

7、由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过度使用闭包可能会导致内存占用过多。
8、由于 JavaScript 没有块级作用域,因此可以使用匿名函数来模仿块级作用域:

(function(){
//这里是块级作用域
})();

这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。这种技术也经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。

9、尽量不要使用间歇调用,因为在不加干涉的情况下,间歇调用将会一直执行到页面卸载,而且后一个间歇调用可能会在前一个间歇调用结束之前启动,最好使用超时调用来模拟间歇调用,对比如下两段代码:

间歇调用:
var num = 0;
var max = 10;
var intervalId = null;
function incrementNumber() {
num++;
//如果执行次数达到了 max 设定的值,则取消后续尚未执行的调用
if (num == max) {
clearInterval(intervalId);
alert("Done");
}
}
intervalId = setInterval(incrementNumber, 500);
超时调用模拟间歇调用:
var num = 0;
var max = 10;
function incrementNumber() {
num++;
//如果执行次数未达到 max 设定的值,则设置另一次超时调用
if (num < max) {
setTimeout(incrementNumber, 500);
} else {
alert("Done");
}
}
setTimeout(incrementNumber, 500);

10、为了确保跨浏览器兼容,最好还是将 nodeType 属性与数字值进行比较,因为IE无法访问 Node 类型。

11、使用cloneNode()方法时在复制之前最好先移除事件处理程序,因为IE 在此存在一个 bug,它会复制事件处理程序。

12、尽量减少访问 NodeList 的次数。因为每次访问 NodeList,都会运行一次基于文档的查询。

13、由于老版本的浏览器不支持,因此在有特殊需要时再使用事件捕获,可以放心地使用事件冒泡。

14、因为HTML 与 JavaScript 代码紧密耦合,因此不要使用 HTML 事件处理程序,可以使用 JavaScript 指定事件处理程序。

15、使用事件委托,在DOM 树中尽量最高的层次上添加一个事件处理程序,不必给每个可单击的元素分别添加事件处理程序,因为事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。最适合采用事件委托技术的事件包括 click、mousedown、mouseup、keydown、keyup 和 keypress。

16、调用 submit()方法的形式提交表单时,不会触发 submit 事件,因此要记得在调用此方法之前先验证表单数据。与调用 submit()方法不同,调用 reset()方法会像单击重置按钮一样触发 reset 事件。

17、读取或设置文本框的值时不建议使用标准的 DOM 方法,而是使用 value 属性:

var textbox = document.forms[0].elements["textbox1"];
textbox.value = "Some new value";

换句话说,不要使用 setAttribute()设置<input>元素的 value 特性,也不要去修改<textarea>元素的第一个子节点。原因很简单:对 value 属性所作的修改,不一定会反映在 DOM 中。因此,在处理文本框的值时,最好不要使用 DOM 方法。

18、不建议使用常规的 DOM 功能来访问 option 元素的数据,因为效率比较低,最好是使用特定于选项的属性,因为所有浏览器都支持这些属性:

var selectbox = document.forms[0].elements["location"];
//不推荐
var text = selectbox.options[0].firstChild.nodeValue; //选项的文本
var value = selectbox.options[0].getAttribute("value"); //选项的值 //推荐
var text = selectbox.options[0].text; //选项的文本
var value = selectbox.options[0].value; //选项的值

JavaScript 基础优化(读书笔记)的更多相关文章

  1. SQL Server2012 T-SQL基础教程--读书笔记(5-7章)

    SQL Server2012 T-SQL基础教程--读书笔记(5-7章) SqlServer T-SQL 示例数据库:点我 Chapter 05 表表达式 5.1 派生表 5.1.1 分配列别名 5. ...

  2. SQL Server2012 T-SQL基础教程--读书笔记(1-4章)

    SQL Server2012 T-SQL基础教程--读书笔记(1-4章) SqlServer T-SQL 示例数据库:点我 Chapter 01 T-SQL 查询和编程背景 1.3 创建表和定义数据的 ...

  3. SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)

    SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1 ...

  4. JavaScript 函数式编程读书笔记1

    概述 这是我读<javascript函数式编程>的读书笔记,供以后开发时参考,相信对其他人也有用. 说明:虽然本书是基于underscore.js库写的,但是其中的理念和思考方式都讲的很好 ...

  5. Web开发基础(读书笔记)

    读书笔记:简单+基础 HTML(hyper Text Markup Language,超文本标记语言) URL(Uniform Resource Locator,统一资源定位器)构成3部分:协议/主机 ...

  6. JavaScript 函数式编程读书笔记2

    概述 这是我读<javascript函数式编程>的读书笔记,供以后开发时参考,相信对其他人也有用. 说明:虽然本书是基于underscore.js库写的,但是其中的理念和思考方式都讲的很好 ...

  7. javascript高级程序设计读书笔记-事件(一)

    读书笔记,写的很乱   事件处理程序   事件处理程序分为三种: 1.html事件2. DOM0级,3,DOM2级别  没有DOM1 同样的事件 DOM0会顶掉html事件   因为他们都是属性  而 ...

  8. 《JavaScript 模式》读书笔记(1)— 简介

    哇,看了自己最近的一篇文章,其实那时候刚接触Jest,啥也不会(虽然现在其实也一样不会,嘿嘿),就像记录下工作中遇到的一些问题,其实,后来的一些发现吧,那两篇文章写的其实是有一些问题的.希望不会给大家 ...

  9. 关于js对象的基础使用方法-《javascript设计模式》读书笔记

    一.利用对象收编变量 当我们决定实现某一项功能的时候最简单的其实就是写一个命名函数,然后调用来实现,就像这样: function checkName(){ //验证姓名 } function chec ...

随机推荐

  1. 配置用户范围settings.xml

    Maven用户可以选择配置<<MavenHome>>/conf/settings.xml或者<<UserHome>>/.m2/settings.xml. ...

  2. hadoop部署、启动全套过程

    Hadoop是Apache基金会的开源项目,为开发者提供了一个分布式系统的基础架构,用户可以在不了解分布式系统的底层细节的情况下开发分布式的应用,充分利用集群的强大功能,实现高速运算和存储.Hadoo ...

  3. iOS进阶面试题----经典10道

    OneV‘s Den在博客里出了10道iOS面试题,用他的话是:"列出了十个应聘Leader级别的高级Cocoa/CocoaTouch开发工程师所应该掌握和理解的技术" .  在这 ...

  4. 快速安装多系统(xp与win7)

    具体方法: 1.利用pe安装xp系统 2.xp下,空出一个分区,用于安装win7 3.进入pe下,安装win7系统到空出的分区 4.win7正常启动后,会覆盖原来xp的启动方式 5.再次进入pe,利用 ...

  5. JS - 图片放大器

    下载地址:http://www.lanrentuku.com/js/tupian-1170.html

  6. PHP之操作数据库

    数据库,顾名思义,是一个存放数据的容器.然后在使用过程中对数据库里面的数据增删改查,具体是怎么实现的呢? 这儿不得不提一下一个神奇的东西:SQL语句:结构化查询语言(Structured Query ...

  7. Citrix 服务器虚拟化之三十二 XenConvert

    Citrix 服务器虚拟化之三十二  XenConvert 简介: Citrix XenConvert 是用于实现物理到虚拟(P2V)转换的工具,可将工作负载从运行 Windows 的服务器或桌面计算 ...

  8. 14.9.4 COMPACT and REDUNDANT Row Formats

    14.9.4 COMPACT and REDUNDANT Row Formats InnoDB 早期的版本 使用一种未命名的文件格式(现在称为Antelope(羚羊)) 对于数据库文件 在这种文件格式 ...

  9. MFC界面相关(彩色工具栏)

    MFC工具栏控件 创建工具栏步骤: (1)在Resource View中插入新toolbar (2)在toolbar上双击增加按钮,更改ID为ID_BUTTON,编译后在resource.h中即可看到 ...

  10. 请问,如何在windows系统下面同时使用中文和英文的cmd?_百度知道

    请问,如何在windows系统下面同时使用中文和英文的cmd?_百度知道 在批处理开始加一行chcp 437就是英文的cmdchcp 936就是中文的cmd