var T = function (selector) {
// 获取DOM元素
var dom = document.querySelector(selector);
// 添加类
dom.addClass = function (className) {
this.classList.add(className);
};
// 删除类
dom.removeClass = function (className) {
this.classList.remove(className)
};
return dom;
};
要解决的问题
上一节 #60 我们已经知道如何使用IIFE和闭包来处理模块化的问题。现在我们来尝试实现两个功能。
我们回想一下,jquery完成上面的功能大概是这样的。
我们分析一下。
工厂模式
ok,上最基础的工厂模式。
缺点
第一,返回的DOM元素无法知道它是从T这个构造函数中来的。 证据:
你可能会说,你这不废话吗!这里只用了工厂模式,压根没构造模式,哪儿来的构造函数! 没错,不过我们看看jquery
看见没?我们现在姑且可以认为jQuery那样做的好处在于起码我知道实例化的对象是从哪儿来的。
第二,每个dom实例的addClass和removeClass方法都会在内存中存一份,并不能共享,造成资源上的浪费。证明依据。
构造模式
我们先来尝试解决工厂模式的第一个缺点。
验证
发现第一个问题已经解决。我们来看第二个问题,函数复用问题。 我们把addClass和removeClass抽象成全局函数(注意,这里的全局是指自执行表达式里面的)
验证:
缺点
addClass和removeClass被声明为全局。虽然我们通过闭包将这种影响限制在模块内,但是这样子做也总感觉失去了对象的封装性。
原型模式
为了解决构造模式的全局函数声明问题,我们使用prototype来实现所谓的原型模式 shit.....忽然发现光用原型模式居然没法搞出一个demo来。比如一般的原型模式是这样的。
实际上这是会报错的
由此我们可以看到原型模式的一个重大缺陷:无法传递参数,也就是说每次构造出来的对象只能是一样的,这能忍? 当然,它还有另外一个重大缺陷,那就是传递引用。由于这里还不涉及到,就不说了。
混合模式
原型模式走不通,原因是因为不能传递参数。但是前面的构造函数可以传参啊,所以结合两者就是混合模式。
如何把new去掉?
目前我们已经做了很多了,但是还不够。比如,看下面的对比。
jquery实例化的时候是不需要new关键字的,而我们的T因为包含构造模式,所以得使用new。那么jquery是如何把new去掉的呢?(当然,new $('selector')也是可以执行的) 这里有一篇文章讲得很不错,http://www.cnblogs.com/aaronjs/p/3278578.html 下面我直接给出改造过后的代码