Underscore 源码学习(一)

暑假打算研究一下 Underscore 源码,我会对一些我觉得比较有意思的点拿出来讨论下,不过我不会过多介绍,也不会去分析 Underscore 的各个方法,但我会附上一些相关的不错的参考资料。由于我也是初学阶段,所以如果有说的不正确的地方望指出。

要点1:立即执行函数

Underscore 的内容都用这么一个东西包装起来了。

1
(function(){..}());

其实也可以这样写

1
(function(){})();

Underscore 把全部内容封装在立即执行函数里面,就形成了一个独立的作用域,与外部隔离,并且这样做还形成了闭包,可以模拟私有方法。
推荐阅读:

要点2:兼容浏览器和 Node 环境

浏览器和服务端的一个主要区别是全局对象命名的不同,在浏览器全局变量是 window,在服务端即 Node 环境则是 global。

1
2
3
var root = typeof self == 'object' && self.self === self && self ||
typeof global == 'object' && global.global === global && global ||
this;

这个地方之前的写法是这样的

1
var root = this;

我认为之所以改成前面那种写法,可能是为了确保 root 指向 global 或者 window(self) 。大部分框架和库都采用这种做法,这种做法更加安全。

1
2
3
4
5
6
7
// 这一步确保self是一个object,这样self.self才不会出错
typeof self == 'object'
// 这一步确保self.self严格等于自身,貌似只有window具备这个特性
// 即window === window.window.window
self.self === self
// 为什么还要进行这一步?
self

推荐阅读:

要点3:提供命名冲突解决方法

Underscore 在给 root 赋值前,先保存了原先 root 的 _ 对象。之所以这样做,是因为可能我们用的其他库也使用了 _ 这个作为命名空间。

1
var previousUnderscore = root._;

我们结合 Underscore 最下面的这个方法来看。

1
2
3
4
_.noConflict = function() {
root._ = previousUnderscore;
return this;
};

如果 _ 出现了冲突,可以使用下面方法

1
var _new = _.noConflict();

这样一来应该很明显了,noConflictpreviousUnderscore 即原先的 root._ 重新放回去,然后重新定义 Underscore 命名给 _new,这样就解决了 _ 冲突问题。

阅读更多

ARP 攻击和无线网卡混杂模式

一次小小的 Hack 尝试…
前段时间换上了 Arch,就开始想这捣鼓一些黑科技。脑海中立即浮现出两个词, monitor 和 ARP 。

ARP 攻击

学过计算机网络了,大概了解ARP攻击这么一回事,但是当我真正去试的时候,才发现局域网原来真的这么脆弱,因为进行ARP攻击实在太容易了。实际上就是几条命令的事情。

主机发现和端口扫描

进行攻击第一步当然就是找目标了。可以使用 nmap 这个工具来进行,这东西简直渗透利器。

1
nmap -sP 192.168.1.0/24

这样就可以扫描192.168.1.0这个网段里面的所有主机了,以 ping 方式扫描,当然他有很多参数很多用法,网上很多这方面的资料我就不叙述了。
Nmap扫描

发起攻击

如果是进行ARP攻击,那也是加多三条命令就搞定的事情。

1
2
3
echo 1 >> /proc/sys/net/ipv4/ip_forward
arpspoof -i wlp3s0 -t 192.168.1.110 192.168.1.1
arpspoof -i wlp3s0 -t 192.168.1.1 192.168.1.110

第一条是开启转发,不然会受害者流量到我们这里出不去就断网了。
第二条是告诉受害者说我是网管。
第三条是告诉网管我是受害者。
这样就完成了 ARP 欺骗,图片以后再补。这之后对方的网络就完全在你的监控之下了。这告诉我们使用 https 和不连接免费 wifi 的重要性!

抓包

抓包推荐使用 wireshark 。具体就不介绍了=.=。你还可以使用 Driftnet 这东西来将对方访问的图片在你这边显示出来~

监听空气包

大部分无线网卡都可以设置 monitor 模式,即无线网卡默认接受下全部经过他的以太网帧而不丢弃,这种方式可以抓到附近范围里面的所以以太网帧。在 Arch 下也是三条命令搞定的事情。

1
2
3
ifconfig wlp3s0 down
iwconfig wlp3s0 mode monitor
ifconfig wlp3s0 up

接着同样开启 wireshark 抓包,你会发现很多802.11帧,不过这个并没有什么卵用,理论上应该对于没有加密的帧应该可以直接得到应用层报文才对,但是很奇怪我一直抓不到,即使是对于有加密的 Wifi,我填入 WAPKEY 解密也不行。这个有待继续研究。。。

阅读更多

从输入 URL 到页面展示

本文从网络层以上讨论从浏览器输入 HTTPS 协议的 URL 到页面展现的全过程。由于不同浏览器之间也存在差异,这里以 Chrome 浏览器为例。

1. DNS查询

DNS 缓存有好几个环节,浏览器缓存,系统缓存,路由器缓存,ISP 缓存。

  • 浏览器首先会查看自身是否已经有进行 DNS 缓存。Chrome 可以通过 chrome://net-internals/#dns 查看缓存的 DNS,浏览器的 DNS 缓存可以加快 DNS 解析速度,但缓存时间不会太长。

    Chrome 的 DNS 缓存
  • 如果浏览器没有相应的缓存,则查找系统缓存,浏览器会向系统发送一个查询请求,如果系统存在缓存或者设置了 host ,则返回相应的 ip 地址给浏览器。

  • 如果系统没有缓存,那么它会发出一个 DNS 查询请求给路由器。

    如果路由器有 DNS 缓存,他会提取出 IP 地址返回。否则,他会向本地域名服务器发出查询,从请求主机到本地域名服务器的请求一般是递归查询,而其他的查询一般是迭代查询。

    DNS 请求主机到本地域名服务器的查询 DNS 域名服务器之间的查询

    请求报文如下

    DNS 请求报文

    我们先简单分析下请求报文。

    1. DNS 使用 UDP 协议,端口号53。
    2. 在 DNS 报文的 Flags 中的 RD=1。表示它建议域名服务器以递归方式查询。
    3. Question section format 需要给出 QNAME, QTYPE, QCLASS。即查询的域名,查询的类型以及查询的类。

    有关DNS报文的更多信息可以参考RFC1035

    响应报文如下

    DNS 响应报文

    我们也简单分析下,如果想详细了解,可以查看上面的 RFC1035 标准。

    1. 与请求报文相比,对比 Flags 可以发现,QR=1 表示这是一个响应报文。RA=1 表示递归查询可用。
    2. ARecord 记录了DNS请求获得的一个或多个IP地址。一般还会得到 CNAME 记录和存活时间等信息。
    3. 这里对 Rcode 也稍加说明下,Rcode=0 表示成功,他还有好几种状态码,比如1表示 Format error,2表示 Server failure,3表示 Name error,4表示 Not lmplemented,5表示 Refused,具体信息可以参考 RFC1035

阅读更多

Angular 学习总结

这学期基本都是在学习和使用 Angular ,这篇文章主要是想介绍几个 Angular 需要注意或者了解的地方。

Angular作用域

​ 也许你知道 ng-if 和 ng-show 的区别是一个只有条件满足的时候才会创建 DOM ,一个是只有在条件满足的时候才会显示 DOM 也就是一开始也会跟着创建。但是你可能不知道, ng-if 会产生新的作用域, ng-repeat 和 ng-switch 和 ng-include 也是如此。这时候内部如果使用外部的变量,第一次的时候会正常显示,因为 Angular 的继承是原型链继承,如果子类没有这个属性就会去尝试继承父类的属性, Angular 会拿父类的属性来创建新的属于这个子类的属性,而这个属性将不再和外层的父类的属性挂钩,如果不注意很可能就会在这里踩坑。

读子类的属性时,子类有这个属性(hasOwnProperty)的时候则读子类自己的,子类没有的时候读父类的,不管子类有没有这个属性,在子类上都不会有新属性被创建。

写子类的属性时,如果子类有这个属性(hasOwnProperty)则写子类的,子类没有的话就会在子类上新建一个同名的新属性,而父类继承过来的属性被隐藏。

​ 关于原型链继承这个可以参考此处JavaScript Prototypal Inheritance,或者[译文] 深入浅出 AngularJS 作用域

​ 使用上述的 ng-if , ng-repeat , ng-switch , ng-include 都会自己创建一级作用域,这点一定要注意。如果想要和父类的属性挂钩,可以使用 $parent 。

​ 但是,还没玩,也许这些你都知道。但是除了这些指令之外, textarea 也会自己创建一级作用域。所以你可能会发现你在 textarea 写的内容获取不到,但是却发现 textarea 总能取到第一次分配的初值。比如

1
<textarea ng-model="content", name="content" class="form-control" row="3"></textarea>

​ 我们在控制器里面定义

1
$scope.content = "测试"

​ 然后我们就会看到 textarea 的初值为”测试”,但是当我们更改其中的内容之后, $scope.content 却一直保持不变。

​ 同样,我们可以使用 $parent 的方式来解决这个问题。

1
<textarea ng-model="$parent.content", name="content" class="form-control" row="3"></textarea>

​ 那如果不想使用 $parent 的话,可以给 content 分配一个类名,比如

1
<textarea ng-model="comment.content", name="content" class="form-control" row="3"></textarea>

​ 这样我们就可以通过 $scope.comment.content 来取值。

Angular track by

​ 在使用 Angular 的 ng-repeat 迭代数组时,有时候会出现 Duplicates in a repeater are not allowed 的提示。

​ track by 是用来建立 $watchCollection 和 DOM 之间的联系。建议自己加上 track by 后面带的值可以自己写,但要确保每个 ngRepeat 的值唯一,比如可以写 track by $index 。

​ 之所以要这么做,是因为,如果不使用 track by ,那么每个 ng-repeat 都会添加一个 $$hashkey 来对的 DOM 进行跟踪,这样会导致不能存在相同的 DOM ,使用 track by 的意义是避免不必要的渲染。

​ 官网API有进行详细的说明,不过我看了之后还是感觉不太明白,等我了解清楚了再来补充下。AngularJS: API: ngRepeat

If you are working with objects that have an identifier property, you should track by the identifier instead of the whole object. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this significantly improves rendering performance. If you don’t have a unique identifier, track by $index can also provide a performance boost.

Angular拦截器

​ Angular 拦截器是 Angular 的一个强大功能,不过暂时没有怎么去研究,简单说下我的一些使用。

阅读更多