underscore.js源码解析之命名空间

1. 引言

  underscore.js是一个1500行左右的Javascript函数式工具库,里面提供了很多实用的、耦合度极低的函数,用来方便的操作Javascript中的数组、对象和函数,它支持函数式和面向对象链式的编程风格,还提供了一个精巧的模板引擎。理解underscore.js的源码和思想,不管是新手,还是工作了一段时间的人,都会上升一个巨大的台阶。虽然我不搞前端,但是在一个星期的阅读分析过程中,仍然受益匪浅,决定把一些自认为很有意义的部分记录下来。

2. 命名空间

  打开underscore.js,最先看到的就是下面这个结构:
  

(function() {
  var root = this;
  var previousUnderscore = root._;
  var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };
  root._ = _;//让外界引用当前作用域;把nodeJS省略了
  _.noConflict = function() {
    //将之前保存的window._还原
    root._ = previousUnderscore;
    return this; //将真正的 _ 返回
  };
}.call(this)); //this是window

整个匿名函数一定义就立刻执行,并且把此函数内部的执行上下文this指向window.
root._ = _;是将局部变量 _ 的引用交给window,这样就算整个匿名函数执行完了,其作用域也不会释放内存空间,因为当前作用域正被外部引用,这样就形成了一个天然的隐蔽空间,_ 是唯一暴露的接口,任何想要被外界访问的属性或函数都必须绑定在 _ 这个对象上,而一些内部辅助属性或函数可以非常安全的直接定义在这个空间里,外界无法访问。大多数JS库都是这么做的,这样可以将命名空间污染降到最低。

但是,_ 还是有可能在全局作用域中出现命名冲突,比如:

<script>
  var _ = 'myUnderscore';
</script>
<script src="underscore.js"></script><!-- 一导入就覆盖了 -->
<script>
  console.log(_);
</script>

或者

<script src="underscore.js"></script>
<script>
  var _ = 'myUnderscore';
  console.log(_);
<script>

都会发生冲突,所以underscore.js做了冲突处理,underscore.js一加载就将window中的 _ 属性值保存在preserveUnderscore这个变量中(window._ 存不存在无所谓),调用_.noConflict函数会将之前的preserveUnderscore还给window._,然后再把真正的 _ 返回,这时应该换一个变量名,用一个非 _ 的变量名来接收:

<script>
  var _ = 'myUnderscore';
</script>
<script src="underscore.js"></script>
<script>
  var __ = _.noConflict();
  console.log(_);//myUnderscore
  console.log(__);//从此__就是underscore,以后都用这个变量名调用underscore.js

同样这种解决命名冲突的方法在别的库中也有用到。

3. 构造函数

var _ = function(obj) {
  if (obj instanceof _) return obj;
  //如果用new关键字调用,则this指向新创建的实例;否则this指向window
  if (!(this instanceof _)) return new _(obj);
  this._wrapped = obj;
};

在上面的代码片段中,可以看到 new _(obj),说明 _ 本身就是个构造函数,underscore.js的所有对外函数都绑定在 _ 这个构造函数身上,使用时直接_.functionName() 来调用,同时还允许创建 _ 的实例,并且允许不用new关键字进行实例的创建,它会自行修正。它的实例包含一个属性_wrapped,目的是允许链式风格的调用。

4. 总结  

  1. 闭包在命名空间上的应用。
  2. 构造函数对非new调用方式的修正。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值