发现了2004年出版的一本好书,用两天快速刷了一遍,草草整理了一下笔记,在此备忘。
类:对象的设计蓝图或制作配方。
对象 === 实例 :老鹰是鸟类的一个实例
基于相同的类创建出许多不同的对象,类更多的是一种模板,而对象就是在这些模板的基础上被创建出来的。
------------------
【类】
JavaScript没有类,一切都基于对象。
依靠的是一套原型系统。
传统: 我基于Person类创建了一个叫做Bob的新对象。(?-> 月饼模子 -> 月饼)
JS中: 我将现有的Person对象扩展成了一个叫做Bob的新对象。(月饼 -> 五仁月饼)
【封装】
主要用于阐述对象中所包含(或封装)的内容 {
1. 相关的数据(用于存储属性)
2. 基于这些数据所能做的事(所能调用的方法)
}
只需要知道所操作对象的接口,并不必关心他的具体实现。
限定方法和属性的可见性。JS中,所有的方法和属性都是public的。
【聚合】
将几个现有的对象合并成一个新对象的过程。
【继承】
通过继承的方式,可以非常优雅地实现对现有代码的重用。
传统:类与类之间的关系。
JS中:对象与对象之间。当一个对象继承自另一个对象时,通常会往其中加入新的方法,以拓展被集成的老对象。&& 覆写。
【多态】
不同对象通过相同的方法调用来实现各自行为的能力。
【函数】
作为函数,本质上是一种代码的分组形式。
我们可以通过这种形式赋予某组代码一个名字,便于日后重用时调用。
函数的组成部分:
1. function子句
2. 函数名称
3. 函数所需的参数
4. 函数要执行的代码块
5. return子句 函数通常都会有返回值,如果某个函数没有显式的返回值,我们就会默认他的返回值undefined
JavaScript中的函数是一种数据,这种特殊的数据类型有两个重要的特性 {
1. 他们所包含的是代码
2. 他们是可执行的(或者说是可调用的)
}
函数的用法: {
1. 将匿名函数作为参数传递给其他函数 -> 【回调函数】 {
(1)可以让我们在不做命名的情况下传递函数(可以节省全局变量)
(2)可以将一个函数调用操作委托给另一个函数(节省代码编写工作)
(3)有助于提升性能
}
2. 定义某个匿名函数来执行某些一次性任务 -> 【自调用函数】
3. 【内部(私有)函数】 {
(1)有助于我们确保全局命名空间的纯净性
(2)私有性,选择只将一些必要的函数暴露给“外部世界”,并保留属于自己的函数,使他们不为该应用程序的其他部分所用。
}
4. 【返回函数的函数】
5. 【能重写自己的函数】 a = a(); 一次性函数
6. 【闭包】{
(1) 作用域链 函数内定义的变量在函数外是不可见的。
(2) 词法作用域 每个函数在被定义时(而非执行时)都会创建一个属于自己的环境(即作用域),函数只能访问自身作用域与全局作用域的内容。函数并不关心其作用域中的变量如何变化,只关心最后变量的值。 -> 我们可以通过添加/删除操作来实现变量的重复添加,并且完全不会影响程序的运行。【函数所绑定的是作用域本身,而不是该作用域中的变量或变量当前所返回的值】
(3) 何时创建闭包:如果一个函数需要在其父级函数返回之后留住对父级作用域的链接的话,就必须要为此建立一个闭包。
7.arguments对象(类数组的对象) -> calllee属性 :引用当前被调用的函数对象 -> 实现匿名函数的递归调用:
(function(count) {
if (count < 5) {
alert(count);
arguments.callee(++count);
}
})(1);
}
【对象】
(1) 数组 {
a. 枚举型数组
b. 关联性数组(哈希表)
}
(2) 对象 {
a. this指针 引用“这个对象”或“当前对象”
b. 构造器函数创建对象 -> 创建对象时接受一些参数
c. 当创建对象时,实际上同时也赋予了该对象一种特殊的属性 - 构造器属性 constructor 该属性实际上是一个指向用于创建该对象的构造器函数的引用(是一个函数,所以可以调用)
当对象是通过文本标识法创建的,那么实际上他就是由內建构造器Object()函数所创建的。 -> 通过instanceof操作符,可以测试一个对象是不是由某个指定的构造器函数所创建的。
}
(3) 内建对象 {
a. 数据封装类对象 -- Object Array Boolean Number 和 String
b. 工具类对象 -- Math Date RegExp
c. 错误类对象 -- Error
}
(4) 空对象 -> 包含一些方法和属性 {
a. 返回构造器函数的构造器属性
b. 返回对象描述字符串的toString()方法
c. 返回对象单只描述信息的valueOf()方法
}
(5) 每个函数的prototype属性中都包含了一个对象,他只有在该函数是构造器时才会发挥作用,该函数创建的所有对象都会持有一个该prototype属性的引用,并可以将其当做自身的属性来使用。
}
【原型】
函数本身也是一个包含了方法和属性的对象。
每个[函数]中都有一个prototype属性,该属性所存储的就是原型对象。
对于原性来说,最重要的是我们要理解它的“live”概念。由于在JavaScript中,对象都是通过传引用的方式来传递的,因此我们所创建的每个新对象实体中并没有一份属于自己的原型副本。这就意味着->我们可以随时修改原型,并且与之相关的对象也都会继承这一改变(甚至可能会影响在修改之前都已经创建了的对象)。
[对象]中存在一个指向相关原型的链接 -> 在Firefox中被叫做 _proto_ 属性
一些原型陷阱:
(1)当我们对原型对象执行完全替换时,可能会触发原型链中某种异常
(2)prototype.constructor属性是不可靠的 -> 当我们重写某对象的prototype时,重置相应的constructor属性是一个好习惯
会存在构造器丢失的问题。
【继承】
对于继承来说,主要目标就是将一些现有的功能归为己有。也就是说,我们在新建一个对象时,通常首先应该继承于现有的对象,然后再为其添加额外的方法和属性。
处于效率考虑,我们应该尽可能的将一些可重用的属性和方法添加到原型中去。但是 {
1. 不要单独为继承关系创建新对象
2. 尽量减少运行时方法搜索,例如toString()
如果所有属性都指向了一个相同的对象,父对象就会受到子对象属性的影响。 -> 利用一个临时构造器函数充当中介
将集成部分封装成函数
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
child.prototype.constructor = Child;
child.uber = Parent.prototype;
}
}
属性拷贝
function extend2(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
}
【编程模式与设计模式】
模式:专门为某些常见问题开发的、优秀的解决方案。
编程模式:一些专门为JavaScript语言开发出的最佳实践方案
设计模式:与具体语言无关,主要来自《设计模式》一书
【编程模式】:
行为隔离
命名空间 尽量减少使用全局变量的机会 -> 将变量和方法定义在不同的命名空间中 -> 实质是只定义一个全局变量,并将其他变量和方法定义为该变量的属性
初始化分支
延迟定义
配置对象 适用于很多歌参数的函数或方法 -> 当一个函数的参数多余三个时,可以用对象来代替多个参数 {
1. 不用考虑参数的顺序
2. 可以跳过某些参数的设置
3. 函数的拓展性更强,可以适应将来拓展需要
4. 代码可读性更好,因为代码中我们看到的是配置对象的属性名称
}
私有变量和方法
特权方法
私有函数的共有化
自治性的方法
链式调用
JSON
【设计模式】:
创建型模式:涉及对象的创建与初始化。
结构型模式: 描述了如何组合对象以提供新的功能。
行为型模式: 描述了对象之间如何通信。
“提到模式,我们更关注的是他们接口之间的关系,而不是内部实现细节。”
【单件模式】
创建型的设计模式,主要考虑的是创建对象的方式。当我们需要创建一种类型或一个类的唯一对象时,就可以使用该模式。
由于JavaScript本身没有类的概念,所有单件成为了默认行为,也是最自然的模式。每个对象都是一个单件。如果我们不对他进行拷贝,也不把它作为另一个对象的原型,那么它的类型将不会改变。
最基本的单件模式是现实适用对象文本标识法: var single ={};
【工厂模式】
属于用来创建对象的创建型模式。当我们有多个相似的对象而又不知道应该先使用哪种时,就可以考虑使用工厂模式。在该模式下,代码将会根据具体的输入或其他的既定规则,自行决定创建哪种类型的对象。
MYAPP.dom.factory = function(type) {
return new MYAPP.dom[type];
}
MYAPP.prototype.dom.Text = function() {...};
MYAPP.prototype.dom.Link = function() {...};
MYAPP.prototype.dom.Image = function() {...};
【装饰器模式】
是一种结构型模式,它与对象的创建无关。主要考虑的是如何拓展对象的功能。也就是说,除了使用线性式继承方式之外,我们也可以为一个基础对象创建若干个装饰对象以拓展其功能。然后,有我们的程序自行选择不同的装饰器,并按不同的顺序使用它们。在不同的程序中我们可能会面临不同的需求,并从同样的装饰器集合中选择不同的子集。
【观察者模式】
是一种行为型模式,主要用于处理不同对象之间交互通信问题,观察者模式中通常会包含两类对象: {
1. 一个或多个发行上对象:当有重要的事情发生时,会通知订阅者。
2. 一个或多个订阅者对象:他们追随一个或多个发行商,监听他们的通知,并作出相应的反应。
}
通常来说,观察者模式可分为两类:推动和拉动。 {
1. 推送模式: 由发行商负责将消息通知给各个订阅者。
2. 拉动模式: 要求订阅者主动追踪发行商的状态变化。
}