JavaScript 基础优化(读书笔记)
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 基础优化(读书笔记)的更多相关文章
- SQL Server2012 T-SQL基础教程--读书笔记(5-7章)
SQL Server2012 T-SQL基础教程--读书笔记(5-7章) SqlServer T-SQL 示例数据库:点我 Chapter 05 表表达式 5.1 派生表 5.1.1 分配列别名 5. ...
- SQL Server2012 T-SQL基础教程--读书笔记(1-4章)
SQL Server2012 T-SQL基础教程--读书笔记(1-4章) SqlServer T-SQL 示例数据库:点我 Chapter 01 T-SQL 查询和编程背景 1.3 创建表和定义数据的 ...
- SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)
SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1 ...
- JavaScript 函数式编程读书笔记1
概述 这是我读<javascript函数式编程>的读书笔记,供以后开发时参考,相信对其他人也有用. 说明:虽然本书是基于underscore.js库写的,但是其中的理念和思考方式都讲的很好 ...
- Web开发基础(读书笔记)
读书笔记:简单+基础 HTML(hyper Text Markup Language,超文本标记语言) URL(Uniform Resource Locator,统一资源定位器)构成3部分:协议/主机 ...
- JavaScript 函数式编程读书笔记2
概述 这是我读<javascript函数式编程>的读书笔记,供以后开发时参考,相信对其他人也有用. 说明:虽然本书是基于underscore.js库写的,但是其中的理念和思考方式都讲的很好 ...
- javascript高级程序设计读书笔记-事件(一)
读书笔记,写的很乱 事件处理程序 事件处理程序分为三种: 1.html事件2. DOM0级,3,DOM2级别 没有DOM1 同样的事件 DOM0会顶掉html事件 因为他们都是属性 而 ...
- 《JavaScript 模式》读书笔记(1)— 简介
哇,看了自己最近的一篇文章,其实那时候刚接触Jest,啥也不会(虽然现在其实也一样不会,嘿嘿),就像记录下工作中遇到的一些问题,其实,后来的一些发现吧,那两篇文章写的其实是有一些问题的.希望不会给大家 ...
- 关于js对象的基础使用方法-《javascript设计模式》读书笔记
一.利用对象收编变量 当我们决定实现某一项功能的时候最简单的其实就是写一个命名函数,然后调用来实现,就像这样: function checkName(){ //验证姓名 } function chec ...
随机推荐
- 基于visual Studio2013解决C语言竞赛题之1028平均值
题目 解决代码及点评 /* 已知有9个数,请求出这些数中的最大值.最小值及平均值,以及有多少个数等于平均值? */ #include<stdio.h> ...
- Research notes for Scientific Writing
Noun. complacency n. 自得;自鸣得意 nomenclature n. 专业术语:e.g. the nomenclature of music; 音乐的专门术语 Verb. abs ...
- Hadoop学习之HBase
1. HBase有哪些基本的特征? 2. HBase相对于关系数据库能解决的问题是什么? 3. HBase的数据模型是什么?如何表述?有哪些操作形式? 4. HBase的模式Schema设计的一些概念 ...
- Use GraceNote SDK in iOS(二)获取音乐的完整信息
在需求彻底明朗化,外加从MusicFans转到GraceNote,再从GraceNote的GNSDK转到iOS SDK后,最终完毕了在iOS上通过音乐的部分信息获取完整信息的功能了.(好吧,我承认是相 ...
- <转载>如果在浏览器网页标题栏左侧加自定义小图标
效果如下: 首先制作一个16*16像素的ico格式的图片,命名为:favicon.ico,然后在网站head标签直接加入: <link rel="icon" href=&qu ...
- 8天玩转并行开发——第三天 plinq的使用
原文 8天玩转并行开发——第三天 plinq的使用 相信在.net平台下,我们都玩过linq,是的,linq让我们的程序简洁优美,简直玩的是爱不释手,但是传统的linq只是串行代码,在并行的 年代如果 ...
- 基于visual Studio2013解决C语言竞赛题之1066进制转化
题目 解决代码及点评 /************************************************************************/ /* ...
- asp.net微软认证全新考试题库及答案1
1.你创建了一个ASP.net应用程序,该程序将运行在TK公司的WEB站点上.你的应用程序包括100个WEB页面.你想配置你的应用程序,当HTTP代码发生错误时,可显示自定义的错误信息给用户.同时你想 ...
- JavaScript常用全局属性与方法
最近,在学习JavaScript,Java作域链包含全局,记录下常用的全局属性与方法,就当是知识的积累,未列出全部,如需查看全部可参考JS相关的API文档. 常用的全局属性: 全局属性 作 ...
- UVA 565 565 Pizza Anyone? (深搜 +位运算)
Pizza Anyone? You are responsible for ordering a large pizza for you and your friends. Each of th ...