ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
我正式读过源码的经典框架有4个,我自己的感觉就是——**解读源码之后,真正留在自己脑子里面的,是这个框架的设计思想**。当跟我看完zepto-core的源码之后,你应该会有这种体会。 <br> ## 诡异的数组 那么接下来,先通过最简单的一个例子看一眼zepto的设计。先来一个很简单的html页面,`<body>`中的代码如下: ```html <p id="p1">测试</p> <div> <span>test</span> <span>test</span> <span>test</span> </div> <script type="text/javascript" src="js/zepto-1.1.6.js"></script> ``` 运行页面,然后在chrome的控制台中输入代码做测试。 ```js var $p = $('p'); // $p 是数组 var $span = $('span'); // $span 是数组 ``` 以上代码中,`$p`和`$span`看起来都是数组,这没有问题。但是我们通过API知道,`$p.addClass`是一个函数,而一般的数组没有`addClass`这个函数。 如果都是一样的数组,那么`$p.addClass`是哪里来的呢?显然`$p`不是一个常规的数组。其实我们还有其他方法可以证明 ```js var arr = [1,2,3]; var $p = $('p'); // 对比1 arr.__proto__.constructor === Array; // true $p.__proto__.constructor === Array; // false // 对比2 arr instanceof Array; // true $p instanceof Array; // false ``` 种种迹象表明,`$p`是一个看似数组,而非数组的东西。像《聊斋》里的画皮,是否很诡异。。。 <br> ## 先扒一层皮 如果你对js语法不是很熟练,估计刚才就被这位『画皮』吓蒙了。不过别着急,如果它是画皮,我就是一个称职的老道士。现在先拿一张道符把它点破,然后下一节再教你一招桌妖大法,让你彻底把它打败。 ```js var arr = [1,2,3]; console.log(arr.__proto__); // 输入一个对象 ``` 如上代码,`arr.__proto__`输出了一个对象,对象里面包含了我们常用的操作数组的函数,例如`concat`,`push`,`map`等,**先不要管这个`__proto__`是什么意思**。就是因为这个`__proto__`有了这些函数,`arr`才能使用。 ![](https://box.kancloud.cn/2016-07-04_577a764b28657.png) js语法非常灵活(号称最大的底线就是无底线),对象是可以随便赋值的,那么我就可以将`__proto__`重新赋值,让数组具有其他函数的功能啊,例如加一个`addClass`函数。 ```js var arr = [1,2,3]; arr.__proto__ = { addClass: function () { console.log(123); } }; arr.addClass(); // 123 ``` 注意,经过这一步,`arr.concat`等其他功能就没有,此时`arr`就只有`addClass`这一个函数相依为命了。 ![](https://box.kancloud.cn/2016-07-04_577a764cbc605.png) 但是无论如何,此时我们再去拿`arr`来做第一次的那几个验证,得到的结果就和之前的`$p`一样了,即`arr`此时也称了一个不是数组的数组。 而zepto也就是这么干的。