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 ...
随机推荐
- 《火球——UML大战需求分析》(第1章 大话UML)——1.5 小结和练习
说明: <火球——UML大战需求分析>是我撰写的一本关于需求分析及UML方面的书,我将会在CSDN上为大家分享前面几章的内容,总字数在几万以上,图片有数十张.欢迎你按文章的序号顺序阅读,谢 ...
- Python Challenge 第四题
这一题没有显示提示语,仅仅有一幅图片,图片也看不出什么名堂,于是直接查看源代码,源代码例如以下: <html> <head> <title>follow the c ...
- c# 未能载入文件或程序集
近期做项目时碰到这个问题了.goole.百度了半天,整理了下面几种可能: DLL文件名称与载入时的DLL文件名称不一致, DLL文件根本不存在,即出现丢失情况, 载入DLL路径错误,即DLL文件存在, ...
- EasyUI - DataGrid 组建 - [ 搜索功能 ]
效果: html代码: 使用css加载的方式,所以要在写html代码,也可以使用js操作. <div> <!--使用JS加载方式--> <table id="t ...
- PHP学习之-1.3 echo语句
echo语句 echo语句是PHP输出语句,可以把字符串输出(字符串用双引号扩起来). 如下代码 <?php echo "Hello World!"; ?> 注意ech ...
- post 请求参数
perl代码: my $login_url='http://192.168.1.1/getpage.gch?pid=1001&logout=1'; my $res = $ua->post ...
- Hadoop2.0/YARN深入浅出(Hadoop2.0、Spark、Storm和Tez)
随着云计算.大数据迅速发展,亟需用hadoop解决大数据量高并发访问的瓶颈.谷歌.淘宝.百度.京东等底层都应用hadoop.越来越多的企 业急需引入hadoop技术人才.由于掌握Hadoop技术的开发 ...
- HDU 4865 Peter's Hobby(2014 多校联合第一场 E)(概率dp)
题意:已知昨天天气与今天天气状况的概率关系(wePro),和今天天气状态和叶子湿度的概率关系(lePro)第一天为sunny 概率为 0.63,cloudy 概率 0.17,rainny 概率 0.2 ...
- Cocos2dx中Plugin-X 在android下的整合
直接拉plugin-x中的jar包导入到Eclipse中就可以.用这么麻烦的工具干嘛.
- 序列化TList of objects(摘自danieleteti的网站)
Some weeks ago a customer asked to me if it is possibile serialize a TList of objects. “Hey, you sho ...