原生JS IIFE构造带私有方法插件的原理疑问及DOM元素直调插件实现咨询
闭包式插件的运行逻辑解答
针对第一个疑问的澄清
- 你对
new的调用逻辑理解存在偏差:外层包裹的立即执行函数(IIFE)在JS脚本加载解析的瞬间就已经执行完成,它的唯一作用就是把内部定义的Constructor函数暴露出来,赋值给全局的myPlugin变量,整个过程完全不需要new触发。后续执行new myPlugin(...)时,本质是调用之前已经赋值好的Constructor函数;因为这个构造函数内部手动返回了publicAPIs对象,new会优先把这个对象作为最终的实例返回,不会使用默认创建的空对象。 - 你对实例内存逻辑的认知完全准确:当前写法下,不管是私有方法
myFunction,还是绑定在publicAPIs上的公共方法,都是每次执行构造函数时重新创建的,每个实例都会单独持有一整套方法副本,不会通过原型共享。这种写法不需要依赖class语法,也不需要兼容浏览器对私有字段的支持,就能实现真正的私有方法访问控制,单实例使用完全没有性能负担。
实现DOM元素直接调用插件的方案
完全可以实现,和jQuery插件的实现逻辑本质一致,核心是通过扩展原生DOM原型,把插件方法挂载到所有DOM元素的可用方法上。
具体修改示例
- 调整原构造函数的参数结构,使其支持接收DOM元素作为参数
- 在原IIFE内部给
Element.prototype挂载自定义的插件方法,该方法执行时的this就是当前触发调用的DOM元素 - 把当前DOM元素传入构造函数,生成插件实例返回
var myPlugin = (function () { 'use strict'; // 调整构造函数参数:接收DOM元素、用户配置 var Constructor = function (el, options) { var publicAPIs = {}; // 私有方法:可以直接访问绑定的DOM元素 function privateHandler() { console.log('当前绑定的DOM元素:', el); } // 公共方法 publicAPIs.myFunction2 = function () { privateHandler(); return 1; } return publicAPIs; }; // 给所有DOM元素的原型挂载插件方法 Element.prototype.myPlugin = function(options) { // this 就是当前调用方法的DOM元素,传入构造函数生成实例 return new Constructor(this, options); } // 保留原来的构造函数返回逻辑,不破坏原有调用方式 return Constructor; })();
修改完成后就可以实现你想要的调用效果:
var myElement = document.querySelector('#id'); // 直接在DOM元素上调用 var pluginInstance = myElement.myPlugin({ customConfig: 'test' }); pluginInstance.myFunction2();
注意事项
- 挂载到
Element.prototype的方法名要尽量特殊,避免和未来浏览器新增的原生DOM方法重名产生冲突 - 每个DOM元素调用插件时都会生成独立的闭包实例,不同元素绑定的插件状态完全隔离,不会互相干扰
内容的提问来源于stack exchange,提问作者Nite
相关产品推荐
相关产品推荐

