本人JS新手,最近项目很多复用的函数,不知道如何处理,只是简单的写成了函数,放在一个JS文件里面,但这样肯定有问题,比如函数重名。
看了一下网上的封装方式,感觉花样太多,不知道有什么常用通用的处理方式呢?我主要就是封装常用函数,比如数组处理、时间处理这种。
网上看了主要是两种方式(或者这根本是两个不同东西 -。-,大概这个意思吧):
1.创建js库,大多采用以下模版
<span style="font-family:FangSong_GB2312;">//JavaScript库模板代码
(function (){
function $(){
alert("被调用到喽!");
/*alert()是JavaScript脚本语言中窗口window对象的一个常用方法;
其主要用法就是在你自己定义了一定的函数以后,通过执行相应的操作,
所弹出对话框的语言。并且alert对话框通常用于一些对用户的提示信息。*/
}
//注册命名空间 'myNameSpace' 到window对象上
window['myNameSpace'] = {}
//把$函数注册到 'myNameSpace'命名空间中
window['myNameSpace']['$']=$;
})();
</span>
看起来有点复杂,另外,搞不懂为什么非要放在span里面,这喵的不是js嘛。
2.js面向对象的封装
采用对象的方式,使用时实例化对象即可。
搜了半天,没看到什么通用的解决办法,方式太多不知道怎样处理比较合理呢。
个人给一点建议不要再搞什么命名空间了。已经进入 2016 年啦,JavaScript 现在的模块化机制已经相当成熟,学习一下如何用 ES2015 Module 来封装模块,实际用的时候可以考虑各种模块转换编译器/加载器,浏览器的兼容性不会是问题。比如说 babel/webpack/jspm 等等都可以……这样吧,我简单帮你梳理一下:
首先学会怎么用 ES2015 来编写/封装模块(node/npm,加上 babel 的入门知识)
学会发布它,比如说发布到 npm
学会如何引入模块到你的应用体系中去,如何加载/打包(用上 gulp/webpack/jspm 等等,取决于项目)
这是一个完整的生态系统,封装不只是要学习代码怎么写,更要知道如何维护,如何应用,否则封装的没有普适性就没有价值。
至于具体到新的模块语法怎么写,我这里有之前回答别人(不在 SF)的一部分内容供你参考——别想太复杂,可以很简单的:
我不喜欢用
Class
,不管是过去的构造器模式还是现在的新语法。不是因为对任何编程范式有偏见,本来 JavaScript 就不是 Class Based OO 语言,硬生生的去模仿就是会觉得别扭罢了。和 Java、C# 等语言不同,class
不是必需品,这也就意味着你完全可以不用。然而奇怪的是使用 JavaScript 的人很多却是不用class
不行,这是不是对这门语言存在很大的误解呢?更重要的是在实践中我们会发现使用其他的模式——比如工厂函数(Factory Functions)要远比
class
简洁、灵活,用它来替代class
几乎总能得到更好的结果。简单工厂函数
用起来和一个 Class 几乎一模一样——除了不需要用
new
,这不算坏处吧?依赖注入
console.log
限制了greet
方法的行为,为了不局限问候的方式,可以使用依赖注入——这是解耦的一种简便易行的方法。即使在现实中很多时候看不出需要依赖注入的迹象,我们也应该有意识的这么做。在定义一种“类型”的时候对外界知道的越少越好(于是就更容易复用、扩展、组合……)。比如说我们可以把
console
封装一下,让系统内所有的ioStream
都具有统一的接口,然后就可以直接使用:不用 Mocking 的单元测试
这个是顺带一提的事情,因为我注意到不懂得处理依赖注入(或者说更高层次上的解耦概念)的人通常都会把单元测试写得无比蛋疼……实际上,对象字面量在很多时候胜过一切构造模式:
封装
其实私有成员可以变得很自然很自然,闭包一样在用,只是不那么扎眼了:
用法就不写了,和之前没什么区别。getter/setter 也不是必须的,看接口设计需求了。
组合
这才是对 OO 来说最重要的(相较于怎么定义/创建对象来说),总的来说组合总是要优于继承,工厂模式搞起来尤其轻松。
比方说我们已经有了一个动作“类”:
那么与
Person
的组合可以这样:事前绑定的方法引用
这是我觉得最好的一个优点。由于
this
在 JavaScript 中是在运行时动态绑定的,如果使用你代码的人不理解这一点,那么他们就会犯错误(而且会指责是你写的不对……)。有些人是因为不理解this
而不敢用,有些人则是为了迁就前者而干脆不去用,架构师会比较容易体会这类情况。这是典型的容易犯错的例子:
容易犯错的地方就是最后一行,如果不加
.bind(stepper)
的话最终this
的指向就是错误的。但往往使用者并不理解这一点,反正看到你的文档就知道这个能加上初始化传入的offset
就是了,除非你不厌其烦的在文档里强调:“注意上下文的变化,如有必要请用bind()
明确this
的指向“……啊,说不定你还得培训一下让大家都知道如有“必要”的确切范围。然而你也可以这样来重写一下:
于是无论是具体实现还是接口定义都能保持简洁一致。